Rust SGX SDK v0.2.0 release
diff --git a/LICENSE b/LICENSE
index 24c7cf2..281da4a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -66,12 +66,216 @@
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
+2. Rust Project
 
-2. compiler_rt
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
 
-The compiler_rt library is dual licensed under both the University of Illinois 
-"BSD-Like" license and the MIT license.  As a user of this code you may choose 
-to use it under either license.  As a contributor, you agree to allow your code 
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+3. compiler_rt
+
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license.  As a user of this code you may choose
+to use it under either license.  As a contributor, you agree to allow your code
 to be used under both.
 
 Full text of the relevant licenses is included below.
@@ -93,64 +297,64 @@
 
     http://llvm.org
 
-Permission is hereby granted, free of charge, to any person obtaining a copy of this 
-software and associated documentation files (the "Software"), to deal with the 
-Software without restriction, including without limitation the rights to use, 
-copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 
-Software, and to permit persons to whom the Software is furnished to do so, subject 
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal with the
+Software without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+Software, and to permit persons to whom the Software is furnished to do so, subject
 to the following conditions:
 
--	Redistributions of source code must retain the above copyright notice, 
+-	Redistributions of source code must retain the above copyright notice,
 this list of conditions and the following disclaimers.
 
--	Redistributions in binary form must reproduce the above copyright notice, 
-this list of conditions and the following disclaimers in the documentation and/or 
+-	Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimers in the documentation and/or
 other materials provided with the distribution.
 
--	Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, 
-nor the names of its contributors may be used to endorse or romote products derived 
+-	Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign,
+nor the names of its contributors may be used to endorse or romote products derived
 from this Software without specific prior written permission.
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
-PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE 
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 
-OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 DEALINGS WITH THE SOFTWARE.
 
 =============================================================================
 
 Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
 
-Permission is hereby granted, free of charge, to any person obtaining a copy of this 
-software and associated documentation files (the "Software"), to deal in the Software 
-without restriction, including without limitation the rights to use, copy, modify, merge, 
-publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
 to whom the Software is furnished to do so, subject to the following conditions:
 
-The above copyright notice and this permission notice shall be included in all copies or 
+The above copyright notice and this permission notice shall be included in all copies or
 substantial portions of the Software.
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
-PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
-FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 DEALINGS IN THE SOFTWARE.
 
 =============================================================================
 Copyrights and Licenses for Third Party Software Distributed with LLVM:
 =============================================================================
-The LLVM software contains code written by third parties.  Such software will have its 
+The LLVM software contains code written by third parties.  Such software will have its
 own individual LICENSE.TXT file in the directory in which it appears.
 This file will describe the copyrights, license, and restrictions which apply to that code.
 
-The disclaimer of warranty in the University of Illinois Open Source License applies to all 
-code in the LLVM Distribution, and nothing in any of the other licenses gives permission to 
-use the names of the LLVM Team or the University of Illinois to endorse or promote products 
+The disclaimer of warranty in the University of Illinois Open Source License applies to all
+code in the LLVM Distribution, and nothing in any of the other licenses gives permission to
+use the names of the LLVM Team or the University of Illinois to endorse or promote products
 derived from this Software.
 
-The following pieces of software have additional or alternate copyrights, licenses, and/or 
+The following pieces of software have additional or alternate copyrights, licenses, and/or
 restrictions:
 
 Program             Directory
@@ -159,7 +363,7 @@
 
 
 
-3. NetBSD
+4. NetBSD
 
 ===============================================================================================
 
@@ -168,7 +372,7 @@
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
- * by 
+ * by
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -194,30 +398,30 @@
 ________________________________________
 For complete copyright and licensing terms, see: http://www.netbsd.org/about/redistribution.html
 
- 
 
 
-4. OpenBSD
+
+5. OpenBSD
 
 http://openbsd.org/
 
 OpenBSD* Copyright Policy
 ________________________________________
 -	Goal
-Copyright law is complex, OpenBSD* policy is simple - OpenBSD strives to maintain the spirit 
+Copyright law is complex, OpenBSD* policy is simple - OpenBSD strives to maintain the spirit
 of the original Berkeley Unix copyrights.
-OpenBSD can exist as it does today because of the example set by the Computer Systems Research 
-Group at Berkeley and the battles which they and others fought to create a relatively 
+OpenBSD can exist as it does today because of the example set by the Computer Systems Research
+Group at Berkeley and the battles which they and others fought to create a relatively
 un-encumbered Unix source distribution.
-The ability of a freely redistributable "Berkeley" Unix to move forward on a competitive 
-basis with other operating systems depends on the willingness of the various development 
-groups to exchange code amongst themselves and with other projects. Understanding the legal 
-issues surrounding copyright is fundamental to the ability to exchange and re-distribute code, 
-while honoring the spirit of the copyright and concept of attribution is fundamental to 
+The ability of a freely redistributable "Berkeley" Unix to move forward on a competitive
+basis with other operating systems depends on the willingness of the various development
+groups to exchange code amongst themselves and with other projects. Understanding the legal
+issues surrounding copyright is fundamental to the ability to exchange and re-distribute code,
+while honoring the spirit of the copyright and concept of attribution is fundamental to
 promoting the cooperation of the people involved.
 -	The Berkeley* Copyright
-The Berkeley* copyright poses no restrictions on private or commercial use of the software 
-and imposes only simple and uniform requirements for maintaining copyright notices in 
+The Berkeley* copyright poses no restrictions on private or commercial use of the software
+and imposes only simple and uniform requirements for maintaining copyright notices in
 redistributed versions and crediting the originator of the material only in advertising.
 For instance:
  * Copyright (c) 1982, 1986, 1990, 1991, 1993
@@ -251,20 +455,20 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
-Berkeley rescinded the 3rd term (the advertising term) on 22 July 1999. Verbatim copies 
-of the Berkeley license in the OpenBSD tree have that term removed. In addition, many 
+Berkeley rescinded the 3rd term (the advertising term) on 22 July 1999. Verbatim copies
+of the Berkeley license in the OpenBSD tree have that term removed. In addition, many
 3rd-party BSD-style licenses consist solely of the first two terms.
-Because the OpenBSD copyright imposes no conditions beyond those imposed by the Berkeley 
-copyright, OpenBSD can hope to share the same wide distribution and applicability as the 
-Berkeley distributions. It follows however, that OpenBSD cannot include material which 
-includes copyrights which are more restrictive than the Berkeley copyright, or must 
-relegate this material to a secondary status, i.e. OpenBSD as a whole is freely 
+Because the OpenBSD copyright imposes no conditions beyond those imposed by the Berkeley
+copyright, OpenBSD can hope to share the same wide distribution and applicability as the
+Berkeley distributions. It follows however, that OpenBSD cannot include material which
+includes copyrights which are more restrictive than the Berkeley copyright, or must
+relegate this material to a secondary status, i.e. OpenBSD as a whole is freely
 redistributable, but some optional components may not be.
 -	Copyright Law
-While the overall subject of copyright law is far beyond the scope of this document, some 
-basics are in order. Under the current copyright law, copyrights are implicit in the 
-creation of a new work and reside with the creator, unless otherwise assigned. In general 
-the copyright applies only to the new work, not the material the work was derived from, 
+While the overall subject of copyright law is far beyond the scope of this document, some
+basics are in order. Under the current copyright law, copyrights are implicit in the
+creation of a new work and reside with the creator, unless otherwise assigned. In general
+the copyright applies only to the new work, not the material the work was derived from,
 nor those portions of the derivative material included in the new work.
 Copyright law admits to three general categories of works:
 Original Work
@@ -273,137 +477,137 @@
 Work that is derived from, includes or amends existing works.
 Compilations
 A work that is a compilation of existing new and derivative works.
-The fundamental concept is that there is primacy of the copyright, that is a copyright of a 
-derivative work does not affect the rights held by the owner of the copyright of the original 
-work, rather only the part added. Likewise the copyright of a compilation does not affect the 
+The fundamental concept is that there is primacy of the copyright, that is a copyright of a
+derivative work does not affect the rights held by the owner of the copyright of the original
+work, rather only the part added. Likewise the copyright of a compilation does not affect the
 rights of the owner of the included works, only the compilation as an entity.
-It is vitally important to understand that copyrights are broad protections as defined by 
-national and international copyright law. The "copyright notices" usually included in source 
-files are not copyrights, but rather notices that a party asserts that they hold copyright 
-to the material or to part of the material. Typically these notices are associated with 
-license terms which grant permissions subject to copyright law and with disclaimers that 
-state the position of the copyright holder/distributor with respect to liability surrounding 
+It is vitally important to understand that copyrights are broad protections as defined by
+national and international copyright law. The "copyright notices" usually included in source
+files are not copyrights, but rather notices that a party asserts that they hold copyright
+to the material or to part of the material. Typically these notices are associated with
+license terms which grant permissions subject to copyright law and with disclaimers that
+state the position of the copyright holder/distributor with respect to liability surrounding
 use of the material.
 -	Permissions - the flip side
-Because copyrights arise from the creation of a work, rather than through a registration process, 
-there needs to be a practical way to extend permission to use a work beyond what might be allowed 
+Because copyrights arise from the creation of a work, rather than through a registration process,
+there needs to be a practical way to extend permission to use a work beyond what might be allowed
 by "fair use" provisions of the copyright laws.
-This permission typically takes the form of a "release" or "license" included in the work, which 
-grants the additional uses beyond those granted by copyright law, usually subject to a variety of 
-conditions. At one extreme sits "public domain" where the originator asserts that he imposes no 
-restrictions on use of the material, at the other restrictive clauses that actually grant no 
-additional rights or impose restrictive, discriminatory or impractical conditions on use of the 
+This permission typically takes the form of a "release" or "license" included in the work, which
+grants the additional uses beyond those granted by copyright law, usually subject to a variety of
+conditions. At one extreme sits "public domain" where the originator asserts that he imposes no
+restrictions on use of the material, at the other restrictive clauses that actually grant no
+additional rights or impose restrictive, discriminatory or impractical conditions on use of the
 work.
-Again, an important point to note is that the release and conditions can only apply to the 
-portion of the work that was originated by the copyright holder - the holder of a copyright 
-on a derivative work can neither grant additional permissions for use of the original work, 
+Again, an important point to note is that the release and conditions can only apply to the
+portion of the work that was originated by the copyright holder - the holder of a copyright
+on a derivative work can neither grant additional permissions for use of the original work,
 nor impose more restrictive conditions for use of that work.
-Because copyright arises from the creation of a work and not the text or a registration process, 
-removing or altering a copyright notice or associated release terms has no bearing on the 
-existence of the copyright, rather all that is accomplished is to cast doubt upon whatever rights 
-the person making the modifications had to use the material in the first place. Likewise, adding 
-terms and conditions in conflict with the original terms and conditions does not supersede them, 
-rather it casts doubts on the rights of the person making the amendments to use the material and 
+Because copyright arises from the creation of a work and not the text or a registration process,
+removing or altering a copyright notice or associated release terms has no bearing on the
+existence of the copyright, rather all that is accomplished is to cast doubt upon whatever rights
+the person making the modifications had to use the material in the first place. Likewise, adding
+terms and conditions in conflict with the original terms and conditions does not supersede them,
+rather it casts doubts on the rights of the person making the amendments to use the material and
 creates confusion as to whether anyone can use the amended version or derivatives thereof.
-Finally, releases are generally binding on the material that they are distributed with. This means 
-that if the originator of a work distributes that work with a release granting certain permissions, 
-those permissions apply as stated, without discrimination, to all persons legitimately possessing 
-a copy of the work. That means that having granted a permission, the copyright holder can not 
-retroactively say that an individual or class of individuals are no longer granted those permissions. 
-Likewise should the copyright holder decide to "go commercial" he can not revoke permissions already 
-granted for the use of the work as distributed, though he may impose more restrictive permissions in 
+Finally, releases are generally binding on the material that they are distributed with. This means
+that if the originator of a work distributes that work with a release granting certain permissions,
+those permissions apply as stated, without discrimination, to all persons legitimately possessing
+a copy of the work. That means that having granted a permission, the copyright holder can not
+retroactively say that an individual or class of individuals are no longer granted those permissions.
+Likewise should the copyright holder decide to "go commercial" he can not revoke permissions already
+granted for the use of the work as distributed, though he may impose more restrictive permissions in
 his future distributions of that work.
 -	Specific Cases
-This section attempts to summarize the position of OpenBSD relative to some commonly encountered 
+This section attempts to summarize the position of OpenBSD relative to some commonly encountered
 copyrights.
 Berkeley*
-The Berkeley copyright is the model for the OpenBSD copyright. It retains the rights of the 
-copyright holder, while imposing minimal conditions on the use of the copyrighted material. 
-Material with Berkeley copyrights, or copyrights closely adhering to the Berkeley model can 
+The Berkeley copyright is the model for the OpenBSD copyright. It retains the rights of the
+copyright holder, while imposing minimal conditions on the use of the copyrighted material.
+Material with Berkeley copyrights, or copyrights closely adhering to the Berkeley model can
 generally be included in OpenBSD.
 AT&T*
-As part of its settlement with AT&T*, Berkeley included an AT&T copyright notice on some of the 
-files in 4.4BSD lite and lite2. The terms of this license are identical to the standard Berkeley 
+As part of its settlement with AT&T*, Berkeley included an AT&T copyright notice on some of the
+files in 4.4BSD lite and lite2. The terms of this license are identical to the standard Berkeley
 license.
-Additionally, OpenBSD includes some other AT&T code with non-restrictive copyrights, such as the 
+Additionally, OpenBSD includes some other AT&T code with non-restrictive copyrights, such as the
 reference implementation of awk.
 Caldera*
-Caldera* (now known as the SCO group) is the current owner of the Unix code copyrights. On 23 
-January 2002, the original Unix code (versions 1 through seven, including 32V) was freed by Caldera. 
-This code is now available under a 4-term BSD-style license. As a result, it is now possible to 
-incorporate real Unix code into OpenBSD (though this code is quite old and generally requires significant 
+Caldera* (now known as the SCO group) is the current owner of the Unix code copyrights. On 23
+January 2002, the original Unix code (versions 1 through seven, including 32V) was freed by Caldera.
+This code is now available under a 4-term BSD-style license. As a result, it is now possible to
+incorporate real Unix code into OpenBSD (though this code is quite old and generally requires significant
 changes to bring it up to date).
 DEC*, Sun*, other manufacturers/software houses.
-In general OpenBSD does not include material copyrighted by manufacturers or software houses. 
-Material may be included where the copyright owner has granted general permission for reuse 
-without conditions, with terms similar to the Berkeley copyright, or where the material is the 
-product of an employee and the employer's copyright notice effectively releases any rights they 
+In general OpenBSD does not include material copyrighted by manufacturers or software houses.
+Material may be included where the copyright owner has granted general permission for reuse
+without conditions, with terms similar to the Berkeley copyright, or where the material is the
+product of an employee and the employer's copyright notice effectively releases any rights they
 might have to the work.
 Carnegie-Mellon* (CMU, Mach)
-The Carnegie-Mellon copyright is similar to the Berkeley copyright, except that it requests that 
-derivative works be made available to Carnegie-Mellon. Because this is only a request and not a 
-condition, such material can still be included in OpenBSD. It should be noted that existing 
-versions of Mach are still subject to AT&T copyrights, which prevents the general distribution 
+The Carnegie-Mellon copyright is similar to the Berkeley copyright, except that it requests that
+derivative works be made available to Carnegie-Mellon. Because this is only a request and not a
+condition, such material can still be included in OpenBSD. It should be noted that existing
+versions of Mach are still subject to AT&T copyrights, which prevents the general distribution
 of Mach sources.
 Apache*
-The original Apache* copyright is similar to the Berkeley copyright, except that it stipulates 
-that products derived from the code may not have "Apache" in their name. The purpose of this 
-clause is to avoid a situation in which another party releases a modified version of the code 
-named in such a way to make users think that it is the "official" version. This is not an issue 
-with OpenBSD because OpenBSD is a Compilation, and not a Derived Work. Source code published under 
-version 2 of the Apache license cannot be included into OpenBSD. As a consequence, OpenBSD now 
-maintains its own version of Apache based on version 1.3.29. The OpenBSD version includes many 
+The original Apache* copyright is similar to the Berkeley copyright, except that it stipulates
+that products derived from the code may not have "Apache" in their name. The purpose of this
+clause is to avoid a situation in which another party releases a modified version of the code
+named in such a way to make users think that it is the "official" version. This is not an issue
+with OpenBSD because OpenBSD is a Compilation, and not a Derived Work. Source code published under
+version 2 of the Apache license cannot be included into OpenBSD. As a consequence, OpenBSD now
+maintains its own version of Apache based on version 1.3.29. The OpenBSD version includes many
 enhancements and bugfixes.
 ISC*
-The ISC* copyright is functionally equivalent to a two-term BSD copyright with language removed 
-that is made unnecessary by the Berne convention. This is the preferred license for new code 
-incorporated into OpenBSD. A sample license is included in the source tree as 
+The ISC* copyright is functionally equivalent to a two-term BSD copyright with language removed
+that is made unnecessary by the Berne convention. This is the preferred license for new code
+incorporated into OpenBSD. A sample license is included in the source tree as
 /usr/src/share/misc/license.template.
 GNU* General Public License, GPL, LGPL, copyleft, etc.
-The GNU* Public License and licenses modeled on it impose the restriction that source code must 
+The GNU* Public License and licenses modeled on it impose the restriction that source code must
 be distributed or made available for all works that are derivatives of the GNU copyrighted code.
-While this may be a noble strategy in terms of software sharing, it is a condition that is 
-typically unacceptable for commercial use of software. As a consequence, software bound by the 
+While this may be a noble strategy in terms of software sharing, it is a condition that is
+typically unacceptable for commercial use of software. As a consequence, software bound by the
 GPL terms can not be included in the kernel or "runtime" of OpenBSD, though software subject to
- GPL terms may be included as development tools or as part of the system that are "optional" as 
+ GPL terms may be included as development tools or as part of the system that are "optional" as
 long as such use does not result in OpenBSD as a whole becoming subject to the GPL terms.
-As an example, GCC and other GNU tools are included in the OpenBSD tool chain. However, it is 
-quite possible to distribute a system for many applications without a tool chain, or the 
-distributor can choose to include a tool chain as an optional bundle which conforms to the 
+As an example, GCC and other GNU tools are included in the OpenBSD tool chain. However, it is
+quite possible to distribute a system for many applications without a tool chain, or the
+distributor can choose to include a tool chain as an optional bundle which conforms to the
 GPL terms.
 NetBSD*
-Much of OpenBSD is originally based on and evolved from NetBSD*, since some of the OpenBSD 
-developers were involved in the NetBSD project. The general NetBSD license terms are compatible 
-with the Berkeley license and permit such use. Material subject only to the general NetBSD license 
+Much of OpenBSD is originally based on and evolved from NetBSD*, since some of the OpenBSD
+developers were involved in the NetBSD project. The general NetBSD license terms are compatible
+with the Berkeley license and permit such use. Material subject only to the general NetBSD license
 can generally be included in OpenBSD.
-In the past, NetBSD has included material copyrighted by individuals who have imposed license 
-conditions beyond that of the general NetBSD license, but granted the NetBSD Foundation license 
-to distribute the material. Such material can not be included in OpenBSD as long as the conditions 
-imposed are at odds with the OpenBSD license terms or releases from those terms are offered on a 
+In the past, NetBSD has included material copyrighted by individuals who have imposed license
+conditions beyond that of the general NetBSD license, but granted the NetBSD Foundation license
+to distribute the material. Such material can not be included in OpenBSD as long as the conditions
+imposed are at odds with the OpenBSD license terms or releases from those terms are offered on a
 discriminatory basis.
 FreeBSD*
-Most of FreeBSD* is also based on Berkeley licensed material or includes copyright notices based 
-on the Berkeley model. Such material can be included in OpenBSD, while those parts that are subject 
-to GPL or various individual copyright terms that are at odds with the OpenBSD license can not be 
+Most of FreeBSD* is also based on Berkeley licensed material or includes copyright notices based
+on the Berkeley model. Such material can be included in OpenBSD, while those parts that are subject
+to GPL or various individual copyright terms that are at odds with the OpenBSD license can not be
 included in OpenBSD.
 Linux*
-Most of Linux* is subject to GPL style licensing terms and therefore can not be included in 
-OpenBSD. Individual components may be eligible, subject to the terms of the originator's copyright 
-notices. Note that Linux "distributions" may also be subject to additional copyright claims of the 
-distributing organization, either as a compilation or on material included that is not part of the 
+Most of Linux* is subject to GPL style licensing terms and therefore can not be included in
+OpenBSD. Individual components may be eligible, subject to the terms of the originator's copyright
+notices. Note that Linux "distributions" may also be subject to additional copyright claims of the
+distributing organization, either as a compilation or on material included that is not part of the
 Linux core.
 X*, XFree86*, X.Org*
-X*, X.Org* or XFree86* are not parts of OpenBSD, rather X.Org and parts of XFree86 3.3.6 are 
-distributed with many OpenBSD ports as a convenience to the user, subject to applicable license 
+X*, X.Org* or XFree86* are not parts of OpenBSD, rather X.Org and parts of XFree86 3.3.6 are
+distributed with many OpenBSD ports as a convenience to the user, subject to applicable license
 terms.
 Shareware, Charityware, Freeware, etc.
-Most "shareware" copyright notices impose conditions for redistribution, use or visibility that 
-are at conflict with the OpenBSD project goals. Review on a case-by-case basis is required as to 
-whether the wording of the conditions is acceptable in terms of conditions being requested vs. 
+Most "shareware" copyright notices impose conditions for redistribution, use or visibility that
+are at conflict with the OpenBSD project goals. Review on a case-by-case basis is required as to
+whether the wording of the conditions is acceptable in terms of conditions being requested vs.
 demanded and whether the spirit of the conditions is compatible with goals of the OpenBSD project.
 Public Domain
-While material that is truly entered into the "Public Domain" can be included in OpenBSD, review 
-is required on a case by case basis. Frequently the "public domain" assertion is made by someone 
+While material that is truly entered into the "Public Domain" can be included in OpenBSD, review
+is required on a case by case basis. Frequently the "public domain" assertion is made by someone
 who does not really hold all rights under Copyright law to grant that status or there are a variety
-of conditions imposed on use. For a work to be truly in the "Public Domain" all rights are abandoned 
+of conditions imposed on use. For a work to be truly in the "Public Domain" all rights are abandoned
 and the material is offered without restrictions.
diff --git a/Readme.md b/Readme.md
index 4102dfc..5f40fd9 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,17 +1,23 @@
 # Rust SGX SDK
-This Rust SGX SDK helps developers write Intel SGX enclaves in Rust programming language. 
+This Rust SGX SDK helps developers write Intel SGX enclaves in Rust programming language.
+
+## v0.2.0 Release
+We are proud to have our v0.2.0 Rust SGX SDK released. It is now providing more threading functions, thread local storages, exception handling routines and supports unwind mechanism, as well as support of **LARGE ENCLAVE MEMORY** with the help of Intel SGX v1.9 (**31.75 GB enclave memory tested**). Please refer to [release notes](https://github.com/baidu/rust-sgx-sdk/blob/master/release_notes.md) for further details. And we are working on a white paper for technical details about this project.
+
+**Attention** Rust has recently merged a patch [(rustc: Implement the #[global_allocator] attribute)](https://github.com/rust-lang/rust/commit/695dee063bcd40f154bb27b7beafcb3d4dd775ac#diff-28f2fd684ad47d385427678d96d2dcd4) which significantly changes the behavior of liballoc. Thus `set_oom_handler` is no longer available since nightly-2017-07-07. Due to its instability, v0.2.0 Rust SGX SDK keeps using the old liballoc instead of new liballoc_system. As a result, nightly version rustc after 2017-07-06 will not successfully compile `sgx_trts`.
 
 ## Requirement
 Ubuntu 16.04
 
-[Intel SGX SDK 1.8 for Linux](https://01.org/zh/intel-softwareguard-extensions) installed
+[Intel SGX SDK 1.9 for Linux](https://01.org/zh/intel-softwareguard-extensions) installed
 
 Docker (Recommended)
 
+
 ## Configuration
 
 ### Using docker (Recommended)
-First, make sure Intel SGX Driver 1.8 is installed and functions well. `/dev/isgx` should be appeared.
+First, make sure Intel SGX Driver 1.9 is installed and functions well. `/dev/isgx` should be appeared.
 
 Second, pull the docker image
 
@@ -35,7 +41,7 @@
 
 ### Native without docker (Not recommended)
 
-Install Intel SGX driver and SDK first. And refer to Dockerfile for detail. 
+Install Intel SGX driver and SDK first. And refer to Dockerfile for detail.
 
 ## Build the docker image by yourself
 
@@ -66,16 +72,19 @@
 shows how to do local attestation in Rust programming language.
 
 * `sealeddata` sample shows how to seal secret data in an enclave and how to
-verify the sealed data. 
+verify the sealed data.
 
 * `thread` sample is a sample ported from the original Intel SGX SDK, showing
-some basic usages of threading APIs. 
+some basic usages of threading APIs.
 
 * New! `remoteattestation` sample shows how to make remote attestation with
 Rust SGX SDK. The sample is forked from [linux-sgx-attestation](https://github.com/svartkanin/linux-sgx-remoteattestation)
 and credits to Blackrabbit (blackrabbit256@gmail.com). The enclave in Rust
 is shipped in this sample and Makefiles are modified accordingly.
 
+* New! `hugemem` sample shows how to use huge mem in SGX enclave. In this
+sample, we allocate reserve 31.75GB heap space and allocate 31.625GB buffers!
+
 # Tips for writing enclaves in Rust
 
 ## Writing EDL
diff --git a/common/inc/complex.h b/common/inc/complex.h
index 7d92d63..93fe495 100644
--- a/common/inc/complex.h
+++ b/common/inc/complex.h
@@ -39,7 +39,7 @@
 #define I		_Complex_I
 
 __BEGIN_DECLS
-/* 
+/*
  * Double versions of C99 functions
  */
 double complex cacos(double complex);
@@ -69,7 +69,7 @@
  */
 double complex clog10(double complex);
 
-/* 
+/*
  * Float versions of C99 functions
  */
 float complex cacosf(float complex);
@@ -99,7 +99,7 @@
  */
 float complex clog10f(float complex);
 
-/* 
+/*
  * Long double versions of C99 functions
  */
 long double complex cacosl(long double complex);
diff --git a/common/inc/float.h b/common/inc/float.h
index 99ae58d..5ca839a 100644
--- a/common/inc/float.h
+++ b/common/inc/float.h
@@ -43,7 +43,7 @@
 #define FLT_ROUNDS      1        /* addition rounding: near */
 #define DECIMAL_DIG     21       /* max precision in decimal digits */
 
-// NOTE: FLT_EVAL_METHOD is -1 under FREEBSD x86. 
+// NOTE: FLT_EVAL_METHOD is -1 under FREEBSD x86.
 #ifdef __i386__
 #define FLT_EVAL_METHOD 2        /* long double */
 #else
diff --git a/common/inc/inttypes.h b/common/inc/inttypes.h
index c4fbcaf..fbc009c 100644
--- a/common/inc/inttypes.h
+++ b/common/inc/inttypes.h
@@ -70,7 +70,7 @@
 #ifdef __x86_64__
 #define PRIdMAX         "ld"    /* intmax_t */
 #else
-#if defined(__i386__) 
+#if defined(__i386__)
 #define PRIdMAX         "lld"   /* intmax_t */
 #else
 #define PRIdMAX         "jd"    /* intmax_t */
@@ -115,7 +115,7 @@
 #ifdef __x86_64__
 #define PRIiMAX         "li"    /* intmax_t */
 #else
-#if defined(__i386__) 
+#if defined(__i386__)
 #define PRIiMAX         "lli"   /* intmax_t */
 #else
 #define PRIiMAX         "ji"    /* intmax_t */
@@ -161,7 +161,7 @@
 #ifdef __x86_64__
 #define PRIoMAX         "lo"    /* intmax_t */
 #else
-#if defined(__i386__) 
+#if defined(__i386__)
 #define PRIoMAX         "llo"   /* intmax_t */
 #else
 #define PRIoMAX         "jo"    /* intmax_t */
@@ -209,7 +209,7 @@
 #ifdef __x86_64__
 #define PRIuMAX         "lu"    /* uintmax_t */
 #else
-#if defined(__i386__) 
+#if defined(__i386__)
 #define PRIuMAX         "llu"   /* uintmax_t */
 #else
 #define PRIuMAX         "ju"    /* uintmax_t */
@@ -254,7 +254,7 @@
 #ifdef __x86_64__
 #define PRIxMAX         "lx"    /* uintmax_t */
 #else
-#if defined(__i386__) 
+#if defined(__i386__)
 #define PRIxMAX         "llx"   /* uintmax_t */
 #else
 #define PRIxMAX         "jx"    /* uintmax_t */
@@ -300,7 +300,7 @@
 #ifdef __x86_64__
 #define PRIXMAX         "lX"    /* uintmax_t */
 #else
-#if defined(__i386__) 
+#if defined(__i386__)
 #define PRIXMAX         "llX"   /* uintmax_t */
 #else
 #define PRIXMAX         "jX"    /* uintmax_t */
diff --git a/common/inc/iso646.h b/common/inc/iso646.h
index d711cac..83feb52 100644
--- a/common/inc/iso646.h
+++ b/common/inc/iso646.h
@@ -1,7 +1,7 @@
 /*	$OpenBSD: iso646.h,v 1.3 2001/10/11 00:05:21 espie Exp $	*/
 /*	$NetBSD: iso646.h,v 1.1 1995/02/17 09:08:10 jtc Exp $	*/
 
-/* 
+/*
  * Written by J.T. Conklin <jtc@wimsey.com> 02/16/95.
  * Public domain.
  */
diff --git a/common/inc/math.h b/common/inc/math.h
index 104ac7f..870e784 100644
--- a/common/inc/math.h
+++ b/common/inc/math.h
@@ -5,7 +5,7 @@
  *
  * Developed at SunPro, a Sun Microsystems, Inc. business.
  * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice 
+ * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
  */
@@ -126,14 +126,14 @@
 double _TLIBC_CDECL_ asinh(double);
 double _TLIBC_CDECL_ atanh(double);
 
-double _TLIBC_CDECL_ exp2(double);  
+double _TLIBC_CDECL_ exp2(double);
 double _TLIBC_CDECL_ expm1(double);
 int    _TLIBC_CDECL_ ilogb(double);
 double _TLIBC_CDECL_ log1p(double);
 double _TLIBC_CDECL_ log2(double);
 double _TLIBC_CDECL_ logb(double);
 double _TLIBC_CDECL_ scalbn(double, int);
-double _TLIBC_CDECL_ scalbln(double, long int); 
+double _TLIBC_CDECL_ scalbln(double, long int);
 
 double _TLIBC_CDECL_ cbrt(double);
 double _TLIBC_CDECL_ hypot(double, double);
@@ -145,23 +145,23 @@
 
 double _TLIBC_CDECL_ nearbyint(double);
 double _TLIBC_CDECL_ rint(double);
-long int _TLIBC_CDECL_ lrint(double); 
-long long int _TLIBC_CDECL_ llrint(double); 
-double _TLIBC_CDECL_ round(double);  
-long int _TLIBC_CDECL_ lround(double); 
+long int _TLIBC_CDECL_ lrint(double);
+long long int _TLIBC_CDECL_ llrint(double);
+double _TLIBC_CDECL_ round(double);
+long int _TLIBC_CDECL_ lround(double);
 long long int _TLIBC_CDECL_ llround(double);
 double _TLIBC_CDECL_ trunc(double);
 
 double _TLIBC_CDECL_ remainder(double, double);
-double _TLIBC_CDECL_ remquo(double, double, int *); 
+double _TLIBC_CDECL_ remquo(double, double, int *);
 
 double _TLIBC_CDECL_ copysign(double, double);
 double _TLIBC_CDECL_ nan(const char *);
 double _TLIBC_CDECL_ nextafter(double, double);
 
-double _TLIBC_CDECL_ fdim(double, double); 
-double _TLIBC_CDECL_ fmax(double, double); 
-double _TLIBC_CDECL_ fmin(double, double); 
+double _TLIBC_CDECL_ fdim(double, double);
+double _TLIBC_CDECL_ fmax(double, double);
+double _TLIBC_CDECL_ fmin(double, double);
 
 double _TLIBC_CDECL_ fma(double, double, double);
 
@@ -185,8 +185,8 @@
 float _TLIBC_CDECL_ tanhf(float);
 
 float _TLIBC_CDECL_ expf(float);
-float _TLIBC_CDECL_ exp2f(float); 
-float _TLIBC_CDECL_ expm1f(float); 
+float _TLIBC_CDECL_ exp2f(float);
+float _TLIBC_CDECL_ expm1f(float);
 float _TLIBC_CDECL_ frexpf(float, int *);
 int   _TLIBC_CDECL_ ilogbf(float);
 float _TLIBC_CDECL_ ldexpf(float, int);
@@ -215,9 +215,9 @@
 float _TLIBC_CDECL_ nearbyintf(float);
 
 float _TLIBC_CDECL_ rintf(float);
-long int _TLIBC_CDECL_ lrintf(float); 
-long long int _TLIBC_CDECL_ llrintf(float); 
-float _TLIBC_CDECL_ roundf(float); 
+long int _TLIBC_CDECL_ lrintf(float);
+long long int _TLIBC_CDECL_ llrintf(float);
+float _TLIBC_CDECL_ roundf(float);
 long int _TLIBC_CDECL_ lroundf(float);
 long long int _TLIBC_CDECL_ llroundf(float);
 float _TLIBC_CDECL_ truncf(float);
@@ -311,9 +311,9 @@
 
 /* nexttoward():
 *      The implementation in Intel math library is incompatible with MSVC.
-*      Because sizeof(long double) is 8bytes with MSVC, 
-*      but the expected long double size is 10bytes. 
-*      And by default, MSVC doesn't provide nexttoward(). 
+*      Because sizeof(long double) is 8bytes with MSVC,
+*      but the expected long double size is 10bytes.
+*      And by default, MSVC doesn't provide nexttoward().
 *      So we only provide Linux version here.
 */
 double _TLIBC_CDECL_ nexttoward(double, long double);
@@ -344,7 +344,7 @@
 int _TLIBC_CDECL_ __isnormall(long double);
 int _TLIBC_CDECL_ __signbitl(long double);
 
-/* 
+/*
  * Non-C99 functions.
  */
 double _TLIBC_CDECL_ drem(double, double);
@@ -407,12 +407,12 @@
 int         _TLIBC_CDECL_ isinfl(long double);
 int         _TLIBC_CDECL_ isnanl(long double);
 
-/* 
+/*
  * TODO: From Intel Decimal Floating-Point Math Library
  * signbitd32/signbitd64/signbitd128, finited32/finited64/finited128
  * isinfd32/isinfd64/isinfd128, isnand32/isnand64/isnand128
  */
-#if defined(__cplusplus) 
+#if defined(__cplusplus)
 /* Clang does not support decimal floating point types.
  *
  * c.f.:
diff --git a/common/inc/setjmp.h b/common/inc/setjmp.h
index ac5627f..3ad2522 100644
--- a/common/inc/setjmp.h
+++ b/common/inc/setjmp.h
@@ -47,13 +47,13 @@
 #define	_BSD_JBSLOT_T_	long
 #endif
 
-#define _JBLEN 8 
+#define _JBLEN 8
 
 typedef _BSD_JBSLOT_T_ jmp_buf[_JBLEN] _JB_ATTRIBUTES;
 
 #include <sys/cdefs.h>
 #define __returns_twice __attribute__((__returns_twice__))
-#define __dead 
+#define __dead
 
 __BEGIN_DECLS
 int	_setjmp(jmp_buf) __returns_twice;
diff --git a/common/inc/string.h b/common/inc/string.h
index c8e458f..86d3cd2 100644
--- a/common/inc/string.h
+++ b/common/inc/string.h
@@ -87,7 +87,7 @@
 _TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, strcat, char *, const char *);
 _TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, strcpy, char *, const char *);
 
-/* 
+/*
  * Common used non-C99 functions.
  */
 char * _TLIBC_CDECL_ strndup(const char *, size_t);
diff --git a/common/inc/sys/_types.h b/common/inc/sys/_types.h
index b1b315c..5b42d16 100644
--- a/common/inc/sys/_types.h
+++ b/common/inc/sys/_types.h
@@ -66,7 +66,7 @@
 typedef unsigned long int   __uint_fast32_t;
 typedef long int            __int_fast64_t;
 typedef unsigned long int   __uint_fast64_t;
-#else 
+#else
 /* Android x86, and Linux x86 */
 typedef __int32_t           __int_fast16_t;
 typedef __uint32_t          __uint_fast16_t;
diff --git a/common/inc/sys/cdefs.h b/common/inc/sys/cdefs.h
index 398a12b..a6fdb58 100644
--- a/common/inc/sys/cdefs.h
+++ b/common/inc/sys/cdefs.h
@@ -47,7 +47,7 @@
 # define __END_DECLS
 #endif
 
-#if defined(__STDC__) || defined(__cplusplus) 
+#if defined(__STDC__) || defined(__cplusplus)
 # define __CONCAT(x,y)  x ## y
 # define __STRING(x)    #x
 #else
@@ -65,7 +65,7 @@
 #endif
 
 /* Calling Convention: cdecl */
-#define _TLIBC_CDECL_      
+#define _TLIBC_CDECL_
 
 /* Thread Directive */
 #define _TLIBC_THREAD_     /* __thread */
@@ -83,7 +83,7 @@
 #endif
 
 /* Static analysis for printf format strings.
- * _MSC_PRINTF_FORMAT_: MSVC SAL annotation for specifying format strings. 
+ * _MSC_PRINTF_FORMAT_: MSVC SAL annotation for specifying format strings.
  * _GCC_PRINTF_FORMAT_(x, y): GCC declaring attribute for checking format strings.
  *   x - index of the format string. In C++ non-static method, index 1 is reseved for 'this'.
  *   y - index of first variadic agrument in '...'.
diff --git a/common/inc/unistd.h b/common/inc/unistd.h
index 2958a6c..4da748a 100644
--- a/common/inc/unistd.h
+++ b/common/inc/unistd.h
@@ -43,7 +43,7 @@
 void * _TLIBC_CDECL_ sbrk(intptr_t);
 
 /*
- * Deprecated Non-C99. 
+ * Deprecated Non-C99.
  */
 _TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execl, const char *, const char *, ...);
 _TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execlp, const char *, const char *, ...);
diff --git a/dockerfile/Dockerfile b/dockerfile/Dockerfile
index 4ecd82e..c27d8ae 100644
--- a/dockerfile/Dockerfile
+++ b/dockerfile/Dockerfile
@@ -36,25 +36,23 @@
 RUN apt-get install -y build-essential ocaml automake autoconf libtool wget python libssl-dev libcurl4-openssl-dev protobuf-compiler libprotobuf-dev sudo kmod vim curl git-core libprotobuf-c0-dev libboost-thread-dev libboost-system-dev liblog4cpp5-dev libjsoncpp-dev
 
 RUN mkdir /root/sgx
-RUN wget -O /root/sgx/optimized_libs-1.8.100.37641.tar https://download.01.org/intel-sgx/linux-1.8/optimized_libs-1.8.100.37641.tar
-RUN wget -O /root/sgx/prebuilt-ae-1.8.100.37641.tar  https://download.01.org/intel-sgx/linux-1.8/prebuilt-ae-1.8.100.37641.tar
-RUN wget -O /root/sgx/sgx_linux_ubuntu16.04.1_x64_psw_1.8.100.37689.bin https://download.01.org/intel-sgx/linux-1.8/sgx_linux_ubuntu16.04.1_x64_psw_1.8.100.37689.bin
-RUN wget -O /root/sgx/sgx_linux_ubuntu16.04.1_x64_sdk_1.8.100.37689.bin https://download.01.org/intel-sgx/linux-1.8/sgx_linux_ubuntu16.04.1_x64_sdk_1.8.100.37689.bin
+RUN wget -O /root/sgx/optimized_libs-1.9.100.39124.tar https://download.01.org/intel-sgx/linux-1.9/optimized_libs-1.9.100.39124.tar
+RUN wget -O /root/sgx/prebuilt-ae-1.9.100.39124.tar  https://download.01.org/intel-sgx/linux-1.9/prebuilt-ae-1.9.100.39124.tar
+RUN wget -O /root/sgx/sgx_linux_ubuntu16.04.1_x64_psw_1.9.100.39124.bin https://download.01.org/intel-sgx/linux-1.9/sgx_linux_ubuntu16.04.1_x64_psw_1.9.100.39124.bin
+RUN wget -O /root/sgx/sgx_linux_ubuntu16.04.1_x64_sdk_1.9.100.39124.bin https://download.01.org/intel-sgx/linux-1.9/sgx_linux_ubuntu16.04.1_x64_sdk_1.9.100.39124.bin
 
-RUN chmod a+x /root/sgx/sgx_linux_ubuntu16.04.1_x64_psw_1.8.100.37689.bin
-RUN /root/sgx/sgx_linux_ubuntu16.04.1_x64_psw_1.8.100.37689.bin
-RUN chmod a+x /root/sgx/sgx_linux_ubuntu16.04.1_x64_sdk_1.8.100.37689.bin
-RUN echo -e 'no\n/opt' | /root/sgx/sgx_linux_ubuntu16.04.1_x64_sdk_1.8.100.37689.bin
+RUN chmod a+x /root/sgx/sgx_linux_ubuntu16.04.1_x64_psw_1.9.100.39124.bin
+RUN /root/sgx/sgx_linux_ubuntu16.04.1_x64_psw_1.9.100.39124.bin
+RUN chmod a+x /root/sgx/sgx_linux_ubuntu16.04.1_x64_sdk_1.9.100.39124.bin
+RUN echo -e 'no\n/opt' | /root/sgx/sgx_linux_ubuntu16.04.1_x64_sdk_1.9.100.39124.bin
 RUN echo 'source /opt/sgxsdk/environment' >> /root/.bashrc
 
-RUN wget 'https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init' -O /root/rustup-init
-RUN chmod +x /root/rustup-init
-RUN echo '1' | /root/rustup-init  --default-toolchain nightly
-RUN echo 'source /root/.cargo/env' >> /root/.bashrc
-
 RUN git clone https://github.com/01org/linux-sgx.git /root/linux-sgx
 ADD patch /root/
 RUN cd /root/linux-sgx && git apply ../patch
 RUN /root/linux-sgx/download_prebuilt.sh
 RUN cd /root/linux-sgx && make
 RUN cp /root/linux-sgx/build/linux/libsgx_tstdc.a /opt/sgxsdk/lib64/libsgx_tstdc.a
+
+RUN wget https://static.rust-lang.org/rustup.sh
+RUN sh rustup.sh --channel=nightly --date=2017-07-06
diff --git a/dockerfile/patch b/dockerfile/patch
index 28b17ef..99d0e7f 100644
--- a/dockerfile/patch
+++ b/dockerfile/patch
@@ -3,11 +3,11 @@
 --- a/sdk/tlibc/Makefile
 +++ b/sdk/tlibc/Makefile
 @@ -33,7 +33,7 @@ include ../../buildenv.mk
- 
+
  CFLAGS   += $(ENCLAVE_CFLAGS)
  ASFLAGS  := $(CFLAGS)
 -CFLAGS   += -std=c99
 +CFLAGS   += -std=c99 -D USE_MALLOC_DEPRECATED
  CXXFLAGS += $(ENCLAVE_CXXFLAGS) -fno-exceptions -fno-rtti
- 
+
  CPPFLAGS += -I.                          \
diff --git a/release_docs/whitepaper.md b/release_docs/whitepaper.md
deleted file mode 100644
index e69de29..0000000
--- a/release_docs/whitepaper.md
+++ /dev/null
diff --git a/release_notes.md b/release_notes.md
index 30d3831..4871351 100644
--- a/release_notes.md
+++ b/release_notes.md
@@ -1,42 +1,39 @@
-# Rust SGX SDK v0.1.0
+# Rust SGX SDK v0.2.0
 
 ## Introduction
-Baidu X-Lab provides Rust SGX SDK, to help develop Intel SGX enclaves in Rust
-programming language.
 
-### Contents
-
-* Basic Rust SGX SDK libraries
-* A patch to solve Rust's floating point compatibility issue.
-* Sample enclave codes.
-* A well-configured [docker image](https://hub.docker.com/r/baiduxlab/sgx-rust/).
-
-Please refer to our white paper for details.
+Baidu X-Lab provides Rust SGX SDK v0.2.0, to help develop Intel SGX enclaves in Rust programming language.
 
 ## What's New
 
-* Support for the latest Intel SGX SDK v1.8 for Linux.
-* Support for the latest Rust nightly build (1.18.0-nightly (c58c928e6 2017-04-11)).
-* Rust style document.
-
-## System Requirements
-
-* Ubuntu 16.04 LTS
-* [Hardware platform supports Intel SGX](https://github.com/ayeks/SGX-hardware)
-* Docker (Strongly recommended)
-* Rust nightly (Tested on rustc 1.18.0-nightly (c58c928e6 2017-04-11))
+* **Support for huge enclave memory (31.75 GB tested).** Please configure higher upper limit of heap size in Enclave.config.xml. The new [hugemem sample](https://github.com/baidu/rust-sgx-sdk/tree/master/samplecode/hugemem) is tested with Linux 16.04 + Xeon E3 1280 V5 + 64 GB memory.
+* Support for newer Rust nightly build (rust version 1.20.0-nightly (nightly-2017-07-06).
+* Support for the latest Intel SGX SDK v1.9.
+* More support of error codes, SGX data structures, API functions.
+* New trait `BytewiseEquality`, which means the equality of two corresponding object can be calculated by memory compare functions.
+* New trait `ContiguousMemory`, which means the corresponding object takes up contiguous memory region. This is important to Intel SGX programming. Many APIs are re-designed to use this new trait.
+* Support exception handling: `catch_unwind`, `panik` and `poisoning`.
+* Add a customized implementation of Rust oom (Out-of-memory) exception handling routine. Developer can use `sgx_trts::rsgx_oom` to catch and memory allocation exceptions and unwind safely.
+* More threading support. Now `park()` and `unpark()` are available for threading.
+* Add support for Thread Local Storage. Currently the Thread Local Storage is only provided to enclave enforced "Bound TCS" policy.
+* Add support for Rust style `Once` call.
+* Add support for global data, using new macro `init_global_object`. Global data could be initiated dynamically on the first ECALL.
+* Add support for Read-write lock (`sgx_tstdc::rwlock`).
+* Add support for spinlock (`sgx_tstdc::spinlock`).
+* Add support for CPUID (`rsgx_cpuid`).
+* Add constant time memory compare API `consttime_memequal` for crypto use.
+* Add API support for `sgx_get_ps_sec_prop_ex` in `sgx_tservice`.
 
 ## Known Issues and Limitations
 
-* Rust stable branch is unsupported.
 * `cargo test` is unsupported.
+* Rust-style backtrace on unexpected error is unsupported.
+* Rust has recently merged a patch [(rustc: Implement the #[global_allocator] attribute)](https://github.com/rust-lang/rust/commit/695dee063bcd40f154bb27b7beafcb3d4dd775ac#diff-28f2fd684ad47d385427678d96d2dcd4) which significantly changes the behavior of liballoc. Thus `set_oom_handler` is no longer available since nightly-2017-07-07. Due to its instability, v0.2.0 Rust SGX SDK keeps using the old liballoc instead of new liballoc_system. As a result, nightly version rustc after 2017-07-06 will not successfully compile `sgx_trts`.
+* For Thread Local Storage variables in "Bound TCS" enclave, destructors can be defined/implemented but never invoked automatically on thread's death.
 
-## Unstable APIs
+## Coming up in future
 
-* `rsgx_get_thread_data`
+* More sample codes and a whitepaper.
+* Upcoming module `sgx_urts` will provide untrusted part support. Developer can write untrusted codes and create enclave in Rust.
+* Port [rustls](https://github.com/ctz/rustls) into SGX enclave.
 
-* `rsgx_get_enclave_base`
-
-* `rsgx_get_heap_base`
-
-* `rsgx_get_heap_size`
diff --git a/samplecode/crypto/Makefile b/samplecode/crypto/Makefile
index 94edfff..4042699 100644
--- a/samplecode/crypto/Makefile
+++ b/samplecode/crypto/Makefile
@@ -86,7 +86,7 @@
 App_C_Files := $(wildcard ./app/*.c)
 App_Include_Paths := -I ./app -I./include -I$(SGX_SDK)/include
 App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths)
-App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread 
+App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread
 ifneq ($(SGX_MODE), HW)
 	App_Link_Flags += -lsgx_uae_service_sim
 else
@@ -158,7 +158,7 @@
 	@$(CC) $(RustEnclave_Compile_Flags) -c $< -o $@
 	@echo "CC   <=  $<"
 
-$(RustEnclave_Name): enclave compiler-rt enclave/Enclave_t.o 
+$(RustEnclave_Name): enclave compiler-rt enclave/Enclave_t.o
 	cp ./enclave/target/release/libCryptosampleenclave.a ./lib/libenclave.a
 	cp ../../compiler-rt/libcompiler-rt-patch.a ./lib
 	@$(CXX) enclave/Enclave_t.o -o $@ $(RustEnclave_Link_Flags)
@@ -171,7 +171,7 @@
 .PHONY: enclave
 enclave:
 	$(MAKE) -C ./enclave/
-	
+
 .PHONY: compiler-rt
 compiler-rt:
 	$(MAKE) -C ../../compiler-rt/ 2> /dev/null
@@ -180,4 +180,4 @@
 clean:
 	@rm -f $(App_Name) $(RustEnclave_Name) $(Signed_RustEnclave_Name) $(RustEnclave_C_Objects) $(App_C_Objects) enclave/*_t.* app/*_u.* lib/*.a
 	@cd enclave && cargo clean && rm -f Cargo.lock
-	
+
diff --git a/samplecode/crypto/app/app.c b/samplecode/crypto/app/app.c
index fb576ec..af20aa6 100644
--- a/samplecode/crypto/app/app.c
+++ b/samplecode/crypto/app/app.c
@@ -113,7 +113,7 @@
             break;
         }
     }
-    
+
     if (idx == ttl)
         printf("Error: Unexpected error occurred.\n");
 }
@@ -129,14 +129,14 @@
     sgx_launch_token_t token = {0};
     sgx_status_t ret = SGX_ERROR_UNEXPECTED;
     int updated = 0;
-    
-    /* Step 1: try to retrieve the launch token saved by last transaction 
+
+    /* Step 1: try to retrieve the launch token saved by last transaction
      *         if there is no token, then create a new one.
      */
     /* try to get the token saved in $HOME */
     const char *home_dir = getpwuid(getuid())->pw_dir;
-    
-    if (home_dir != NULL && 
+
+    if (home_dir != NULL &&
         (strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) {
         /* compose the token path */
         strncpy(token_path, home_dir, strlen(home_dir));
@@ -196,7 +196,7 @@
     uint32_t sealed_log_size = 1024;
     uint8_t sealed_log[1024] = {0};
     sgx_sealed_data_t * sealed_data = 0;
-    
+
     (void)(argc);
     (void)(argv);
 
@@ -204,13 +204,13 @@
     if(initialize_enclave() < 0){
         printf("Enter a character before exit ...\n");
         getchar();
-        return -1; 
+        return -1;
     }
 
     // SHA-256 test case comes from
     // https://tools.ietf.org/html/rfc4634
     // TEST1
-    
+
     const char* str = "abc";
     size_t len = strlen(str);
     uint8_t * output_hash = (uint8_t *) malloc (32 + 1);
@@ -219,9 +219,9 @@
     printf("[+] Expected SHA256 hash: %s\n",
            "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
 
-    sgx_ret = calc_sha256(global_eid, 
-                         &enclave_ret, 
-                         (const uint8_t *) str, 
+    sgx_ret = calc_sha256(global_eid,
+                         &enclave_ret,
+                         (const uint8_t *) str,
                          len,
                          output_hash);
 
@@ -259,7 +259,7 @@
     printf("[+] aes-gcm-128 expected ciphertext: %s\n",
            "0388dace60b6a392f328c2b971b2fe78");
     sgx_ret = aes_gcm_128_encrypt(global_eid,
-                                  &enclave_ret,                      
+                                  &enclave_ret,
                                   aes_gcm_key,
                                   aes_gcm_plaintext,
                                   16,
@@ -293,7 +293,7 @@
 
     printf("[+] Starting aes-gcm-128 decrypt calculation\n");
     printf("[+] aes-gcm-128 expected plaintext: %s", aes_gcm_plaintext);
-    
+
     uint8_t aes_gcm_decrypted_text[16] = {0};
     sgx_ret = aes_gcm_128_decrypt(global_eid,
                                   &enclave_ret,
@@ -371,7 +371,7 @@
 
     /* Destroy the enclave */
     sgx_destroy_enclave(global_eid);
-    
+
     return 0;
 }
 
@@ -382,7 +382,7 @@
         printf("malloc failed\n");
         return;
     }
-    
+
     memcpy(string, str, len);
     char * ptr = string + len;
     * ptr = 0;
diff --git a/samplecode/crypto/enclave/Cargo.toml b/samplecode/crypto/enclave/Cargo.toml
index 394019d..4165e57 100644
--- a/samplecode/crypto/enclave/Cargo.toml
+++ b/samplecode/crypto/enclave/Cargo.toml
@@ -13,4 +13,5 @@
 
 [dependencies]
 sgx_types = { path = "../../../sgx_types" }
+sgx_trts = { path = "../../../sgx_trts" }
 sgx_tcrypto = { path = "../../../sgx_tcrypto" }
diff --git a/samplecode/crypto/enclave/Enclave.edl b/samplecode/crypto/enclave/Enclave.edl
index 50bec35..f2c2209 100644
--- a/samplecode/crypto/enclave/Enclave.edl
+++ b/samplecode/crypto/enclave/Enclave.edl
@@ -1,9 +1,9 @@
 enclave {
-	
+
     trusted {
         /* define ECALLs here. */
-		
-        public sgx_status_t calc_sha256([in, size=len] const uint8_t* input_str, 
+
+        public sgx_status_t calc_sha256([in, size=len] const uint8_t* input_str,
                                         size_t len,
                                         [out] uint8_t hash[32]);
 
@@ -27,10 +27,10 @@
                                      [out] uint8_t cmac[16]);
 
     };
-    
+
     untrusted {
         void ocall_print_string([in, size=len] const char *str, size_t len);
     };
 
- 
+
 };
diff --git a/samplecode/crypto/enclave/Makefile b/samplecode/crypto/enclave/Makefile
index ec1512d..145950c 100644
--- a/samplecode/crypto/enclave/Makefile
+++ b/samplecode/crypto/enclave/Makefile
@@ -5,5 +5,5 @@
 
 all: $(Rust_Enclave_Name)
 
-$(Rust_Enclave_Name): $(Rust_Enclave_Files)  
+$(Rust_Enclave_Name): $(Rust_Enclave_Files)
 	cargo build --release
diff --git a/samplecode/crypto/enclave/src/lib.rs b/samplecode/crypto/enclave/src/lib.rs
index 7b7073c..8c9cc2e 100644
--- a/samplecode/crypto/enclave/src/lib.rs
+++ b/samplecode/crypto/enclave/src/lib.rs
@@ -8,6 +8,7 @@
 extern crate collections;
 
 extern crate sgx_types;
+extern crate sgx_trts;
 extern crate sgx_tcrypto;
 
 use sgx_types::*;
@@ -268,7 +269,7 @@
 /// # Errors
 ///
 /// **SGX_ERROR_INVALID_PARAMETER** Indicates the parameter is invalid.
-/// 
+///
 /// **SGX_ERROR_UNEXPECTED** means that decryption failed.
 ///
 /// # Requirements
diff --git a/samplecode/helloworld/Makefile b/samplecode/helloworld/Makefile
index 7549846..440f3e6 100644
--- a/samplecode/helloworld/Makefile
+++ b/samplecode/helloworld/Makefile
@@ -86,7 +86,7 @@
 App_C_Files := $(wildcard ./app/*.c)
 App_Include_Paths := -I ./app -I./include -I$(SGX_SDK)/include
 App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths)
-App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread 
+App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread
 ifneq ($(SGX_MODE), HW)
 	App_Link_Flags += -lsgx_uae_service_sim
 else
@@ -158,7 +158,7 @@
 	@$(CC) $(RustEnclave_Compile_Flags) -c $< -o $@
 	@echo "CC   <=  $<"
 
-$(RustEnclave_Name): enclave compiler-rt enclave/Enclave_t.o 
+$(RustEnclave_Name): enclave compiler-rt enclave/Enclave_t.o
 	cp ./enclave/target/release/libhelloworldsampleenclave.a ./lib/libenclave.a
 	cp ../../compiler-rt/libcompiler-rt-patch.a ./lib
 	@$(CXX) enclave/Enclave_t.o -o $@ $(RustEnclave_Link_Flags)
@@ -171,7 +171,7 @@
 .PHONY: enclave
 enclave:
 	$(MAKE) -C ./enclave/
-	
+
 .PHONY: compiler-rt
 compiler-rt:
 	$(MAKE) -C ../../compiler-rt/ 2> /dev/null
@@ -180,4 +180,4 @@
 clean:
 	@rm -f $(App_Name) $(RustEnclave_Name) $(Signed_RustEnclave_Name) $(RustEnclave_C_Objects) $(App_C_Objects) enclave/*_t.* app/*_u.* lib/*.a
 	@cd enclave && cargo clean && rm -f Cargo.lock
-	
+
diff --git a/samplecode/helloworld/app/app.c b/samplecode/helloworld/app/app.c
index de309ab..c0f3517 100644
--- a/samplecode/helloworld/app/app.c
+++ b/samplecode/helloworld/app/app.c
@@ -113,7 +113,7 @@
             break;
         }
     }
-    
+
     if (idx == ttl)
         printf("Error: Unexpected error occurred.\n");
 }
@@ -129,14 +129,14 @@
     sgx_launch_token_t token = {0};
     sgx_status_t ret = SGX_ERROR_UNEXPECTED;
     int updated = 0;
-    
-    /* Step 1: try to retrieve the launch token saved by last transaction 
+
+    /* Step 1: try to retrieve the launch token saved by last transaction
      *         if there is no token, then create a new one.
      */
     /* try to get the token saved in $HOME */
     const char *home_dir = getpwuid(getuid())->pw_dir;
-    
-    if (home_dir != NULL && 
+
+    if (home_dir != NULL &&
         (strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) {
         /* compose the token path */
         strncpy(token_path, home_dir, strlen(home_dir));
@@ -196,7 +196,7 @@
     uint32_t sealed_log_size = 1024;
     uint8_t sealed_log[1024] = {0};
     sgx_sealed_data_t * sealed_data = 0;
-	
+
     (void)(argc);
     (void)(argv);
 
@@ -204,15 +204,15 @@
     if(initialize_enclave() < 0){
         printf("Enter a character before exit ...\n");
         getchar();
-        return -1; 
+        return -1;
     }
- 	
+
     const char* str = "This is c str passed into enclave!";
     size_t len = strlen(str);
 
-    sgx_ret = say_something(global_eid, 
-	                        &enclave_ret, 
-							(const uint8_t *) str, 
+    sgx_ret = say_something(global_eid,
+	                        &enclave_ret,
+							(const uint8_t *) str,
 							len);
 
     if(sgx_ret != SGX_SUCCESS) {
@@ -229,7 +229,7 @@
 
     /* Destroy the enclave */
     sgx_destroy_enclave(global_eid);
-    
+
     return 0;
 }
 
@@ -240,7 +240,7 @@
     	printf("malloc failed\n");
     	return;
     }
-    
+
     memcpy(string, str, len);
     char * ptr = string + len;
     * ptr = 0;
diff --git a/samplecode/helloworld/enclave/Cargo.toml b/samplecode/helloworld/enclave/Cargo.toml
index 1469edc..4b9e38e 100644
--- a/samplecode/helloworld/enclave/Cargo.toml
+++ b/samplecode/helloworld/enclave/Cargo.toml
@@ -13,4 +13,4 @@
 
 [dependencies]
 sgx_types = { path = "../../../sgx_types" }
-sgx_tstdc = { path = "../../../sgx_tstdc" }
+sgx_trts = { path = "../../../sgx_trts" }
diff --git a/samplecode/helloworld/enclave/Enclave.edl b/samplecode/helloworld/enclave/Enclave.edl
index 45e1e59..4a08022 100644
--- a/samplecode/helloworld/enclave/Enclave.edl
+++ b/samplecode/helloworld/enclave/Enclave.edl
@@ -1,14 +1,14 @@
 enclave {
-	
+
     trusted {
         /* define ECALLs here. */
-		
+
         public sgx_status_t say_something([in, size=len] const uint8_t* some_string, size_t len);
     };
-    
+
     untrusted {
         void ocall_print_string([in, size=len] const char *str, size_t len);
     };
 
- 
+
 };
diff --git a/samplecode/helloworld/enclave/Makefile b/samplecode/helloworld/enclave/Makefile
index ec1512d..145950c 100644
--- a/samplecode/helloworld/enclave/Makefile
+++ b/samplecode/helloworld/enclave/Makefile
@@ -5,5 +5,5 @@
 
 all: $(Rust_Enclave_Name)
 
-$(Rust_Enclave_Name): $(Rust_Enclave_Files)  
+$(Rust_Enclave_Name): $(Rust_Enclave_Files)
 	cargo build --release
diff --git a/samplecode/helloworld/enclave/src/lib.rs b/samplecode/helloworld/enclave/src/lib.rs
index c36d200..7f66b50 100644
--- a/samplecode/helloworld/enclave/src/lib.rs
+++ b/samplecode/helloworld/enclave/src/lib.rs
@@ -8,6 +8,7 @@
 extern crate collections;
 
 extern crate sgx_types;
+extern crate sgx_trts;
 
 use sgx_types::*;
 use collections::string::String;
diff --git a/samplecode/hugemem/Makefile b/samplecode/hugemem/Makefile
new file mode 100644
index 0000000..778f83b
--- /dev/null
+++ b/samplecode/hugemem/Makefile
@@ -0,0 +1,183 @@
+#
+# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#   * Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+#   * Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.
+#   * Neither the name of Intel Corporation nor the names of its
+#     contributors may be used to endorse or promote products derived
+#     from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+######## SGX SDK Settings ########
+
+SGX_SDK ?= /opt/intel/sgxsdk
+SGX_MODE ?= HW
+SGX_ARCH ?= x64
+
+ifeq ($(shell getconf LONG_BIT), 32)
+	SGX_ARCH := x86
+else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32)
+	SGX_ARCH := x86
+endif
+
+ifeq ($(SGX_ARCH), x86)
+	SGX_COMMON_CFLAGS := -m32
+	SGX_LIBRARY_PATH := $(SGX_SDK)/lib
+	SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign
+	SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r
+else
+	SGX_COMMON_CFLAGS := -m64
+	SGX_LIBRARY_PATH := $(SGX_SDK)/lib64
+	SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign
+	SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r
+endif
+
+ifeq ($(SGX_DEBUG), 1)
+ifeq ($(SGX_PRERELEASE), 1)
+$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!)
+endif
+endif
+
+
+ifeq ($(SGX_DEBUG), 1)
+	SGX_COMMON_CFLAGS += -O0 -g
+else
+	SGX_COMMON_CFLAGS += -O2
+endif
+
+######## CUSTOM Settings ########
+
+CUSTOM_LIBRARY_PATH := ./lib
+CUSTOM_BIN_PATH := ./bin
+
+######## EDL Settings ########
+
+Enclave_EDL_Files := enclave/Enclave_t.c enclave/Enclave_t.h app/Enclave_u.c app/Enclave_u.h
+
+######## APP Settings ########
+
+ifneq ($(SGX_MODE), HW)
+	Urts_Library_Name := sgx_urts_sim
+else
+	Urts_Library_Name := sgx_urts
+endif
+
+App_C_Files := $(wildcard ./app/*.c)
+App_Include_Paths := -I ./app -I./include -I$(SGX_SDK)/include
+App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths)
+App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread
+ifneq ($(SGX_MODE), HW)
+	App_Link_Flags += -lsgx_uae_service_sim
+else
+	App_Link_Flags += -lsgx_uae_service
+endif
+
+App_C_Objects := $(App_C_Files:.c=.o)
+
+App_Name := bin/app
+
+######## Enclave Settings ########
+
+ifneq ($(SGX_MODE), HW)
+	Trts_Library_Name := sgx_trts_sim
+	Service_Library_Name := sgx_tservice_sim
+else
+	Trts_Library_Name := sgx_trts
+	Service_Library_Name := sgx_tservice
+endif
+Crypto_Library_Name := sgx_tcrypto
+KeyExchange_Library_Name := sgx_tkey_exchange
+
+RustEnclave_C_Files := $(wildcard ./enclave/*.c)
+RustEnclave_C_Objects := $(RustEnclave_C_Files:.c=.o)
+RustEnclave_Include_Paths := -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport -I$(SGX_SDK)/include/epid -I ./enclave -I./include
+
+RustEnclave_Link_Libs := -L$(CUSTOM_LIBRARY_PATH) -lcompiler-rt-patch -lenclave
+RustEnclave_Compile_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(RustEnclave_Include_Paths)
+RustEnclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \
+	-Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \
+	-Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -l$(Crypto_Library_Name) -l$(KeyExchange_Library_Name) -l$(Service_Library_Name) $(RustEnclave_Link_Libs) -Wl,--end-group \
+	-Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \
+	-Wl,-pie,-eenclave_entry -Wl,--export-dynamic  \
+	-Wl,--defsym,__ImageBase=0 \
+	-Wl,--gc-sections \
+	-Wl,--version-script=enclave/Enclave.lds
+
+
+RustEnclave_Name := enclave/enclave.so
+Signed_RustEnclave_Name := bin/enclave.signed.so
+
+.PHONY: all
+all: $(Enclave_EDL_Files) $(App_Name) $(Signed_RustEnclave_Name)
+
+######## EDL Objects ########
+
+$(Enclave_EDL_Files): $(SGX_EDGER8R) enclave/Enclave.edl
+	$(SGX_EDGER8R) --trusted enclave/Enclave.edl --search-path $(SGX_SDK)/include --trusted-dir enclave
+	$(SGX_EDGER8R) --untrusted enclave/Enclave.edl --search-path $(SGX_SDK)/include --untrusted-dir app
+	@echo "GEN  =>  $(Enclave_EDL_Files)"
+
+######## App Objects ########
+
+app/Enclave_u.o: app/Enclave_u.c
+	@$(CC) $(App_C_Flags) -c $< -o $@
+	@echo "CC   <=  $<"
+
+app/%.o: app/%.c
+	@$(CXX) $(App_C_Flags) -c $< -o $@
+	@echo "CXX  <=  $<"
+
+$(App_Name): app/Enclave_u.o $(App_C_Objects)
+	@$(CXX) $^ -o $@ $(App_Link_Flags)
+	@echo "LINK =>  $@"
+
+######## Enclave Objects ########
+
+enclave/Enclave_t.o: enclave/Enclave_t.c
+	@$(CC) $(RustEnclave_Compile_Flags) -c $< -o $@
+	@echo "CC   <=  $<"
+
+$(RustEnclave_Name): enclave compiler-rt enclave/Enclave_t.o
+	cp ./enclave/target/release/libhugememsampleenclave.a ./lib/libenclave.a
+	cp ../../compiler-rt/libcompiler-rt-patch.a ./lib
+	@$(CXX) enclave/Enclave_t.o -o $@ $(RustEnclave_Link_Flags)
+	@echo "LINK =>  $@"
+
+$(Signed_RustEnclave_Name): $(RustEnclave_Name)
+	@$(SGX_ENCLAVE_SIGNER) sign -key enclave/Enclave_private.pem -enclave $(RustEnclave_Name) -out $@ -config enclave/Enclave.config.xml
+	@echo "SIGN =>  $@"
+
+.PHONY: enclave
+enclave:
+	$(MAKE) -C ./enclave/
+
+.PHONY: compiler-rt
+compiler-rt:
+	$(MAKE) -C ../../compiler-rt/ 2> /dev/null
+
+.PHONY: clean
+clean:
+	@rm -f $(App_Name) $(RustEnclave_Name) $(Signed_RustEnclave_Name) $(RustEnclave_C_Objects) $(App_C_Objects) enclave/*_t.* app/*_u.* lib/*.a
+	@cd enclave && cargo clean && rm -f Cargo.lock
+
diff --git a/samplecode/hugemem/app/app.c b/samplecode/hugemem/app/app.c
new file mode 100644
index 0000000..c0f3517
--- /dev/null
+++ b/samplecode/hugemem/app/app.c
@@ -0,0 +1,249 @@
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <unistd.h>
+#include <pwd.h>
+#define MAX_PATH FILENAME_MAX
+
+#include "sgx_urts.h"
+#include "sgx_tseal.h"
+#include "app.h"
+#include "Enclave_u.h"
+
+
+sgx_enclave_id_t global_eid = 0;
+
+typedef struct _sgx_errlist_t {
+    sgx_status_t err;
+    const char *msg;
+    const char *sug; /* Suggestion */
+} sgx_errlist_t;
+
+/* Error code returned by sgx_create_enclave */
+static sgx_errlist_t sgx_errlist[] = {
+    {
+        SGX_ERROR_UNEXPECTED,
+        "Unexpected error occurred.",
+        NULL
+    },
+    {
+        SGX_ERROR_INVALID_PARAMETER,
+        "Invalid parameter.",
+        NULL
+    },
+    {
+        SGX_ERROR_OUT_OF_MEMORY,
+        "Out of memory.",
+        NULL
+    },
+    {
+        SGX_ERROR_ENCLAVE_LOST,
+        "Power transition occurred.",
+        "Please refer to the sample \"PowerTransition\" for details."
+    },
+    {
+        SGX_ERROR_INVALID_ENCLAVE,
+        "Invalid enclave image.",
+        NULL
+    },
+    {
+        SGX_ERROR_INVALID_ENCLAVE_ID,
+        "Invalid enclave identification.",
+        NULL
+    },
+    {
+        SGX_ERROR_INVALID_SIGNATURE,
+        "Invalid enclave signature.",
+        NULL
+    },
+    {
+        SGX_ERROR_OUT_OF_EPC,
+        "Out of EPC memory.",
+        NULL
+    },
+    {
+        SGX_ERROR_NO_DEVICE,
+        "Invalid SGX device.",
+        "Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards."
+    },
+    {
+        SGX_ERROR_MEMORY_MAP_CONFLICT,
+        "Memory map conflicted.",
+        NULL
+    },
+    {
+        SGX_ERROR_INVALID_METADATA,
+        "Invalid enclave metadata.",
+        NULL
+    },
+    {
+        SGX_ERROR_DEVICE_BUSY,
+        "SGX device was busy.",
+        NULL
+    },
+    {
+        SGX_ERROR_INVALID_VERSION,
+        "Enclave version was invalid.",
+        NULL
+    },
+    {
+        SGX_ERROR_INVALID_ATTRIBUTE,
+        "Enclave was not authorized.",
+        NULL
+    },
+    {
+        SGX_ERROR_ENCLAVE_FILE_ACCESS,
+        "Can't open enclave file.",
+        NULL
+    },
+};
+
+/* Check error conditions for loading enclave */
+void print_error_message(sgx_status_t ret)
+{
+    size_t idx = 0;
+    size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0];
+
+    for (idx = 0; idx < ttl; idx++) {
+        if(ret == sgx_errlist[idx].err) {
+            if(NULL != sgx_errlist[idx].sug)
+                printf("Info: %s\n", sgx_errlist[idx].sug);
+            printf("Error: %s\n", sgx_errlist[idx].msg);
+            break;
+        }
+    }
+
+    if (idx == ttl)
+        printf("Error: Unexpected error occurred.\n");
+}
+
+/* Initialize the enclave:
+ *   Step 1: try to retrieve the launch token saved by last transaction
+ *   Step 2: call sgx_create_enclave to initialize an enclave instance
+ *   Step 3: save the launch token if it is updated
+ */
+int initialize_enclave(void)
+{
+    char token_path[MAX_PATH] = {'\0'};
+    sgx_launch_token_t token = {0};
+    sgx_status_t ret = SGX_ERROR_UNEXPECTED;
+    int updated = 0;
+
+    /* Step 1: try to retrieve the launch token saved by last transaction
+     *         if there is no token, then create a new one.
+     */
+    /* try to get the token saved in $HOME */
+    const char *home_dir = getpwuid(getuid())->pw_dir;
+
+    if (home_dir != NULL &&
+        (strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) {
+        /* compose the token path */
+        strncpy(token_path, home_dir, strlen(home_dir));
+        strncat(token_path, "/", strlen("/"));
+        strncat(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)+1);
+    } else {
+        /* if token path is too long or $HOME is NULL */
+        strncpy(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME));
+    }
+
+    FILE *fp = fopen(token_path, "rb");
+    if (fp == NULL && (fp = fopen(token_path, "wb")) == NULL) {
+        printf("Warning: Failed to create/open the launch token file \"%s\".\n", token_path);
+    }
+
+    if (fp != NULL) {
+        /* read the token from saved file */
+        size_t read_num = fread(token, 1, sizeof(sgx_launch_token_t), fp);
+        if (read_num != 0 && read_num != sizeof(sgx_launch_token_t)) {
+            /* if token is invalid, clear the buffer */
+            memset(&token, 0x0, sizeof(sgx_launch_token_t));
+            printf("Warning: Invalid launch token read from \"%s\".\n", token_path);
+        }
+    }
+    /* Step 2: call sgx_create_enclave to initialize an enclave instance */
+    /* Debug Support: set 2nd parameter to 1 */
+    ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL);
+    if (ret != SGX_SUCCESS) {
+        print_error_message(ret);
+        if (fp != NULL) fclose(fp);
+        return -1;
+    }
+    printf("[+] global_eid: %ld\n", global_eid);
+
+    /* Step 3: save the launch token if it is updated */
+    if (updated == FALSE || fp == NULL) {
+        /* if the token is not updated, or file handler is invalid, do not perform saving */
+        if (fp != NULL) fclose(fp);
+        return 0;
+    }
+
+    /* reopen the file with write capablity */
+    fp = freopen(token_path, "wb", fp);
+    if (fp == NULL) return 0;
+    size_t write_num = fwrite(token, 1, sizeof(sgx_launch_token_t), fp);
+    if (write_num != sizeof(sgx_launch_token_t))
+        printf("Warning: Failed to save launch token to \"%s\".\n", token_path);
+    fclose(fp);
+    return 0;
+}
+
+/* Application entry */
+int SGX_CDECL main(int argc, char *argv[])
+{
+    sgx_status_t sgx_ret = SGX_SUCCESS;
+    sgx_status_t enclave_ret = SGX_SUCCESS;
+    uint32_t sealed_log_size = 1024;
+    uint8_t sealed_log[1024] = {0};
+    sgx_sealed_data_t * sealed_data = 0;
+
+    (void)(argc);
+    (void)(argv);
+
+    /* Initialize the enclave */
+    if(initialize_enclave() < 0){
+        printf("Enter a character before exit ...\n");
+        getchar();
+        return -1;
+    }
+
+    const char* str = "This is c str passed into enclave!";
+    size_t len = strlen(str);
+
+    sgx_ret = say_something(global_eid,
+	                        &enclave_ret,
+							(const uint8_t *) str,
+							len);
+
+    if(sgx_ret != SGX_SUCCESS) {
+        print_error_message(sgx_ret);
+        return -1;
+    }
+
+    if(enclave_ret != SGX_SUCCESS) {
+        print_error_message(enclave_ret);
+        return -1;
+    }
+
+    printf("[+] say_something success ...\n");
+
+    /* Destroy the enclave */
+    sgx_destroy_enclave(global_eid);
+
+    return 0;
+}
+
+void ocall_print_string(const char *str, size_t len)
+{
+    char * string = (char *)malloc(len + (size_t)sizeof(char));
+    if (string == NULL) {
+    	printf("malloc failed\n");
+    	return;
+    }
+
+    memcpy(string, str, len);
+    char * ptr = string + len;
+    * ptr = 0;
+    printf("%s\n", string);
+    free(string);
+}
diff --git a/samplecode/hugemem/app/app.h b/samplecode/hugemem/app/app.h
new file mode 100644
index 0000000..8ec36fb
--- /dev/null
+++ b/samplecode/hugemem/app/app.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#ifndef _APP_H_
+#define _APP_H_
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "sgx_error.h"       /* sgx_status_t */
+#include "sgx_eid.h"     /* sgx_enclave_id_t */
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define TOKEN_FILENAME   "enclave.token"
+#define ENCLAVE_FILENAME "enclave.signed.so"
+
+extern sgx_enclave_id_t global_eid;    /* global enclave id */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* !_APP_H_ */
diff --git a/samplecode/hugemem/bin/readme.txt b/samplecode/hugemem/bin/readme.txt
new file mode 100644
index 0000000..c5e82d7
--- /dev/null
+++ b/samplecode/hugemem/bin/readme.txt
@@ -0,0 +1 @@
+bin
\ No newline at end of file
diff --git a/samplecode/hugemem/enclave/Cargo.toml b/samplecode/hugemem/enclave/Cargo.toml
new file mode 100644
index 0000000..a37c12b
--- /dev/null
+++ b/samplecode/hugemem/enclave/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "Hugememsampleenclave"
+version = "0.1.0"
+authors = ["Baidu"]
+
+[lib]
+name = "hugememsampleenclave"
+crate-type = ["staticlib"]
+
+[features]
+default = []
+use_std = []
+
+[dependencies]
+sgx_types = { path = "../../../sgx_types" }
+sgx_trts = { path = "../../../sgx_trts" }
diff --git a/samplecode/hugemem/enclave/Enclave.config.xml b/samplecode/hugemem/enclave/Enclave.config.xml
new file mode 100644
index 0000000..a3c1f72
--- /dev/null
+++ b/samplecode/hugemem/enclave/Enclave.config.xml
@@ -0,0 +1,12 @@
+<!-- Please refer to User's Guide for the explanation of each field -->
+<EnclaveConfiguration>
+  <ProdID>0</ProdID>
+  <ISVSVN>0</ISVSVN>
+  <StackMaxSize>0x40000</StackMaxSize>
+  <HeapMaxSize>0x7F0000000</HeapMaxSize>
+  <TCSNum>1</TCSNum>
+  <TCSPolicy>1</TCSPolicy>
+  <DisableDebug>0</DisableDebug>
+  <MiscSelect>0</MiscSelect>
+  <MiscMask>0xFFFFFFFF</MiscMask>
+</EnclaveConfiguration>
diff --git a/samplecode/hugemem/enclave/Enclave.edl b/samplecode/hugemem/enclave/Enclave.edl
new file mode 100644
index 0000000..4a08022
--- /dev/null
+++ b/samplecode/hugemem/enclave/Enclave.edl
@@ -0,0 +1,14 @@
+enclave {
+
+    trusted {
+        /* define ECALLs here. */
+
+        public sgx_status_t say_something([in, size=len] const uint8_t* some_string, size_t len);
+    };
+
+    untrusted {
+        void ocall_print_string([in, size=len] const char *str, size_t len);
+    };
+
+
+};
diff --git a/samplecode/hugemem/enclave/Enclave.lds b/samplecode/hugemem/enclave/Enclave.lds
new file mode 100644
index 0000000..eb09b70
--- /dev/null
+++ b/samplecode/hugemem/enclave/Enclave.lds
@@ -0,0 +1,9 @@
+libTestEnclave.so
+{
+    global:
+        g_global_data_sim;
+        g_global_data;
+        enclave_entry;
+    local:
+        *;
+};
diff --git a/samplecode/hugemem/enclave/Enclave_private.pem b/samplecode/hugemem/enclave/Enclave_private.pem
new file mode 100644
index 0000000..529d07b
--- /dev/null
+++ b/samplecode/hugemem/enclave/Enclave_private.pem
@@ -0,0 +1,39 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ
+AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ
+ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr
+nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b
+3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H
+ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD
+5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW
+KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC
+1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe
+K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z
+AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q
+ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6
+JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826
+5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02
+wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9
+osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm
+WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i
+Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9
+xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd
+vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD
+Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a
+cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC
+0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ
+gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo
+gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t
+k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz
+Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6
+O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5
+afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom
+e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G
+BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv
+fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN
+t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9
+yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp
+6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg
+WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH
+NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk=
+-----END RSA PRIVATE KEY-----
diff --git a/samplecode/hugemem/enclave/Makefile b/samplecode/hugemem/enclave/Makefile
new file mode 100644
index 0000000..145950c
--- /dev/null
+++ b/samplecode/hugemem/enclave/Makefile
@@ -0,0 +1,9 @@
+Rust_Enclave_Name := libenclave.a
+Rust_Enclave_Files := $(wildcard src/*.rs)
+
+.PHONY: all
+
+all: $(Rust_Enclave_Name)
+
+$(Rust_Enclave_Name): $(Rust_Enclave_Files)
+	cargo build --release
diff --git a/samplecode/hugemem/enclave/src/lib.rs b/samplecode/hugemem/enclave/src/lib.rs
new file mode 100644
index 0000000..f20f9a1
--- /dev/null
+++ b/samplecode/hugemem/enclave/src/lib.rs
@@ -0,0 +1,124 @@
+#![crate_name = "hugememsampleenclave"]
+#![crate_type = "staticlib"]
+
+#![no_std]
+#![feature(collections)]
+
+#[macro_use]
+extern crate collections;
+
+extern crate sgx_types;
+extern crate sgx_trts;
+
+use sgx_types::*;
+use collections::string::String;
+use collections::vec::Vec;
+
+/// The Ocall declared in Enclave.edl and implemented in app.c
+///
+/// # Parameters
+///
+/// **str**
+///
+/// A pointer to the string to be printed
+///
+/// **len**
+///
+/// An unsigned int indicates the length of str
+///
+/// # Return value
+///
+/// None
+extern "C" {
+    fn ocall_print_string(str: *const c_uchar, len: size_t);
+}
+
+/// A function simply invokes ocall print to print the incoming string
+///
+/// # Parameters
+///
+/// **some_string**
+///
+/// A pointer to the string to be printed
+///
+/// **len**
+///
+/// An unsigned int indicates the length of str
+///
+/// # Return value
+///
+/// Always returns SGX_SUCCESS
+#[no_mangle]
+pub extern "C" fn say_something(some_string: *const u8, some_len: u32) -> sgx_status_t {
+    unsafe {
+        ocall_print_string(some_string as *const c_uchar, some_len as size_t);
+    }
+
+    // A sample &'static string
+    let rust_raw_string = "This is a ";
+    // An array
+    let word:[u8;4] = [82, 117, 115, 116];
+    // An vector
+    let word_vec:Vec<u8> = vec![32, 115, 116, 114, 105, 110, 103, 33];
+
+    // Construct a string from &'static string
+    let mut hello_string = String::from(rust_raw_string);
+
+    // Iterate on word array
+    for c in word.iter() {
+        hello_string.push(*c as char);
+    }
+
+    // Rust style convertion
+    hello_string += String::from_utf8(word_vec).expect("Invalid UTF-8")
+                                               .as_str();
+
+    // Ocall to normal world for output
+    unsafe {
+        ocall_print_string(hello_string.as_ptr() as *const c_uchar,
+                           hello_string.len() as size_t);
+    }
+
+    let mut sum:u64 = 0;
+    let mut vv:Vec<Vec<u8>> = Vec::new();
+    let mut onev:Vec<u8>; // 1Mbyte
+    let testblocksize:usize = 128 * 1024 * 1024; // 128Mbyte
+    let total = 0x7E8000000 ; // 31.625 GB = rounddown (31.75 GB - essential costs)
+
+    for i in 0..total / testblocksize{
+        onev = Vec::with_capacity(testblocksize); // 128Mbyte
+        for j in 0..testblocksize {
+            onev.push(((j as u32) % 256) as u8);
+        }
+        vv.push(onev);
+        sum += testblocksize as u64;
+        let outstr = format!("{}th allocate {} vec sum = {} bytes", i, testblocksize, sum);
+        unsafe {
+            ocall_print_string(outstr.as_ptr() as *const c_uchar,
+                               outstr.len() as size_t);
+        }
+    }
+
+    hello_string = String::from("Checking for values in allocated memory");
+
+    unsafe {
+        ocall_print_string(hello_string.as_ptr() as *const c_uchar,
+                           hello_string.len() as size_t);
+    }
+    
+    for i in 0..total / testblocksize{
+        for j in 0..testblocksize {
+            if vv[i][j] != ((j as u32) % 256) as u8 {
+                return sgx_status_t::SGX_ERROR_UNEXPECTED;
+            }
+        }
+    }
+
+    hello_string = String::from("All check success!");
+    unsafe {
+        ocall_print_string(hello_string.as_ptr() as *const c_uchar,
+                           hello_string.len() as size_t);
+    }
+
+    sgx_status_t::SGX_SUCCESS
+}
diff --git a/samplecode/hugemem/lib/readme.txt b/samplecode/hugemem/lib/readme.txt
new file mode 100644
index 0000000..7951405
--- /dev/null
+++ b/samplecode/hugemem/lib/readme.txt
@@ -0,0 +1 @@
+lib
\ No newline at end of file
diff --git a/samplecode/localattestation/Makefile b/samplecode/localattestation/Makefile
index a9a4276..1a89fa6 100644
--- a/samplecode/localattestation/Makefile
+++ b/samplecode/localattestation/Makefile
@@ -83,7 +83,7 @@
 App_Cpp_Files := $(wildcard ./app/*.cpp)
 App_Include_Paths := -I ./app -I./include -I$(SGX_SDK)/include -I./attestation -I./Include
 App_Cpp_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths)
-App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread 
+App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread
 ifneq ($(SGX_MODE), HW)
 	App_Link_Flags += -lsgx_uae_service_sim
 else
@@ -136,7 +136,7 @@
 
 ######## EDL Objects ########
 
-$(Enclave_EDL_Files): $(SGX_EDGER8R) enclave1/Enclave1.edl enclave2/Enclave2.edl enclave3/Enclave3.edl 
+$(Enclave_EDL_Files): $(SGX_EDGER8R) enclave1/Enclave1.edl enclave2/Enclave2.edl enclave3/Enclave3.edl
 	$(SGX_EDGER8R) --use-prefix --trusted enclave1/Enclave1.edl --search-path $(SGX_SDK)/include --trusted-dir enclave1
 	$(SGX_EDGER8R) --use-prefix --untrusted enclave1/Enclave1.edl --search-path $(SGX_SDK)/include --untrusted-dir app
 
@@ -184,7 +184,7 @@
 $(RustEnclave1_Name): enclave1 compiler-rt enclave1/Enclave1_t.o
 	cp ./enclave1/target/release/libenclave1.a ./lib
 	cp ../../compiler-rt/libcompiler-rt-patch.a ./lib
-	@$(CXX) enclave1/Enclave1_t.o -o $@ $(RustEnclave_Link_Libs) -lenclave1 $(RustEnclave_Link_Flags) 
+	@$(CXX) enclave1/Enclave1_t.o -o $@ $(RustEnclave_Link_Libs) -lenclave1 $(RustEnclave_Link_Flags)
 	@echo "LINK =>  $@"
 
 $(Signed_RustEnclave1_Name): $(RustEnclave1_Name)
@@ -201,7 +201,7 @@
 $(RustEnclave2_Name): enclave2 compiler-rt enclave2/Enclave2_t.o
 	cp ./enclave2/target/release/libenclave2.a ./lib
 	cp ../../compiler-rt/libcompiler-rt-patch.a ./lib
-	@$(CXX) enclave2/Enclave2_t.o -o $@ $(RustEnclave_Link_Libs) -lenclave2 $(RustEnclave_Link_Flags) 
+	@$(CXX) enclave2/Enclave2_t.o -o $@ $(RustEnclave_Link_Libs) -lenclave2 $(RustEnclave_Link_Flags)
 	@echo "LINK =>  $@"
 
 $(Signed_RustEnclave2_Name): $(RustEnclave2_Name)
@@ -217,7 +217,7 @@
 $(RustEnclave3_Name): enclave3 compiler-rt enclave3/Enclave3_t.o
 	cp ./enclave3/target/release/libenclave3.a ./lib
 	cp ../../compiler-rt/libcompiler-rt-patch.a ./lib
-	@$(CXX) enclave3/Enclave3_t.o -o $@ $(RustEnclave_Link_Libs) -lenclave3 $(RustEnclave_Link_Flags) 
+	@$(CXX) enclave3/Enclave3_t.o -o $@ $(RustEnclave_Link_Libs) -lenclave3 $(RustEnclave_Link_Flags)
 	@echo "LINK =>  $@"
 
 $(Signed_RustEnclave3_Name): $(RustEnclave3_Name)
@@ -227,20 +227,23 @@
 .PHONY: enclave1
 enclave1:
 	$(MAKE) -C ./enclave1/
-	
+
 .PHONY: enclave2
 enclave2:
 	$(MAKE) -C ./enclave2/
-	
+
 .PHONY: enclave3
 enclave3:
 	$(MAKE) -C ./enclave3/
-	
+
 .PHONY: compiler-rt
 compiler-rt:
 	$(MAKE) -C ../../compiler-rt/ 2> /dev/null
-	
+
 .PHONY: clean
 clean:
 	@rm -f $(App_Name) $(RustEnclave1_Name) $(Signed_RustEnclave1_Name) $(RustEnclave2_Name) $(Signed_RustEnclave2_Name) $(RustEnclave3_Name) $(Signed_RustEnclave3_Name) $(RustEnclave_C_Objects) $(App_Cpp_Objects) enclave1/*_t.* enclave2/*_t.* enclave3/*_t.* app/*_u.* lib/*.a
-	
+	@cd enclave1 && cargo clean && rm -f Cargo.lock
+	@cd enclave2 && cargo clean && rm -f Cargo.lock
+	@cd enclave3 && cargo clean && rm -f Cargo.lock
+	@cd attestation && cargo clean && rm -f Cargo.lock
diff --git a/samplecode/localattestation/app/App.cpp b/samplecode/localattestation/app/App.cpp
index c147436..2abbeb6 100644
--- a/samplecode/localattestation/app/App.cpp
+++ b/samplecode/localattestation/app/App.cpp
@@ -70,7 +70,7 @@
     	printf("malloc failed\n");
     	return;
     }
-    
+
     memcpy(string, str, len);
     char * ptr = string + len;
     * ptr = 0;
@@ -127,7 +127,7 @@
     {
         printf("\nLoad Enclave Failure");
     }
-    
+
     do
     {
         Enclave1_test_enclave_init(e1_enclave_id);
@@ -292,7 +292,7 @@
         }
 
 #pragma warning (push)
-#pragma warning (disable : 4127)    
+#pragma warning (disable : 4127)
     }while(0);
 #pragma warning (pop)
 
diff --git a/samplecode/localattestation/app/UntrustedEnclaveMessageExchange.cpp b/samplecode/localattestation/app/UntrustedEnclaveMessageExchange.cpp
index b703b3f..d045419 100644
--- a/samplecode/localattestation/app/UntrustedEnclaveMessageExchange.cpp
+++ b/samplecode/localattestation/app/UntrustedEnclaveMessageExchange.cpp
@@ -70,7 +70,7 @@
 			ret = Enclave3_session_request(dest_enclave_id, &status, src_enclave_id, dh_msg1, &session_ptr);
 			break;
 	}
-	if (ret == SGX_SUCCESS) 
+	if (ret == SGX_SUCCESS)
 	{
 		std::map<sgx_enclave_id_t, std::map<sgx_enclave_id_t, size_t> >::iterator it_ptr = g_session_ptr_map.find(dest_enclave_id);
 		if(it_ptr != g_session_ptr_map.end())
@@ -86,7 +86,7 @@
 
 		return (ATTESTATION_STATUS)status;
 	}
-	else	
+	else
 	    return INVALID_SESSION;
 
 }
@@ -136,7 +136,7 @@
 	}
 	if (ret == SGX_SUCCESS)
 		return (ATTESTATION_STATUS)status;
-	else	
+	else
 	    return INVALID_SESSION;
 
 }
@@ -185,9 +185,9 @@
 			ret = Enclave3_end_session(dest_enclave_id, &status, src_enclave_id, (size_t*)session_ptr);
 			break;
 	}
-	if (ret == SGX_SUCCESS) 
+	if (ret == SGX_SUCCESS)
 		return (ATTESTATION_STATUS)status;
-	else	
+	else
 	    return INVALID_SESSION;
 
 }
diff --git a/samplecode/localattestation/attestation/attestation.edl b/samplecode/localattestation/attestation/attestation.edl
index f5f0cda..7ddbef6 100644
--- a/samplecode/localattestation/attestation/attestation.edl
+++ b/samplecode/localattestation/attestation/attestation.edl
@@ -28,14 +28,14 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  */
- 
+
 enclave  {
     include "sgx_eid.h"
     include "sgx_dh.h"
     trusted{
         public uint32_t session_request(sgx_enclave_id_t src_enclave_id, [out] sgx_dh_msg1_t *dh_msg1, [out] size_t* session_ptr);
         public uint32_t exchange_report(sgx_enclave_id_t src_enclave_id, [in] sgx_dh_msg2_t *dh_msg2, [out] sgx_dh_msg3_t *dh_msg3, [user_check]size_t* session_ptr);
-        public uint32_t end_session(sgx_enclave_id_t src_enclave_id, [user_check]size_t* session_ptr);        
+        public uint32_t end_session(sgx_enclave_id_t src_enclave_id, [user_check]size_t* session_ptr);
     };
 
     untrusted{
diff --git a/samplecode/localattestation/attestation/src/err.rs b/samplecode/localattestation/attestation/src/err.rs
index ffc00f2..bb66836 100644
--- a/samplecode/localattestation/attestation/src/err.rs
+++ b/samplecode/localattestation/attestation/src/err.rs
@@ -48,4 +48,4 @@
         DUPLICATE_SESSION       = 0xEF,
         UNKNOWN_ERROR           = 0xF0,
     }
-}
\ No newline at end of file
+}
diff --git a/samplecode/localattestation/attestation/src/func.rs b/samplecode/localattestation/attestation/src/func.rs
index 1edc498..e38b24a 100644
--- a/samplecode/localattestation/attestation/src/func.rs
+++ b/samplecode/localattestation/attestation/src/func.rs
@@ -38,19 +38,19 @@
 use err::*;
 
 extern {
-    pub fn session_request_ocall(ret: *mut u32, 
-                                 src_enclave_id: sgx_enclave_id_t, 
-                                 dest_enclave_id: sgx_enclave_id_t, 
+    pub fn session_request_ocall(ret: *mut u32,
+                                 src_enclave_id: sgx_enclave_id_t,
+                                 dest_enclave_id: sgx_enclave_id_t,
                                  dh_msg1: *mut sgx_dh_msg1_t) -> sgx_status_t;
 
-    pub fn exchange_report_ocall(ret: *mut u32, 
-                                 src_enclave_id: sgx_enclave_id_t, 
-                                 dest_enclave_id: sgx_enclave_id_t, 
-                                 dh_msg2: *mut sgx_dh_msg2_t, 
+    pub fn exchange_report_ocall(ret: *mut u32,
+                                 src_enclave_id: sgx_enclave_id_t,
+                                 dest_enclave_id: sgx_enclave_id_t,
+                                 dh_msg2: *mut sgx_dh_msg2_t,
                                  dh_msg3: *mut sgx_dh_msg3_t) -> sgx_status_t;
 
-    pub fn end_session_ocall(ret: *mut u32, 
-                             src_enclave_id:sgx_enclave_id_t, 
+    pub fn end_session_ocall(ret: *mut u32,
+                             src_enclave_id:sgx_enclave_id_t,
                              dest_enclave_id:sgx_enclave_id_t) -> sgx_status_t;
 
     pub fn ocall_print_string(str: *const c_uchar, len: size_t);
@@ -83,7 +83,7 @@
     let mut ret = 0;
 
     let mut initiator: SgxDhInitiator = SgxDhInitiator::init_session();
-    
+
     let status = unsafe { session_request_ocall(&mut ret, src_enclave_id, dest_enclave_id, &mut dh_msg1) };
     if status != sgx_status_t::SGX_SUCCESS {
         return ATTESTATION_STATUS::ATTESTATION_SE_ERROR;
@@ -140,7 +140,7 @@
 }
 
 fn session_request_safe(src_enclave_id: sgx_enclave_id_t, dh_msg1: &mut sgx_dh_msg1_t, session_ptr: &mut usize) -> ATTESTATION_STATUS {
-    
+
     let mut responder = SgxDhResponder::init_session();
 
     let status = responder.gen_msg1(dh_msg1);
@@ -163,7 +163,7 @@
 pub extern "C" fn session_request(src_enclave_id: sgx_enclave_id_t, dh_msg1: *mut sgx_dh_msg1_t, session_ptr: *mut usize) -> ATTESTATION_STATUS {
     unsafe {
         session_request_safe(src_enclave_id, &mut *dh_msg1, &mut *session_ptr)
-    }    
+    }
 }
 
 #[allow(unused_variables)]
@@ -204,7 +204,7 @@
 pub extern "C" fn exchange_report(src_enclave_id: sgx_enclave_id_t, dh_msg2: *mut sgx_dh_msg2_t , dh_msg3: *mut sgx_dh_msg3_t, session_ptr: *mut usize) -> ATTESTATION_STATUS {
     unsafe {
         exchange_report_safe(src_enclave_id, &mut *dh_msg2, &mut *dh_msg3, &mut *(session_ptr as *mut DhSessionInfo))
-    }  
+    }
 }
 
 //Respond to the request from the Source Enclave to close the session
@@ -215,9 +215,9 @@
     return ATTESTATION_STATUS::SUCCESS;
 }
 
-#[allow(dead_code)] 
+#[allow(dead_code)]
 fn output(outstr: &str) {
     unsafe {
         ocall_print_string(outstr.as_ptr() as *const c_uchar, outstr.len() as size_t);
     }
-}
\ No newline at end of file
+}
diff --git a/samplecode/localattestation/attestation/src/lib.rs b/samplecode/localattestation/attestation/src/lib.rs
index ff0e4a0..d5beeaf 100644
--- a/samplecode/localattestation/attestation/src/lib.rs
+++ b/samplecode/localattestation/attestation/src/lib.rs
@@ -48,4 +48,4 @@
 pub use self::types::*;
 
 pub mod func;
-pub use self::func::*;
\ No newline at end of file
+pub use self::func::*;
diff --git a/samplecode/localattestation/attestation/src/types.rs b/samplecode/localattestation/attestation/src/types.rs
index 0392a44..01dd131 100644
--- a/samplecode/localattestation/attestation/src/types.rs
+++ b/samplecode/localattestation/attestation/src/types.rs
@@ -27,7 +27,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 use sgx_types::*;
-use sgx_tdh::dh::*;
+use sgx_tdh::*;
 
 use core::default::Default;
 
@@ -86,4 +86,4 @@
 pub struct DhSessionInfo {
     pub enclave_id: sgx_enclave_id_t,
     pub session: DhSession,
-}
\ No newline at end of file
+}
diff --git a/samplecode/localattestation/enclave1/Enclave1.config.xml b/samplecode/localattestation/enclave1/Enclave1.config.xml
index 942b839..36465f4 100644
--- a/samplecode/localattestation/enclave1/Enclave1.config.xml
+++ b/samplecode/localattestation/enclave1/Enclave1.config.xml
@@ -1,11 +1,11 @@
-<EnclaveConfiguration> 
-  <ProdID>0</ProdID> 
-  <ISVSVN>0</ISVSVN> 
-  <StackMaxSize>0x40000</StackMaxSize> 
-  <HeapMaxSize>0x100000</HeapMaxSize> 
-  <TCSNum>1</TCSNum> 
-  <TCSPolicy>1</TCSPolicy> 
-  <DisableDebug>0</DisableDebug> 
+<EnclaveConfiguration>
+  <ProdID>0</ProdID>
+  <ISVSVN>0</ISVSVN>
+  <StackMaxSize>0x40000</StackMaxSize>
+  <HeapMaxSize>0x100000</HeapMaxSize>
+  <TCSNum>1</TCSNum>
+  <TCSPolicy>1</TCSPolicy>
+  <DisableDebug>0</DisableDebug>
   <MiscSelect>0</MiscSelect>
   <MiscMask>0xFFFFFFFF</MiscMask>
 </EnclaveConfiguration>
diff --git a/samplecode/localattestation/enclave1/Makefile b/samplecode/localattestation/enclave1/Makefile
index a807f7e..7ba6c85 100644
--- a/samplecode/localattestation/enclave1/Makefile
+++ b/samplecode/localattestation/enclave1/Makefile
@@ -33,5 +33,5 @@
 
 all: $(Rust_Enclave_Name)
 
-$(Rust_Enclave_Name): $(Rust_Enclave_Files)  
+$(Rust_Enclave_Name): $(Rust_Enclave_Files)
 	cargo build --release
diff --git a/samplecode/localattestation/enclave1/src/lib.rs b/samplecode/localattestation/enclave1/src/lib.rs
index 2feaef8..f81a76b 100644
--- a/samplecode/localattestation/enclave1/src/lib.rs
+++ b/samplecode/localattestation/enclave1/src/lib.rs
@@ -67,4 +67,4 @@
 #[allow(unused_variables)]
 pub extern "C" fn test_close_session(src_enclave_id: sgx_enclave_id_t, dest_enclave_id: sgx_enclave_id_t) -> u32 {
     close_session(src_enclave_id, dest_enclave_id) as u32
-}
\ No newline at end of file
+}
diff --git a/samplecode/localattestation/enclave2/Enclave2.config.xml b/samplecode/localattestation/enclave2/Enclave2.config.xml
index 89a7ab5..36465f4 100644
--- a/samplecode/localattestation/enclave2/Enclave2.config.xml
+++ b/samplecode/localattestation/enclave2/Enclave2.config.xml
@@ -1,10 +1,10 @@
-<EnclaveConfiguration> 
-  <ProdID>0</ProdID> 
-  <ISVSVN>0</ISVSVN> 
-  <StackMaxSize>0x40000</StackMaxSize> 
-  <HeapMaxSize>0x100000</HeapMaxSize> 
-  <TCSNum>1</TCSNum> 
-  <TCSPolicy>1</TCSPolicy> 
+<EnclaveConfiguration>
+  <ProdID>0</ProdID>
+  <ISVSVN>0</ISVSVN>
+  <StackMaxSize>0x40000</StackMaxSize>
+  <HeapMaxSize>0x100000</HeapMaxSize>
+  <TCSNum>1</TCSNum>
+  <TCSPolicy>1</TCSPolicy>
   <DisableDebug>0</DisableDebug>
   <MiscSelect>0</MiscSelect>
   <MiscMask>0xFFFFFFFF</MiscMask>
diff --git a/samplecode/localattestation/enclave2/Makefile b/samplecode/localattestation/enclave2/Makefile
index 3bd5488..b0f2295 100644
--- a/samplecode/localattestation/enclave2/Makefile
+++ b/samplecode/localattestation/enclave2/Makefile
@@ -33,5 +33,5 @@
 
 all: $(Rust_Enclave_Name)
 
-$(Rust_Enclave_Name): $(Rust_Enclave_Files)  
+$(Rust_Enclave_Name): $(Rust_Enclave_Files)
 	cargo build --release
diff --git a/samplecode/localattestation/enclave2/src/lib.rs b/samplecode/localattestation/enclave2/src/lib.rs
index 5d8c36e..dcdf3c6 100644
--- a/samplecode/localattestation/enclave2/src/lib.rs
+++ b/samplecode/localattestation/enclave2/src/lib.rs
@@ -67,4 +67,4 @@
 #[allow(unused_variables)]
 pub extern "C" fn test_close_session(src_enclave_id: sgx_enclave_id_t, dest_enclave_id: sgx_enclave_id_t) -> u32 {
     close_session(src_enclave_id, dest_enclave_id) as u32
-}
\ No newline at end of file
+}
diff --git a/samplecode/localattestation/enclave3/Enclave3.config.xml b/samplecode/localattestation/enclave3/Enclave3.config.xml
index 942b839..36465f4 100644
--- a/samplecode/localattestation/enclave3/Enclave3.config.xml
+++ b/samplecode/localattestation/enclave3/Enclave3.config.xml
@@ -1,11 +1,11 @@
-<EnclaveConfiguration> 
-  <ProdID>0</ProdID> 
-  <ISVSVN>0</ISVSVN> 
-  <StackMaxSize>0x40000</StackMaxSize> 
-  <HeapMaxSize>0x100000</HeapMaxSize> 
-  <TCSNum>1</TCSNum> 
-  <TCSPolicy>1</TCSPolicy> 
-  <DisableDebug>0</DisableDebug> 
+<EnclaveConfiguration>
+  <ProdID>0</ProdID>
+  <ISVSVN>0</ISVSVN>
+  <StackMaxSize>0x40000</StackMaxSize>
+  <HeapMaxSize>0x100000</HeapMaxSize>
+  <TCSNum>1</TCSNum>
+  <TCSPolicy>1</TCSPolicy>
+  <DisableDebug>0</DisableDebug>
   <MiscSelect>0</MiscSelect>
   <MiscMask>0xFFFFFFFF</MiscMask>
 </EnclaveConfiguration>
diff --git a/samplecode/localattestation/enclave3/Makefile b/samplecode/localattestation/enclave3/Makefile
index 32af18e..98f7f0e 100644
--- a/samplecode/localattestation/enclave3/Makefile
+++ b/samplecode/localattestation/enclave3/Makefile
@@ -33,5 +33,5 @@
 
 all: $(Rust_Enclave_Name)
 
-$(Rust_Enclave_Name): $(Rust_Enclave_Files)  
+$(Rust_Enclave_Name): $(Rust_Enclave_Files)
 	cargo build --release
diff --git a/samplecode/localattestation/enclave3/src/lib.rs b/samplecode/localattestation/enclave3/src/lib.rs
index 2f08a74..9afc3bf 100644
--- a/samplecode/localattestation/enclave3/src/lib.rs
+++ b/samplecode/localattestation/enclave3/src/lib.rs
@@ -67,4 +67,4 @@
 #[allow(unused_variables)]
 pub extern "C" fn test_close_session(src_enclave_id: sgx_enclave_id_t, dest_enclave_id: sgx_enclave_id_t) -> u32 {
     close_session(src_enclave_id, dest_enclave_id) as u32
-}
\ No newline at end of file
+}
diff --git a/samplecode/remoteattestation/Application/Makefile b/samplecode/remoteattestation/Application/Makefile
index 02043e4..599bf14 100644
--- a/samplecode/remoteattestation/Application/Makefile
+++ b/samplecode/remoteattestation/Application/Makefile
@@ -146,7 +146,7 @@
 
 run: all
 ifneq ($(Build_Mode), HW_RELEASE)
-	@$(CURDIR)/$(App_Name) 	
+	@$(CURDIR)/$(App_Name)
 	@echo "RUN  =>  $(App_Name) [$(SGX_MODE)|$(SGX_ARCH), OK]"
 endif
 
diff --git a/samplecode/remoteattestation/Application/enclave/Cargo.toml b/samplecode/remoteattestation/Application/enclave/Cargo.toml
index a6d68e4..48a3b37 100644
--- a/samplecode/remoteattestation/Application/enclave/Cargo.toml
+++ b/samplecode/remoteattestation/Application/enclave/Cargo.toml
@@ -13,6 +13,7 @@
 
 [dependencies]
 sgx_types = { path = "../../../../sgx_types" }
+sgx_trts = { path = "../../../../sgx_trts" }
 sgx_tstdc = { path = "../../../../sgx_tstdc" }
 sgx_tdh = { path = "../../../../sgx_tdh" }
 sgx_tcrypto = { path = "../../../../sgx_tcrypto" }
diff --git a/samplecode/remoteattestation/Application/enclave/Makefile b/samplecode/remoteattestation/Application/enclave/Makefile
index 3fba6e6..b565f96 100644
--- a/samplecode/remoteattestation/Application/enclave/Makefile
+++ b/samplecode/remoteattestation/Application/enclave/Makefile
@@ -5,7 +5,7 @@
 
 all: $(Rust_Enclave_Name)
 
-$(Rust_Enclave_Name): $(Rust_Enclave_Files)  
+$(Rust_Enclave_Name): $(Rust_Enclave_Files)
 	cargo build --release
 
 clean:
diff --git a/samplecode/remoteattestation/Application/enclave/src/lib.rs b/samplecode/remoteattestation/Application/enclave/src/lib.rs
index e6233c3..36f02a8 100644
--- a/samplecode/remoteattestation/Application/enclave/src/lib.rs
+++ b/samplecode/remoteattestation/Application/enclave/src/lib.rs
@@ -34,10 +34,13 @@
 #![no_std]
 #![feature(collections)]
 
+#![allow(unused_variables)]
+
 #[macro_use]
 extern crate collections;
 
 extern crate sgx_types;
+extern crate sgx_trts;
 extern crate sgx_tdh;
 extern crate sgx_tcrypto;
 extern crate sgx_tservice;
@@ -87,7 +90,7 @@
 
     match rsgx_ra_init(&G_SP_PUB_KEY, b_pse) {
         Ok(p) => {
-            *p_context = p; 
+            *p_context = p;
             ret = sgx_status_t::SGX_SUCCESS;
         },
         Err(x) => {
@@ -177,7 +180,7 @@
 
     let ret:sgx_status_t;
     let sk_key:sgx_ec_key_128bit_t;
-    
+
     match rsgx_ra_get_keys(context, sgx_ra_key_type_t::SGX_RA_KEY_SK) {
         Ok(key) => sk_key = key,
         Err(x) => return x
diff --git a/samplecode/remoteattestation/README.md b/samplecode/remoteattestation/README.md
index 5c84be5..4ef4b96 100644
--- a/samplecode/remoteattestation/README.md
+++ b/samplecode/remoteattestation/README.md
@@ -9,20 +9,20 @@
 #Linux SGX remote attestation (Original Readme below)
 Example of a remote attestation with Intel's SGX including the communication with IAS.
 
-The code requires the installation of Intel SGX [here](https://github.com/01org/linux-sgx) and 
+The code requires the installation of Intel SGX [here](https://github.com/01org/linux-sgx) and
 the SGX driver [here](https://github.com/01org/linux-sgx-driver). Furthermore, also a developer account
 for the usage of IAS has be registered [Deverloper account](https://software.intel.com/en-us/sgx).
 After the registration with a certificate (can be self-signed for development purposes), Intel will
-respond with a SPID which is needed to communicate with IAS. 
+respond with a SPID which is needed to communicate with IAS.
 
 The code consists of two separate programs, the ServiceProvider and the Application.
-The message exchange over the network is performed using Google Protocol Buffers. 
+The message exchange over the network is performed using Google Protocol Buffers.
 
 ## Installation
 
 Before running the code, some settings have to be set in the ```GeneralSettings.h``` file:
-* The application port and IP 
-* A server certificate and private key are required for the SSL communication between the SP and the Application (which can be self-signed)<br /> 
+* The application port and IP
+* A server certificate and private key are required for the SSL communication between the SP and the Application (which can be self-signed)<br />
 e.g. ```openssl req -x509 -nodes -newkey rsa:4096 -keyout server.key -out sever.crt -days 365```
 * The SPID provided by Intel when registering for the developer account
 * The certificate sent to Intel when registering for the developer account
diff --git a/samplecode/remoteattestation/ServiceProvider/Makefile b/samplecode/remoteattestation/ServiceProvider/Makefile
index 3b9d2f0..7949706 100644
--- a/samplecode/remoteattestation/ServiceProvider/Makefile
+++ b/samplecode/remoteattestation/ServiceProvider/Makefile
@@ -48,7 +48,7 @@
 App_Cpp_Files := isv_app/isv_app.cpp ../Util/LogBase.cpp ../Networking/NetworkManager.cpp \
 ../Networking/Session.cpp ../Networking/Client.cpp ../Networking/Server.cpp isv_app/VerificationManager.cpp ../Networking/NetworkManagerClient.cpp \
 ../GoogleMessages/Messages.pb.cpp ../Networking/AbstractNetworkOps.cpp ../Util/UtilityFunctions.cpp ../WebService/WebService.cpp \
-../Util/Base64.cpp 
+../Util/Base64.cpp
 
 App_Include_Paths := -Iservice_provider -I$(SGX_SDK)/include -Iheaders -I../Util -I../Networking -Iisv_app -I../GoogleMessages -I/usr/local/include -I../WebService
 
@@ -87,7 +87,7 @@
 service_provider/ias_ra.cpp ../Util/UtilityFunctions.cpp ../WebService/WebService.cpp service_provider/ServiceProvider.cpp
 
 ServiceProvider_Include_Paths := -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport -Isample_libcrypto
- 
+
 ServiceProvider_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes -I$(SGX_SDK)/include -Isample_libcrypto -I/usr/local/include -I../GoogleMessages -I../Util \
 -I../WebService -I../Networking
 
diff --git a/samplecode/remoteattestation/ServiceProvider/sample_libcrypto/libsample_libcrypto.so b/samplecode/remoteattestation/ServiceProvider/sample_libcrypto/libsample_libcrypto.so
index 0723919..d812266 100755
--- a/samplecode/remoteattestation/ServiceProvider/sample_libcrypto/libsample_libcrypto.so
+++ b/samplecode/remoteattestation/ServiceProvider/sample_libcrypto/libsample_libcrypto.so
Binary files differ
diff --git a/samplecode/remoteattestation/ServiceProvider/sample_libcrypto/sample_libcrypto.h b/samplecode/remoteattestation/ServiceProvider/sample_libcrypto/sample_libcrypto.h
index 0abf54a..39b5781 100644
--- a/samplecode/remoteattestation/ServiceProvider/sample_libcrypto/sample_libcrypto.h
+++ b/samplecode/remoteattestation/ServiceProvider/sample_libcrypto/sample_libcrypto.h
@@ -32,7 +32,7 @@
 /**
 * File: sample_libcrypto.h
 * Description:
-*  Interface for generic crypto library APIs. 
+*  Interface for generic crypto library APIs.
 *  Do NOT use this library in your actual product.
 *  The purpose of this sample library is to aid the debugging of a
 *  remote attestation service.
@@ -102,7 +102,7 @@
 #ifdef __cplusplus
     #define EXTERN_C extern "C"
 #else
-    #define EXTERN_C 
+    #define EXTERN_C
 #endif
 
     #define SAMPLE_LIBCRYPTO_API EXTERN_C
@@ -176,24 +176,24 @@
                                              sample_ecc_state_handle_t ecc_handle);
 
 
-/* Computes signature for data based on private key 
+/* Computes signature for data based on private key
 *
 * A message digest is a fixed size number derived from the original message with
 * an applied hash function over the binary code of the message. (SHA256 in this case)
-* The signer's private key and the message digest are used to create a signature. 
+* The signer's private key and the message digest are used to create a signature.
 *
 * A digital signature over a message consists of a pair of large numbers, 256-bits each,
-* which the given function computes. 
+* which the given function computes.
 *
 * The scheme used for computing a digital signature is of the ECDSA scheme,
-* an elliptic curve of the DSA scheme. 
+* an elliptic curve of the DSA scheme.
 *
 * The keys can be generated and set up by the function: sgx_ecc256_create_key_pair.
 *
-* The elliptic curve domain parameters must be created by function: 
+* The elliptic curve domain parameters must be created by function:
 *     sample_ecc256_open_context
 *
-* Return: If context, private key, signature or data pointer is NULL, 
+* Return: If context, private key, signature or data pointer is NULL,
 *                       SAMPLE_ERROR_INVALID_PARAMETER is returned.
 *         If the signature creation process fails then SAMPLE_ERROR_UNEXPECTED is returned.
 *
@@ -204,10 +204,10 @@
 *           uint8_t *p_data - Pointer to the data to be signed
 *           uint32_t data_size - Size of the data to be signed
 *   Output: ec256_signature_t *p_signature - Pointer to the signature - LITTLE ENDIAN */
-SAMPLE_LIBCRYPTO_API sample_status_t sample_ecdsa_sign(const uint8_t *p_data, 
-                                        uint32_t data_size,  
-                                        sample_ec256_private_t *p_private, 
-                                        sample_ec256_signature_t *p_signature, 
+SAMPLE_LIBCRYPTO_API sample_status_t sample_ecdsa_sign(const uint8_t *p_data,
+                                        uint32_t data_size,
+                                        sample_ec256_private_t *p_private,
+                                        sample_ec256_signature_t *p_signature,
                                         sample_ecc_state_handle_t ecc_handle);
 
 /* Allocates and initializes sha256 state
diff --git a/samplecode/remoteattestation/Util/Base64.cpp b/samplecode/remoteattestation/Util/Base64.cpp
index 37b098e..d0321e4 100644
--- a/samplecode/remoteattestation/Util/Base64.cpp
+++ b/samplecode/remoteattestation/Util/Base64.cpp
@@ -119,7 +119,7 @@
         char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
         char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
 
-        for (j=0; j<i-1; j++) 
+        for (j=0; j<i-1; j++)
 			ret += char_array_3[j];
     }
 
diff --git a/samplecode/sealeddata/Makefile b/samplecode/sealeddata/Makefile
index e2fbb1e..ee2fe0b 100644
--- a/samplecode/sealeddata/Makefile
+++ b/samplecode/sealeddata/Makefile
@@ -83,7 +83,7 @@
 App_C_Files := $(wildcard ./app/*.c)
 App_Include_Paths := -I ./app -I./include -I$(SGX_SDK)/include
 App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths)
-App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread 
+App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread
 ifneq ($(SGX_MODE), HW)
 	App_Link_Flags += -lsgx_uae_service_sim
 else
@@ -155,7 +155,7 @@
 	@$(CC) $(RustEnclave_Compile_Flags) -c $< -o $@
 	@echo "CC   <=  $<"
 
-$(RustEnclave_Name): enclave compiler-rt enclave/Enclave_t.o 
+$(RustEnclave_Name): enclave compiler-rt enclave/Enclave_t.o
 	cp ./enclave/target/release/libenclave.a ./lib
 	cp ../../compiler-rt/libcompiler-rt-patch.a ./lib
 	@$(CXX) enclave/Enclave_t.o -o $@ $(RustEnclave_Link_Flags)
@@ -168,7 +168,7 @@
 .PHONY: enclave
 enclave:
 	$(MAKE) -C ./enclave/
-	
+
 .PHONY: compiler-rt
 compiler-rt:
 	$(MAKE) -C ../../compiler-rt/ 2> /dev/null
@@ -176,4 +176,4 @@
 .PHONY: clean
 clean:
 	@rm -f $(App_Name) $(RustEnclave_Name) $(Signed_RustEnclave_Name) $(RustEnclave_C_Objects) $(App_C_Objects) enclave/*_t.* app/*_u.* lib/*.a
-	
+	@cd enclave && cargo clean && rm -f Cargo.lock
diff --git a/samplecode/sealeddata/app/app.c b/samplecode/sealeddata/app/app.c
index f64128a..782f624 100644
--- a/samplecode/sealeddata/app/app.c
+++ b/samplecode/sealeddata/app/app.c
@@ -143,7 +143,7 @@
             break;
         }
     }
-    
+
     if (idx == ttl)
         printf("Error: Unexpected error occurred.\n");
 }
@@ -159,14 +159,14 @@
     sgx_launch_token_t token = {0};
     sgx_status_t ret = SGX_ERROR_UNEXPECTED;
     int updated = 0;
-    
-    /* Step 1: try to retrieve the launch token saved by last transaction 
+
+    /* Step 1: try to retrieve the launch token saved by last transaction
      *         if there is no token, then create a new one.
      */
     /* try to get the token saved in $HOME */
     const char *home_dir = getpwuid(getuid())->pw_dir;
-    
-    if (home_dir != NULL && 
+
+    if (home_dir != NULL &&
         (strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) {
         /* compose the token path */
         strncpy(token_path, home_dir, strlen(home_dir));
@@ -226,7 +226,7 @@
 	uint32_t sealed_log_size = 1024;
 	uint8_t sealed_log[1024] = {0};
     sgx_sealed_data_t * sealed_data = 0;
-	
+
     (void)(argc);
     (void)(argv);
 
@@ -234,9 +234,9 @@
     if(initialize_enclave() < 0){
         printf("Enter a character before exit ...\n");
         getchar();
-        return -1; 
+        return -1;
     }
- 	
+
  	sgx_ret = create_sealeddata(global_eid, &enclave_ret, sealed_log, sealed_log_size);
  	if(sgx_ret != SGX_SUCCESS) {
         print_error_message(sgx_ret);
@@ -268,7 +268,7 @@
 
     /* Destroy the enclave */
     sgx_destroy_enclave(global_eid);
-    
+
     printf("Enter a character before exit ...\n");
     getchar();
     return 0;
@@ -281,7 +281,7 @@
     	printf("malloc failed\n");
     	return;
     }
-    
+
     memcpy(string, str, len);
     char * ptr = string + len;
     * ptr = 0;
diff --git a/samplecode/sealeddata/enclave/Enclave.edl b/samplecode/sealeddata/enclave/Enclave.edl
index 93bb206..c286189 100644
--- a/samplecode/sealeddata/enclave/Enclave.edl
+++ b/samplecode/sealeddata/enclave/Enclave.edl
@@ -28,22 +28,22 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  */
- 
+
 enclave {
-	
+
 	trusted {
         /* define ECALLs here. */
-		
+
         public sgx_status_t create_sealeddata([out, size=sealed_log_size]
             uint8_t* sealed_log, uint32_t sealed_log_size );
 
         public sgx_status_t verify_sealeddata([in, size=sealed_log_size]
             uint8_t* sealed_log, uint32_t sealed_log_size);
     };
-    
+
     untrusted {
         void ocall_print_string([in, size=len] const char *str, size_t len);
     };
 
- 
+
 };
\ No newline at end of file
diff --git a/samplecode/sealeddata/enclave/Makefile b/samplecode/sealeddata/enclave/Makefile
index 3953ca0..56346bb 100644
--- a/samplecode/sealeddata/enclave/Makefile
+++ b/samplecode/sealeddata/enclave/Makefile
@@ -33,5 +33,5 @@
 
 all: $(Rust_Enclave_Name)
 
-$(Rust_Enclave_Name): $(Rust_Enclave_Files)  
+$(Rust_Enclave_Name): $(Rust_Enclave_Files)
 	cargo build --release
diff --git a/samplecode/sealeddata/enclave/src/lib.rs b/samplecode/sealeddata/enclave/src/lib.rs
index 7cd0192..a52ea24 100644
--- a/samplecode/sealeddata/enclave/src/lib.rs
+++ b/samplecode/sealeddata/enclave/src/lib.rs
@@ -40,6 +40,7 @@
 extern crate sgx_trts;
 
 use sgx_types::*;
+use sgx_types::marker::ContiguousMemory;
 use sgx_tseal::*;
 use sgx_trts::*;
 
@@ -49,6 +50,8 @@
     rand: [u8; 16],
 }
 
+unsafe impl ContiguousMemory for RandData {}
+
 extern {
     fn ocall_print_string(str: * const c_uchar, len: size_t);
 }
@@ -61,7 +64,7 @@
     let error = rsgx_read_rand(&mut data.rand);
     if error.is_err() {
         return error.unwrap_err();
-    } 
+    }
 
     let aad: [u8; 0] = [0_u8; 0];
     let result = SgxSealedData::<RandData>::seal_data(&aad, &data);
@@ -69,17 +72,17 @@
         Ok(x) => x,
         Err(ret) => {
             return ret;
-        }, 
+        },
     };
 
     let opt = to_sealed_log(&sealed_data, sealed_log, sealed_log_size);
     if opt.is_none() {
         return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
     }
-    
+
     let outstring = format!("{:?}", data);
     output(&outstring);
-    
+
     sgx_status_t::SGX_SUCCESS
 }
 
@@ -93,13 +96,13 @@
             return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
         },
     };
-    
+
     let result = sealed_data.unseal_data();
     let unsealed_data = match result {
         Ok(x) => x,
         Err(ret) => {
             return ret;
-        }, 
+        },
     };
 
     let data = unsealed_data.get_decrypt_txt();
@@ -115,13 +118,13 @@
     }
 }
 
-fn to_sealed_log<T>(sealed_data: &SgxSealedData<T>, sealed_log: * mut u8, sealed_log_size: u32) -> Option<* mut sgx_sealed_data_t> {
+fn to_sealed_log<T: Copy + ContiguousMemory>(sealed_data: &SgxSealedData<T>, sealed_log: * mut u8, sealed_log_size: u32) -> Option<* mut sgx_sealed_data_t> {
     unsafe {
         sealed_data.to_raw_sealed_data_t(sealed_log as * mut sgx_sealed_data_t, sealed_log_size)
     }
 }
-fn from_sealed_log<T: Copy>(sealed_log: * mut u8, sealed_log_size: u32) -> Option<SgxSealedData<T>> {
+fn from_sealed_log<'a, T: Copy + ContiguousMemory>(sealed_log: * mut u8, sealed_log_size: u32) -> Option<SgxSealedData<'a, T>> {
     unsafe {
         SgxSealedData::<T>::from_raw_sealed_data_t(sealed_log as * mut sgx_sealed_data_t, sealed_log_size)
     }
-}
\ No newline at end of file
+}
diff --git a/samplecode/thread/Makefile b/samplecode/thread/Makefile
index eceee66..4ffcf3d 100644
--- a/samplecode/thread/Makefile
+++ b/samplecode/thread/Makefile
@@ -84,7 +84,7 @@
 App_Include_Paths := -I ./app -I./include -I$(SGX_SDK)/include
 App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths)
 App_Cpp_Flags := $(App_C_Flags) -std=c++11
-App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread 
+App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread
 ifneq ($(SGX_MODE), HW)
 	App_Link_Flags += -lsgx_uae_service_sim
 else
@@ -156,7 +156,7 @@
 	@$(CC) $(RustEnclave_Compile_Flags) -c $< -o $@
 	@echo "CC   <=  $<"
 
-$(RustEnclave_Name): enclave compiler-rt enclave/Enclave_t.o 
+$(RustEnclave_Name): enclave compiler-rt enclave/Enclave_t.o
 	cp ./enclave/target/release/libenclave.a ./lib
 	cp ../../compiler-rt/libcompiler-rt-patch.a ./lib
 	@$(CXX) enclave/Enclave_t.o -o $@ $(RustEnclave_Link_Flags)
@@ -169,12 +169,12 @@
 .PHONY: enclave
 enclave:
 	$(MAKE) -C ./enclave/
-	
+
 .PHONY: compiler-rt
 compiler-rt:
 	$(MAKE) -C ../../compiler-rt/ 2> /dev/null
-	
+
 .PHONY: clean
 clean:
 	@rm -f $(App_Name) $(RustEnclave_Name) $(Signed_RustEnclave_Name) $(RustEnclave_C_Objects) $(App_Cpp_Objects) enclave/*_t.* app/*_u.* lib/*.a
-	
+	@cd enclave && cargo clean && rm -f Cargo.lock
diff --git a/samplecode/thread/app/App.cpp b/samplecode/thread/app/App.cpp
index 76359ab..555e5d2 100644
--- a/samplecode/thread/app/App.cpp
+++ b/samplecode/thread/app/App.cpp
@@ -144,7 +144,7 @@
             break;
         }
     }
-    
+
     if (idx == ttl)
         printf("Error: Unexpected error occurred.\n");
 }
@@ -160,14 +160,14 @@
     sgx_launch_token_t token = {0};
     sgx_status_t ret = SGX_ERROR_UNEXPECTED;
     int updated = 0;
-    
-    /* Step 1: try to retrieve the launch token saved by last transaction 
+
+    /* Step 1: try to retrieve the launch token saved by last transaction
      *         if there is no token, then create a new one.
      */
     /* try to get the token saved in $HOME */
     const char *home_dir = getpwuid(getuid())->pw_dir;
-    
-    if (home_dir != NULL && 
+
+    if (home_dir != NULL &&
         (strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) {
         /* compose the token path */
         strncpy(token_path, home_dir, strlen(home_dir));
@@ -226,7 +226,7 @@
     	printf("malloc failed\n");
     	return;
     }
-    
+
     memcpy(string, str, len);
     char * ptr = string + len;
     * ptr = 0;
@@ -245,14 +245,14 @@
     if(initialize_enclave() < 0){
         printf("Enter a character before exit ...\n");
         getchar();
-        return -1; 
+        return -1;
     }
- 
+
     ecall_thread_functions();
 
     /* Destroy the enclave */
     sgx_destroy_enclave(global_eid);
-    
+
     printf("Info: SampleEnclave successfully returned.\n");
 
     printf("Enter a character before exit ...\n");
diff --git a/samplecode/thread/app/Thread.cpp b/samplecode/thread/app/Thread.cpp
index 396ee9e..f6f1c28 100644
--- a/samplecode/thread/app/Thread.cpp
+++ b/samplecode/thread/app/Thread.cpp
@@ -86,7 +86,7 @@
     thread consumer2(data_consumer);
     thread consumer3(data_consumer);
     thread consumer4(data_consumer);
-    
+
     consumer1.join();
     consumer2.join();
     consumer3.join();
diff --git a/samplecode/thread/enclave/Cargo.toml b/samplecode/thread/enclave/Cargo.toml
index 3d0f90c..7d654be 100644
--- a/samplecode/thread/enclave/Cargo.toml
+++ b/samplecode/thread/enclave/Cargo.toml
@@ -13,4 +13,5 @@
 
 [dependencies]
 sgx_types = { path = "../../../sgx_types" }
+sgx_trts = { path = "../../../sgx_trts" }
 sgx_tstdc = { path = "../../../sgx_tstdc" }
diff --git a/samplecode/thread/enclave/Makefile b/samplecode/thread/enclave/Makefile
index 3953ca0..56346bb 100644
--- a/samplecode/thread/enclave/Makefile
+++ b/samplecode/thread/enclave/Makefile
@@ -33,5 +33,5 @@
 
 all: $(Rust_Enclave_Name)
 
-$(Rust_Enclave_Name): $(Rust_Enclave_Files)  
+$(Rust_Enclave_Name): $(Rust_Enclave_Files)
 	cargo build --release
diff --git a/samplecode/thread/enclave/src/lib.rs b/samplecode/thread/enclave/src/lib.rs
index 79f2d8e..9043b74 100644
--- a/samplecode/thread/enclave/src/lib.rs
+++ b/samplecode/thread/enclave/src/lib.rs
@@ -37,6 +37,7 @@
 use core::sync::atomic::{AtomicPtr, Ordering};
 
 extern crate sgx_types;
+extern crate sgx_trts;
 extern crate sgx_tstdc;
 
 use sgx_types::*;
@@ -83,7 +84,7 @@
     let ptr = GLOBAL_COND_BUFFER.swap(0 as * mut (), Ordering::SeqCst) as * mut (SgxMutex<CondBuffer>, SgxCond, SgxCond);
     if ptr.is_null() {
        return;
-    } 
+    }
     let _ = unsafe { Box::from_raw(ptr) };
 }
 
@@ -93,7 +94,7 @@
     if ptr.is_null() {
         None
     } else {
-        Some(unsafe { &* ptr })  
+        Some(unsafe { &* ptr })
     }
 }
 
@@ -104,13 +105,13 @@
     let &(ref mutex, ref more, ref less) = get_ref_cond_buffer().unwrap();
 
     for _ in 0..max_index {
-            
+
         let mut guard = mutex.lock().unwrap();
 
         while guard.occupied >= BUFFER_SIZE as i32 {
             guard = less.wait(guard).unwrap();
         }
-            
+
         let index = guard.nextin;
         guard.buf[index] = guard.nextin;
         guard.nextin += 1;
@@ -128,7 +129,7 @@
     let &(ref mutex, ref more, ref less) = get_ref_cond_buffer().unwrap();
 
     for _ in 0..max_index {
-            
+
         let mut guard = mutex.lock().unwrap();
 
         while guard.occupied <= 0 {
diff --git a/sgx_tcrypto/Cargo.toml b/sgx_tcrypto/Cargo.toml
index e401c2c..d9fa51b 100644
--- a/sgx_tcrypto/Cargo.toml
+++ b/sgx_tcrypto/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tcrypto"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Baidu"]
 
 [features]
diff --git a/sgx_tcrypto/src/crypto.rs b/sgx_tcrypto/src/crypto.rs
index 7e528af..c266ebe 100644
--- a/sgx_tcrypto/src/crypto.rs
+++ b/sgx_tcrypto/src/crypto.rs
@@ -30,6 +30,7 @@
 //! Cryptographic Functions
 //!
 use sgx_types::*;
+use sgx_types::marker::ContiguousMemory;
 use core::ops::{Drop, DerefMut};
 use core::ptr;
 use core::mem;
@@ -39,15 +40,15 @@
 /// The rsgx_sha256_msg function performs a standard SHA256 hash over the input data buffer.
 ///
 /// # Description
-/// 
-/// The rsgx_sha256_msg function performs a standard SHA256 hash over the input data buffer. 
-/// Only a 256-bit version of the SHA hash is supported. (Other sizes, for example 512, are 
+///
+/// The rsgx_sha256_msg function performs a standard SHA256 hash over the input data buffer.
+/// Only a 256-bit version of the SHA hash is supported. (Other sizes, for example 512, are
 /// not supported in this minimal cryptography library).
 ///
 /// The function should be used if the complete input data stream is available.
 /// Otherwise, the Init, Update… Update, Final procedure should be used to compute
 /// a SHA256 bit hash over multiple input data sets.
-/// 
+///
 /// # Parameters
 ///
 /// **src**
@@ -76,8 +77,9 @@
 ///
 /// The SHA256 hash calculation failed.
 ///
-pub fn rsgx_sha256_msg<T: Copy>(src: &T) -> SgxResult<sgx_sha256_hash_t> {
-    
+pub fn rsgx_sha256_msg<T>(src: &T) -> SgxResult<sgx_sha256_hash_t>
+    where T: Copy + ContiguousMemory {
+
     let size = mem::size_of::<T>();
     if size == 0 {
         return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
@@ -97,9 +99,10 @@
 ///
 /// The rsgx_sha256_slice function performs a standard SHA256 hash over the input data buffer.
 ///
-pub fn rsgx_sha256_slice<T: Copy>(src: &[T]) -> SgxResult<sgx_sha256_hash_t> {
-    
-    let size = mem::size_of::<T>() * src.len();
+pub fn rsgx_sha256_slice<T>(src: &[T]) -> SgxResult<sgx_sha256_hash_t>
+    where T: Copy + ContiguousMemory {
+
+    let size = mem::size_of_val(src);
     if size == 0 {
         return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
     }
@@ -117,12 +120,13 @@
 
 fn rsgx_sha256_init(sha_handle: &mut sgx_sha_state_handle_t) -> sgx_status_t {
 
-    unsafe { 
-        sgx_sha256_init(sha_handle as * mut _ as * mut sgx_sha_state_handle_t) 
+    unsafe {
+        sgx_sha256_init(sha_handle as * mut _ as * mut sgx_sha_state_handle_t)
     }
 }
 
-fn rsgx_sha256_update_msg<T: Copy>(src: &T, sha_handle: sgx_sha_state_handle_t) -> sgx_status_t {
+fn rsgx_sha256_update_msg<T>(src: &T, sha_handle: sgx_sha_state_handle_t) -> sgx_status_t
+    where T: Copy + ContiguousMemory {
 
     let size = mem::size_of::<T>();
     if size == 0 {
@@ -132,14 +136,15 @@
         return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
     }
 
-    unsafe { 
-        sgx_sha256_update(src as * const _ as * const u8, size as u32, sha_handle) 
+    unsafe {
+        sgx_sha256_update(src as * const _ as * const u8, size as u32, sha_handle)
     }
 }
 
-fn rsgx_sha256_update_slice<T: Copy>(src: &[T], sha_handle: sgx_sha_state_handle_t) -> sgx_status_t {
+fn rsgx_sha256_update_slice<T>(src: &[T], sha_handle: sgx_sha_state_handle_t) -> sgx_status_t
+    where T: Copy + ContiguousMemory {
 
-    let size = mem::size_of::<T>() * src.len();
+    let size = mem::size_of_val(src);
     if size == 0 {
         return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
     }
@@ -152,23 +157,23 @@
 }
 
 fn rsgx_sha256_get_hash(sha_handle: sgx_sha_state_handle_t, hash: &mut sgx_sha256_hash_t) -> sgx_status_t {
-    
+
     unsafe { sgx_sha256_get_hash(sha_handle, hash as * mut sgx_sha256_hash_t) }
 }
 
 fn rsgx_sha256_close(sha_handle: sgx_sha_state_handle_t) -> sgx_status_t {
-     
+
      unsafe { sgx_sha256_close(sha_handle) }
 }
 
 ///
 /// SHA algorithm context state.
 ///
-/// This is a handle to the context state used by the cryptography library to perform an iterative SHA256 hash. 
+/// This is a handle to the context state used by the cryptography library to perform an iterative SHA256 hash.
 /// The algorithm stores the intermediate results of performing the hash calculation over data sets.
 ///
 pub struct SgxShaHandle {
-    handle: RefCell<sgx_sha_state_handle_t>, 
+    handle: RefCell<sgx_sha_state_handle_t>,
     initflag: Cell<bool>,
 }
 
@@ -179,24 +184,24 @@
     ///
     pub fn new() -> Self {
         SgxShaHandle{
-            handle: RefCell::new(ptr::null_mut() as sgx_sha_state_handle_t), 
+            handle: RefCell::new(ptr::null_mut() as sgx_sha_state_handle_t),
             initflag: Cell::new(false),
-            }
+        }
     }
 
     ///
     /// init returns an allocated and initialized SHA algorithm context state.
     ///
-    /// This should be part of the Init, Update … Update, Final process when the SHA hash is to be performed 
-    /// over multiple datasets. If a complete dataset is available, the recommend call is rsgx_sha256_msg to 
+    /// This should be part of the Init, Update … Update, Final process when the SHA hash is to be performed
+    /// over multiple datasets. If a complete dataset is available, the recommend call is rsgx_sha256_msg to
     /// perform the hash in a single call.
     ///
     /// # Description
     ///
-    /// Calling init is the first set in performing a SHA256 hash over multiple datasets. The caller does not 
-    /// allocate memory for the SHA256 state that this function returns. The state is specific to the implementation 
-    /// of the cryptography library; thus the allocation is performed by the library itself. If the hash over the 
-    /// desired datasets is completed or any error occurs during the hash calculation process, sgx_sha256_close should 
+    /// Calling init is the first set in performing a SHA256 hash over multiple datasets. The caller does not
+    /// allocate memory for the SHA256 state that this function returns. The state is specific to the implementation
+    /// of the cryptography library; thus the allocation is performed by the library itself. If the hash over the
+    /// desired datasets is completed or any error occurs during the hash calculation process, sgx_sha256_close should
     /// be called to free the state allocated by this algorithm.
     ///
     /// # Requirements
@@ -232,27 +237,27 @@
             _ => Err(ret),
         }
     }
-    
+
     ///
-    /// update_msg performs a SHA256 hash over the input dataset provided. 
+    /// update_msg performs a SHA256 hash over the input dataset provided.
     ///
-    /// This function supports an iterative calculation of the hash over multiple datasets where the 
+    /// This function supports an iterative calculation of the hash over multiple datasets where the
     /// sha_handle contains the intermediate results of the hash calculation over previous datasets.
     ///
     /// # Description
     ///
-    /// This function should be used as part of a SHA256 calculation over multiple datasets. 
-    /// If a SHA256 hash is needed over a single data set, function rsgx_sha256_msg should be used instead. 
-    /// Prior to calling this function on the first dataset, the init function must be called first to allocate 
-    /// and initialize the SHA256 state structure which will hold intermediate hash results over earlier datasets. 
-    /// The function get_hash should be used to obtain the hash after the final dataset has been processed 
+    /// This function should be used as part of a SHA256 calculation over multiple datasets.
+    /// If a SHA256 hash is needed over a single data set, function rsgx_sha256_msg should be used instead.
+    /// Prior to calling this function on the first dataset, the init function must be called first to allocate
+    /// and initialize the SHA256 state structure which will hold intermediate hash results over earlier datasets.
+    /// The function get_hash should be used to obtain the hash after the final dataset has been processed
     /// by this function.
     ///
     /// # Parameters
     ///
     /// **src**
     ///
-    /// A pointer to the input data stream to be hashed. 
+    /// A pointer to the input data stream to be hashed.
     ///
     /// # Requirements
     ///
@@ -272,7 +277,8 @@
     ///
     /// An internal cryptography library failure occurred while performing the SHA256 hash calculation.
     ///
-    pub fn update_msg<T: Copy>(&self, src: &T) -> SgxError {
+    pub fn update_msg<T>(&self, src: &T) -> SgxError
+        where T: Copy + ContiguousMemory {
 
         if self.initflag.get() == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
@@ -286,9 +292,10 @@
     }
 
     ///
-    /// update_slice performs a SHA256 hash over the input dataset provided. 
+    /// update_slice performs a SHA256 hash over the input dataset provided.
     ///
-    pub fn update_slice<T: Copy>(&self, src: &[T]) -> SgxError {
+    pub fn update_slice<T>(&self, src: &[T]) -> SgxError
+        where T: Copy + ContiguousMemory {
 
         if self.initflag.get() == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
@@ -306,7 +313,7 @@
     ///
     /// # Description
     ///
-    /// This function returns the hash after performing the SHA256 calculation over one or more datasets 
+    /// This function returns the hash after performing the SHA256 calculation over one or more datasets
     /// using the update function.
     ///
     /// # Requirements
@@ -338,7 +345,7 @@
         }
 
         let mut hash = sgx_sha256_hash_t::default();
-        let ret = rsgx_sha256_get_hash(*self.handle.borrow(), &mut hash); 
+        let ret = rsgx_sha256_get_hash(*self.handle.borrow(), &mut hash);
         match ret {
             sgx_status_t::SGX_SUCCESS => Ok(hash),
             _ => Err(ret),
@@ -350,7 +357,7 @@
     ///
     /// # Description
     ///
-    /// Calling close is the last step after performing a SHA256 hash over multiple datasets. 
+    /// Calling close is the last step after performing a SHA256 hash over multiple datasets.
     /// The caller uses this function to deallocate memory used to store the SHA256 calculation state.
     ///
     /// # Requirements
@@ -377,7 +384,7 @@
                 rsgx_sha256_close(handle)
             }
         };
-         
+
         match ret {
             sgx_status_t::SGX_SUCCESS => {
                 self.initflag.set(false);
@@ -407,11 +414,11 @@
 
 ///
 /// rsgx_rijndael128GCM_encrypt performs a Rijndael AES-GCM encryption operation.
-/// 
+///
 /// Only a 128bit key size is supported by this Intel(R) SGX SDK cryptography library.
 ///
 /// # Description
-/// 
+///
 /// The Galois/Counter Mode (GCM) is a mode of operation of the AES algorithm.
 /// GCM [NIST SP 800-38D] uses a variation of the counter mode of operation for
 /// encryption. GCM assures authenticity of the confidential data (of up to about
@@ -428,7 +435,7 @@
 /// within the enclave. The AAD buffer could be allocated within or outside
 /// enclave memory. The use of AAD data buffer could be information identifying
 /// the encrypted data since it will remain in clear text.
-/// 
+///
 /// # Parameters
 ///
 /// **key**
@@ -441,12 +448,12 @@
 ///
 /// **iv**
 ///
-/// A pointer to the initialization vector to be used in the AES-GCM calculation. NIST AES-GCM recommended 
+/// A pointer to the initialization vector to be used in the AES-GCM calculation. NIST AES-GCM recommended
 /// IV size is 96 bits (12 bytes).
 ///
 /// **aad**
 ///
-/// A pointer to an optional additional authentication data buffer which is used in the GCM MAC calculation. 
+/// A pointer to an optional additional authentication data buffer which is used in the GCM MAC calculation.
 /// The data in this buffer will not be encrypted. The field is optional and content could be empty.
 ///
 /// **dst**
@@ -455,7 +462,7 @@
 ///
 /// **mac**
 ///
-/// This is the output GCM MAC performed over the input data buffer (data to be encrypted) as well as 
+/// This is the output GCM MAC performed over the input data buffer (data to be encrypted) as well as
 /// the additional authentication data (this is optional data). The calling code should allocate this buffer.
 ///
 /// # Requirements
@@ -484,7 +491,7 @@
                                    aad: &[u8],
                                    dst: &mut [u8],
                                    mac: &mut sgx_aes_gcm_128bit_tag_t) -> SgxError {
-    
+
     let src_len = src.len();
     if src_len > u32::max_value() as usize {
         return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
@@ -535,12 +542,12 @@
 }
 
 ///
-/// rsgx_rijndael128GCM_decrypt performs a Rijndael AES-GCM decryption operation. 
-/// 
+/// rsgx_rijndael128GCM_decrypt performs a Rijndael AES-GCM decryption operation.
+///
 /// Only a 128bit key size is supported by this Intel(R) SGX SDK cryptography library.
 ///
 /// # Description
-/// 
+///
 /// The Galois/Counter Mode (GCM) is a mode of operation of the AES algorithm.
 /// GCM [NIST SP 800-38D] uses a variation of the counter mode of operation for
 /// encryption. GCM assures authenticity of the confidential data (of up to about
@@ -568,18 +575,18 @@
 ///
 /// **iv**
 ///
-/// A pointer to the initialization vector to be used in the AES-GCM calculation. NIST AES-GCM recommended 
+/// A pointer to the initialization vector to be used in the AES-GCM calculation. NIST AES-GCM recommended
 /// IV size is 96 bits (12 bytes).
 ///
 /// **aad**
 ///
-/// A pointer to an optional additional authentication data buffer which is provided for the GCM MAC calculation 
+/// A pointer to an optional additional authentication data buffer which is provided for the GCM MAC calculation
 /// when encrypting. The data in this buffer was not encrypted. The field is optional and content could be empty.
 ///
 /// **mac**
 ///
-/// This is the GCM MAC that was performed over the input data buffer (data to be encrypted) as well as 
-/// the additional authentication data (this is optional data) during the encryption process (call to 
+/// This is the GCM MAC that was performed over the input data buffer (data to be encrypted) as well as
+/// the additional authentication data (this is optional data) during the encryption process (call to
 /// rsgx_rijndael128GCM_encrypt).
 ///
 /// **dst**
@@ -670,8 +677,8 @@
 /// The rsgx_rijndael128_cmac_msg function performs a standard 128bit CMAC hash over the input data buffer.
 ///
 /// # Description
-/// 
-/// The rsgx_rijndael128_cmac_msg function performs a standard CMAC hash over the input data buffer. 
+///
+/// The rsgx_rijndael128_cmac_msg function performs a standard CMAC hash over the input data buffer.
 /// Only a 128-bit version of the CMAC hash is supported.
 ///
 /// The function should be used if the complete input data stream is available.
@@ -710,8 +717,9 @@
 ///
 /// An internal cryptography library failure occurred.
 ///
-pub fn rsgx_rijndael128_cmac_msg<T: Copy>(key: &sgx_cmac_128bit_key_t, src: &T) -> SgxResult<sgx_cmac_128bit_tag_t> {
-    
+pub fn rsgx_rijndael128_cmac_msg<T>(key: &sgx_cmac_128bit_key_t, src: &T) -> SgxResult<sgx_cmac_128bit_tag_t>
+    where T: Copy + ContiguousMemory {
+
     let size = mem::size_of::<T>();
     if size == 0 {
         return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
@@ -722,9 +730,9 @@
 
     let mut mac = sgx_cmac_128bit_tag_t::default();
     let ret = unsafe {
-        sgx_rijndael128_cmac_msg(key as * const sgx_cmac_128bit_key_t, 
-                                 src as * const _ as * const u8, 
-                                 size as u32, 
+        sgx_rijndael128_cmac_msg(key as * const sgx_cmac_128bit_key_t,
+                                 src as * const _ as * const u8,
+                                 size as u32,
                                  &mut mac as * mut sgx_cmac_128bit_tag_t)
     };
     match ret {
@@ -736,9 +744,10 @@
 ///
 /// The rsgx_rijndael128_cmac_slice function performs a standard 128bit CMAC hash over the input data buffer.
 ///
-pub fn rsgx_rijndael128_cmac_slice<T: Copy>(key: &sgx_cmac_128bit_key_t, src: &[T]) -> SgxResult<sgx_cmac_128bit_tag_t> {
-    
-    let size = mem::size_of::<T>() * src.len();
+pub fn rsgx_rijndael128_cmac_slice<T>(key: &sgx_cmac_128bit_key_t, src: &[T]) -> SgxResult<sgx_cmac_128bit_tag_t>
+    where T: Copy + ContiguousMemory {
+
+    let size = mem::size_of_val(src);
     if size == 0 {
         return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
     }
@@ -748,11 +757,11 @@
 
     let mut mac = sgx_cmac_128bit_tag_t::default();
     let ret = unsafe {
-        sgx_rijndael128_cmac_msg(key as * const sgx_cmac_128bit_key_t, 
+        sgx_rijndael128_cmac_msg(key as * const sgx_cmac_128bit_key_t,
                                  src.as_ptr() as * const u8,
-                                 size as u32, 
+                                 size as u32,
                                  &mut mac as * mut sgx_cmac_128bit_tag_t)
-    }; 
+    };
     match ret {
         sgx_status_t::SGX_SUCCESS => Ok(mac),
         _ => Err(ret),
@@ -760,14 +769,15 @@
 }
 
 fn rsgx_cmac128_init(key: &sgx_cmac_128bit_key_t, cmac_handle: &mut sgx_cmac_state_handle_t) -> sgx_status_t {
-    
+
     unsafe {
-        sgx_cmac128_init(key as * const sgx_cmac_128bit_key_t, 
+        sgx_cmac128_init(key as * const sgx_cmac_128bit_key_t,
                          cmac_handle as * mut _ as * mut sgx_cmac_state_handle_t)
     }
 }
 
-fn rsgx_cmac128_update_msg<T: Copy>(src: &T, cmac_handle: sgx_cmac_state_handle_t) -> sgx_status_t {
+fn rsgx_cmac128_update_msg<T>(src: &T, cmac_handle: sgx_cmac_state_handle_t) -> sgx_status_t
+    where T: Copy + ContiguousMemory {
 
     let size = mem::size_of::<T>();
     if size == 0 {
@@ -781,9 +791,10 @@
     }
 }
 
-fn rsgx_cmac128_update_slice<T: Copy>(src: &[T], cmac_handle: sgx_cmac_state_handle_t) -> sgx_status_t {
+fn rsgx_cmac128_update_slice<T>(src: &[T], cmac_handle: sgx_cmac_state_handle_t) -> sgx_status_t
+    where T: Copy + ContiguousMemory {
 
-    let size = mem::size_of::<T>() * src.len();
+    let size = mem::size_of_val(src);
     if size == 0 {
         return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
     }
@@ -796,24 +807,24 @@
 }
 
 fn rsgx_cmac128_final(cmac_handle: sgx_cmac_state_handle_t, hash: &mut sgx_cmac_128bit_tag_t) -> sgx_status_t {
-    
+
     unsafe { sgx_cmac128_final(cmac_handle, hash as * mut sgx_cmac_128bit_tag_t) }
 }
 
 fn rsgx_cmac128_close(cmac_handle: sgx_cmac_state_handle_t) -> sgx_status_t {
-    
+
     unsafe { sgx_cmac128_close(cmac_handle) }
 }
 
 ///
 /// CMAC algorithm context state.
 ///
-/// This is a handle to the context state used by the cryptography library to perform an 
-/// iterative CMAC 128-bit hash. The algorithm stores the intermediate results of performing 
+/// This is a handle to the context state used by the cryptography library to perform an
+/// iterative CMAC 128-bit hash. The algorithm stores the intermediate results of performing
 /// the hash calculation over data sets.
 ///
 pub struct SgxCmacHandle {
-    handle: RefCell<sgx_cmac_state_handle_t>, 
+    handle: RefCell<sgx_cmac_state_handle_t>,
     initflag: Cell<bool>,
 }
 
@@ -824,31 +835,31 @@
     ///
     pub fn new() -> Self {
         SgxCmacHandle{
-            handle: RefCell::new(ptr::null_mut() as sgx_cmac_state_handle_t), 
+            handle: RefCell::new(ptr::null_mut() as sgx_cmac_state_handle_t),
             initflag: Cell::new(false),
             }
     }
 
     ///
-    /// init returns an allocated and initialized CMAC algorithm context state. 
+    /// init returns an allocated and initialized CMAC algorithm context state.
     ///
-    /// This should be part of the Init, Update … Update, Final process when the CMAC hash is to be 
-    /// performed over multiple datasets. If a complete dataset is available, the recommended call 
+    /// This should be part of the Init, Update … Update, Final process when the CMAC hash is to be
+    /// performed over multiple datasets. If a complete dataset is available, the recommended call
     /// is rsgx_rijndael128_cmac_msg to perform the hash in a single call.
     ///
     /// # Description
     ///
-    /// Calling init is the first set in performing a CMAC 128-bit hash over multiple datasets. 
-    /// The caller does not allocate memory for the CMAC state that this function returns. 
-    /// The state is specific to the implementation of the cryptography library and thus the 
-    /// allocation is performed by the library itself. If the hash over the desired datasets is 
+    /// Calling init is the first set in performing a CMAC 128-bit hash over multiple datasets.
+    /// The caller does not allocate memory for the CMAC state that this function returns.
+    /// The state is specific to the implementation of the cryptography library and thus the
+    /// allocation is performed by the library itself. If the hash over the desired datasets is
     /// completed or any error occurs during the hash calculation process, sgx_cmac128_close should
     /// be called to free the state allocated by this algorithm.
     ///
     /// # Parameters
     ///
     /// **key**
-    /// 
+    ///
     /// A pointer to key to be used in the CMAC hash operation. The size must be 128 bits.
     ///
     /// # Requirements
@@ -870,7 +881,7 @@
     /// An internal cryptography library failure occurred.
     ///
     pub fn init(&self, key: &sgx_cmac_128bit_key_t) -> SgxError {
-        
+
         if self.initflag.get() == true {
             return Ok(());
         }
@@ -886,9 +897,9 @@
     }
 
     ///
-    /// update_msg performs a CMAC 128-bit hash over the input dataset provided. 
+    /// update_msg performs a CMAC 128-bit hash over the input dataset provided.
     ///
-    /// This function supports an iterative calculation of the hash over multiple datasets where the 
+    /// This function supports an iterative calculation of the hash over multiple datasets where the
     /// cmac_handle contains the intermediate results of the hash calculation over previous datasets.
     ///
     /// # Description
@@ -896,15 +907,15 @@
     /// This function should be used as part of a CMAC 128-bit hash calculation over
     /// multiple datasets. If a CMAC hash is needed over a single data set, function
     /// rsgx_rijndael128_cmac128_msg should be used instead. Prior to calling
-    /// this function on the first dataset, the init function must be called first to 
-    /// allocate and initialize the CMAC state structure which will hold intermediate 
-    /// hash results over earlier datasets. The function get_hash should be used 
+    /// this function on the first dataset, the init function must be called first to
+    /// allocate and initialize the CMAC state structure which will hold intermediate
+    /// hash results over earlier datasets. The function get_hash should be used
     /// to obtain the hash after the final dataset has been processed by this function.
     ///
     /// # Parameters
     ///
     /// **src**
-    /// 
+    ///
     /// A pointer to the input data stream to be hashed.
     ///
     /// # Requirements
@@ -929,8 +940,9 @@
     ///
     /// An internal cryptography library failure occurred while performing the CMAC hash calculation.
     ///
-    pub fn update_msg<T: Copy>(&self, src: &T) -> SgxError {
-        
+    pub fn update_msg<T>(&self, src: &T) -> SgxError
+        where T: Copy + ContiguousMemory {
+
         if self.initflag.get() == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
         }
@@ -943,10 +955,11 @@
     }
 
     ///
-    /// update_slice performs a CMAC 128-bit hash over the input dataset provided. 
+    /// update_slice performs a CMAC 128-bit hash over the input dataset provided.
     ///
-    pub fn update_slice<T: Copy>(&self, src: &[T]) -> SgxError {
-        
+    pub fn update_slice<T>(&self, src: &[T]) -> SgxError
+        where T: Copy + ContiguousMemory {
+
         if self.initflag.get() == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
         }
@@ -1007,7 +1020,7 @@
     ///
     /// # Description
     ///
-    /// Calling close is the last step after performing a CMAC hash over multiple datasets. 
+    /// Calling close is the last step after performing a CMAC hash over multiple datasets.
     /// The caller uses this function to deallocate memory used for storing the CMAC algorithm context state.
     ///
     /// # Requirements
@@ -1034,7 +1047,7 @@
                 rsgx_cmac128_close(handle)
             }
         };
-         
+
         match ret {
             sgx_status_t::SGX_SUCCESS => {
                 self.initflag.set(false);
@@ -1066,11 +1079,11 @@
 
 ///
 /// rsgx_aes_ctr_encrypt performs a Rijndael AES-CTR encryption operation.
-/// 
+///
 /// Only a 128bit key size is supported by this Intel(R) SGX SDK cryptography library.
 ///
 /// # Description
-/// 
+///
 /// This function encrypts the input data stream of a variable length according to
 /// the CTR mode as specified in [NIST SP 800-38A]. The counter can be thought
 /// of as an IV which increments on successive encryption or decryption calls. For
@@ -1081,7 +1094,7 @@
 ///
 /// It is recommended that the source, destination and counter data buffers are
 /// allocated within the enclave.
-/// 
+///
 /// # Parameters
 ///
 /// **key**
@@ -1122,12 +1135,12 @@
 ///
 /// An internal cryptography library failure occurred.
 ///
-pub fn rsgx_aes_ctr_encrypt(key: &sgx_aes_ctr_128bit_key_t, 
-                            src: &[u8], 
-                            ctr: &sgx_aes_ctr_128bit_ctr_t, 
+pub fn rsgx_aes_ctr_encrypt(key: &sgx_aes_ctr_128bit_key_t,
+                            src: &[u8],
+                            ctr: &sgx_aes_ctr_128bit_ctr_t,
                             ctr_inc_bits: u32,
                             dst: &mut [u8]) -> SgxError {
-    
+
     let src_len = src.len();
     if src_len > u32::max_value() as usize {
         return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
@@ -1143,7 +1156,7 @@
         return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
     }
 
-    let ret = unsafe {        
+    let ret = unsafe {
         sgx_aes_ctr_encrypt(key as * const sgx_aes_ctr_128bit_key_t,
                             src.as_ptr(),
                             src_len as u32,
@@ -1159,11 +1172,11 @@
 
 ///
 /// rsgx_aes_ctr_decrypt performs a Rijndael AES-CTR decryption operation.
-/// 
+///
 /// Only a 128bit key size is supported by this Intel(R) SGX SDK cryptography library.
 ///
 /// # Description
-/// 
+///
 /// This function decrypts the input data stream of a variable length according to
 /// the CTR mode as specified in [NIST SP 800-38A]. The counter can be thought
 /// of as an IV which increments on successive encryption or decryption calls. For
@@ -1174,7 +1187,7 @@
 ///
 /// It is recommended that the source, destination and counter data buffers are
 /// allocated within the enclave.
-/// 
+///
 /// # Parameters
 ///
 /// **key**
@@ -1236,7 +1249,7 @@
         return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
     }
 
-    let ret = unsafe {     
+    let ret = unsafe {
         sgx_aes_ctr_decrypt(key as * const sgx_aes_ctr_128bit_key_t,
                             src.as_ptr(),
                             src.len() as u32,
@@ -1251,7 +1264,7 @@
 }
 
 fn rsgx_ecc256_open_context(ecc_handle: &mut sgx_ecc_state_handle_t) -> sgx_status_t {
-    
+
     unsafe { sgx_ecc256_open_context(ecc_handle as * mut _ as * mut sgx_ecc_state_handle_t) }
 }
 
@@ -1260,8 +1273,8 @@
     unsafe { sgx_ecc256_close_context(ecc_handle) }
 }
 
-fn rsgx_ecc256_create_key_pair(private: &mut sgx_ec256_private_t, 
-                               public: &mut sgx_ec256_public_t, 
+fn rsgx_ecc256_create_key_pair(private: &mut sgx_ec256_private_t,
+                               public: &mut sgx_ec256_public_t,
                                ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t {
     unsafe {
         sgx_ecc256_create_key_pair(private as * mut sgx_ec256_private_t,
@@ -1287,11 +1300,25 @@
     }
 }
 
-fn rsgx_ecdsa_sign_msg<T: Copy>(data: &T, 
-                                private: &sgx_ec256_private_t, 
-                                signature: &mut sgx_ec256_signature_t, 
-                                ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t {
-    
+fn rsgx_ecc256_compute_shared_dhkey512(private_b: &sgx_ec256_private_t,
+                                       public_ga: &sgx_ec256_public_t,
+                                       shared_key: &mut sgx_ec256_dh_shared512_t,
+                                       ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t {
+
+    unsafe {
+        sgx_ecc256_compute_shared_dhkey512(private_b as * const _ as * mut sgx_ec256_private_t,
+                                           public_ga as * const _ as * mut sgx_ec256_public_t,
+                                           shared_key as * mut sgx_ec256_dh_shared512_t,
+                                           ecc_handle)
+    }
+}
+
+fn rsgx_ecdsa_sign_msg<T>(data: &T,
+                          private: &sgx_ec256_private_t,
+                          signature: &mut sgx_ec256_signature_t,
+                          ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t
+    where T: Copy + ContiguousMemory {
+
     let size = mem::size_of::<T>();
     if size == 0 {
         return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
@@ -1301,20 +1328,21 @@
     }
 
     unsafe {
-        sgx_ecdsa_sign(data as * const _  as * const u8, 
-                       size as u32, 
+        sgx_ecdsa_sign(data as * const _  as * const u8,
+                       size as u32,
                        private as * const _ as * mut sgx_ec256_private_t,
                        signature as * mut sgx_ec256_signature_t,
                        ecc_handle)
     }
 }
 
-fn rsgx_ecdsa_sign_slice<T: Copy>(data: &[T], 
-                                  private: &sgx_ec256_private_t, 
-                                  signature: &mut sgx_ec256_signature_t, 
-                                  ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t {
-    
-    let size = mem::size_of::<T>() * data.len();
+fn rsgx_ecdsa_sign_slice<T>(data: &[T],
+                            private: &sgx_ec256_private_t,
+                            signature: &mut sgx_ec256_signature_t,
+                            ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t
+    where T: Copy + ContiguousMemory {
+
+    let size = mem::size_of_val(data);
     if size == 0 {
         return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
     }
@@ -1323,19 +1351,20 @@
     }
 
     unsafe {
-        sgx_ecdsa_sign(data.as_ptr() as * const _  as * const u8, 
-                       size as u32, 
+        sgx_ecdsa_sign(data.as_ptr() as * const _  as * const u8,
+                       size as u32,
                        private as * const _ as * mut sgx_ec256_private_t,
                        signature as * mut sgx_ec256_signature_t,
                        ecc_handle)
     }
 }
 
-fn rsgx_ecdsa_verify_msg<T: Copy>(data: &T, 
-                                  public: &sgx_ec256_public_t, 
-                                  signature: &sgx_ec256_signature_t, 
-                                  result: &mut sgx_generic_ecresult_t, 
-                                  ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t {
+fn rsgx_ecdsa_verify_msg<T>(data: &T,
+                            public: &sgx_ec256_public_t,
+                            signature: &sgx_ec256_signature_t,
+                            result: &mut sgx_generic_ecresult_t,
+                            ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t
+    where T: Copy + ContiguousMemory {
 
     let size = mem::size_of::<T>();
     if size == 0 {
@@ -1365,13 +1394,14 @@
     }
 }
 
-fn rsgx_ecdsa_verify_slice<T: Copy>(data: &[T], 
-                                    public: &sgx_ec256_public_t, 
-                                    signature: &sgx_ec256_signature_t, 
-                                    result: &mut sgx_generic_ecresult_t, 
-                                    ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t {
+fn rsgx_ecdsa_verify_slice<T>(data: &[T],
+                              public: &sgx_ec256_public_t,
+                              signature: &sgx_ec256_signature_t,
+                              result: &mut sgx_generic_ecresult_t,
+                              ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t
+    where T: Copy + ContiguousMemory {
 
-    let size = mem::size_of::<T>() * data.len();
+    let size = mem::size_of_val(data);
     if size == 0 {
         return sgx_status_t::SGX_ERROR_INVALID_PARAMETER;
     }
@@ -1402,12 +1432,12 @@
 ///
 /// ECC GF(p) context state.
 ///
-/// This is a handle to the ECC GF(p) context state allocated and initialized used to perform 
-/// elliptic curve cryptosystem standard functions. The algorithm stores the intermediate results 
+/// This is a handle to the ECC GF(p) context state allocated and initialized used to perform
+/// elliptic curve cryptosystem standard functions. The algorithm stores the intermediate results
 /// of calculations performed using this context.
 ///
 pub struct SgxEccHandle{
-    handle: RefCell<sgx_ecc_state_handle_t>, 
+    handle: RefCell<sgx_ecc_state_handle_t>,
     initflag: Cell<bool>,
 }
 
@@ -1418,16 +1448,16 @@
     ///
     pub fn new() -> Self {
         SgxEccHandle{
-            handle: RefCell::new(ptr::null_mut() as sgx_ecc_state_handle_t), 
+            handle: RefCell::new(ptr::null_mut() as sgx_ecc_state_handle_t),
             initflag: Cell::new(false),
             }
     }
 
     ///
-    /// open returns an allocated and initialized context for the elliptic curve cryptosystem 
+    /// open returns an allocated and initialized context for the elliptic curve cryptosystem
     /// over a prime finite field, GF(p).
     ///
-    /// This context must be created prior to calling create_key_pair or compute_shared_dhkey. 
+    /// This context must be created prior to calling create_key_pair or compute_shared_dhkey.
     /// When the calling code has completed its set of ECC operations, close should be called to
     /// cleanup and deallocate the ECC context.
     ///
@@ -1480,7 +1510,7 @@
     /// The ECC context state was not initialized properly due to an internal cryptography library failure.
     ///
     pub fn open(&self) -> SgxError {
-        
+
         if self.initflag.get() == true {
             return Ok(());
         }
@@ -1496,8 +1526,8 @@
     }
 
     ///
-    /// create_key_pair generates a private/public key pair on the ECC curve for the given 
-    /// cryptographic system. 
+    /// create_key_pair generates a private/public key pair on the ECC curve for the given
+    /// cryptographic system.
     ///
     /// open must be called to allocate and initialize the ECC context prior to making this call.
     ///
@@ -1523,7 +1553,7 @@
     ///
     /// **sgx_ec256_private_t**
     ///
-    /// The private key which is a number that lies in the range of [1, n-1] where n is the order 
+    /// The private key which is a number that lies in the range of [1, n-1] where n is the order
     /// of the elliptic curve base point.
     ///
     /// **sgx_ec256_public_t**
@@ -1551,7 +1581,7 @@
     /// The key creation process failed due to an internal cryptography library failure.
     ///
     pub fn create_key_pair(&self) -> SgxResult<(sgx_ec256_private_t, sgx_ec256_public_t)> {
-        
+
         if self.initflag.get() == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
         }
@@ -1567,7 +1597,7 @@
     }
 
     ///
-    /// check_point checks whether the input point is a valid point on the ECC curve for the given cryptographic system. 
+    /// check_point checks whether the input point is a valid point on the ECC curve for the given cryptographic system.
     ///
     /// open context must be called to allocate and initialize the ECC context prior to making this call.
     ///
@@ -1636,12 +1666,12 @@
     }
 
     ///
-    /// compute_shared_dhkey generates a secret key shared between two participants of the cryptosystem. 
+    /// compute_shared_dhkey generates a secret key shared between two participants of the cryptosystem.
     ///
     /// # Description
     ///
     /// This function computes the Diffie-Hellman shared key based on the enclave’s
-    /// own (local) private key and remote enclave’s public Ga Key. 
+    /// own (local) private key and remote enclave’s public Ga Key.
     ///
     /// The function computes a secret number sharedKey, which is a secret key
     /// shared between two participants of the cryptosystem.
@@ -1667,7 +1697,7 @@
     /// privKeyB: pubKeyB = privKeyB * G, where G is a base point of the elliptic curve.
     ///
     /// 4. Bob passes the public key to Alice.
-    /// 
+    ///
     /// 5. Alice gets Bob's public key and calculates the secret point shareKeyA. When
     /// calculating, she uses her own private key and Bob's public key and applies the
     /// following formula:
@@ -1726,7 +1756,7 @@
     /// The key creation process failed due to an internal cryptography library failure.
     ///
     pub fn compute_shared_dhkey(&self, private_b: &sgx_ec256_private_t, public_ga: &sgx_ec256_public_t) -> SgxResult<sgx_ec256_dh_shared_t> {
-        
+
         if self.initflag.get() == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
         }
@@ -1739,8 +1769,22 @@
         }
     }
 
+    pub fn compute_shared_dhkey512(&self, private_b: &sgx_ec256_private_t, public_ga: &sgx_ec256_public_t) -> SgxResult<sgx_ec256_dh_shared512_t> {
+
+        if self.initflag.get() == false {
+            return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
+        }
+
+        let mut shared_key = sgx_ec256_dh_shared512_t::default();
+        let ret = rsgx_ecc256_compute_shared_dhkey512(private_b, public_ga, &mut shared_key, *self.handle.borrow());
+        match ret {
+            sgx_status_t::SGX_SUCCESS => Ok(shared_key),
+            _ => Err(ret),
+        }
+    }
+
     ///
-    /// ecdsa_sign_msg computes a digital signature with a given private key over an input dataset. 
+    /// ecdsa_sign_msg computes a digital signature with a given private key over an input dataset.
     ///
     /// # Description
     ///
@@ -1799,8 +1843,9 @@
     ///
     /// The signature generation process failed due to an internal cryptography library failure.
     ///
-    pub fn ecdsa_sign_msg<T: Copy>(&self, data: &T, private: &sgx_ec256_private_t) -> SgxResult<sgx_ec256_signature_t> {
-        
+    pub fn ecdsa_sign_msg<T>(&self, data: &T, private: &sgx_ec256_private_t) -> SgxResult<sgx_ec256_signature_t>
+        where T: Copy + ContiguousMemory {
+
         if self.initflag.get() == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
         }
@@ -1814,10 +1859,11 @@
     }
 
     ///
-    /// ecdsa_sign_slice computes a digital signature with a given private key over an input dataset. 
+    /// ecdsa_sign_slice computes a digital signature with a given private key over an input dataset.
     ///
-    pub fn ecdsa_sign_slice<T: Copy>(&self, data: &[T], private: &sgx_ec256_private_t) -> SgxResult<sgx_ec256_signature_t> {
-        
+    pub fn ecdsa_sign_slice<T>(&self, data: &[T], private: &sgx_ec256_private_t) -> SgxResult<sgx_ec256_signature_t>
+        where T: Copy + ContiguousMemory {
+
         if self.initflag.get() == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
         }
@@ -1831,7 +1877,7 @@
     }
 
     ///
-    /// ecdsa_verify_msg verifies the input digital signature with a given public key over an input dataset. 
+    /// ecdsa_verify_msg verifies the input digital signature with a given public key over an input dataset.
     ///
     /// # Description
     ///
@@ -1890,12 +1936,16 @@
     ///
     /// The verification process failed due to an internal cryptography library failure.
     ///
-    pub fn ecdsa_verify_msg<T: Copy>(&self, data: &T, public: &sgx_ec256_public_t, signature: &sgx_ec256_signature_t) -> SgxResult<bool> {
-        
+    pub fn ecdsa_verify_msg<T>(&self,
+                               data: &T,
+                               public: &sgx_ec256_public_t,
+                               signature: &sgx_ec256_signature_t) -> SgxResult<bool>
+        where T: Copy + ContiguousMemory {
+
         if self.initflag.get() == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
         }
-        
+
         let mut result = sgx_generic_ecresult_t::default();
         let ret = rsgx_ecdsa_verify_msg(data, public, signature, &mut result, *self.handle.borrow());
         match ret {
@@ -1910,14 +1960,18 @@
     }
 
     ///
-    /// ecdsa_verify_slice verifies the input digital signature with a given public key over an input dataset. 
+    /// ecdsa_verify_slice verifies the input digital signature with a given public key over an input dataset.
     ///
-    pub fn ecdsa_verify_slice<T: Copy>(&self, data: &[T], public: &sgx_ec256_public_t, signature: &sgx_ec256_signature_t) -> SgxResult<bool> {
-        
+    pub fn ecdsa_verify_slice<T>(&self,
+                                 data: &[T],
+                                 public: &sgx_ec256_public_t,
+                                 signature: &sgx_ec256_signature_t) -> SgxResult<bool>
+        where T: Copy + ContiguousMemory {
+
         if self.initflag.get() == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
         }
-        
+
         let mut result = sgx_generic_ecresult_t::default();
         let ret = rsgx_ecdsa_verify_slice(data, public, signature, &mut result, *self.handle.borrow());
         match ret {
@@ -1930,13 +1984,13 @@
             _ => Err(ret),
         }
     }
-     
+
     ///
     /// close cleans up and deallocates the ECC 256 GF(p) state that was allocated in function open.
     ///
     /// # Description
     ///
-    /// close is used by calling code to deallocate memory used for storing the ECC 256 GF(p) state used 
+    /// close is used by calling code to deallocate memory used for storing the ECC 256 GF(p) state used
     /// in ECC cryptographic calculations.
     ///
     /// # Requirements
@@ -1963,7 +2017,7 @@
                 rsgx_ecc256_close_context(handle)
             }
         };
-         
+
         match ret {
             sgx_status_t::SGX_SUCCESS => {
                 self.initflag.set(false);
@@ -1988,4 +2042,4 @@
     fn drop(&mut self) {
         let _ = self.close();
     }
-}
\ No newline at end of file
+}
diff --git a/sgx_tcrypto/src/lib.rs b/sgx_tcrypto/src/lib.rs
index cd87880..d1d296a 100644
--- a/sgx_tcrypto/src/lib.rs
+++ b/sgx_tcrypto/src/lib.rs
@@ -28,7 +28,7 @@
 
 //! # Cryptography Library
 //!
-//! The Intel(R) Software Guard Extensions SDK includes a trusted cryptography library named sgx_tcrypto. 
+//! The Intel(R) Software Guard Extensions SDK includes a trusted cryptography library named sgx_tcrypto.
 //! It includes the cryptographic functions used by other trusted libraries included in the SDK
 //!
 #![crate_name = "sgx_tcrypto"]
@@ -44,5 +44,5 @@
 
 extern crate sgx_types;
 
-pub mod crypto;
-pub use self::crypto::*;
\ No newline at end of file
+mod crypto;
+pub use self::crypto::*;
diff --git a/sgx_tdh/Cargo.toml b/sgx_tdh/Cargo.toml
index 88eed37..5b0e295 100644
--- a/sgx_tdh/Cargo.toml
+++ b/sgx_tdh/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tdh"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Baidu"]
 
 [features]
diff --git a/sgx_tdh/src/dh.rs b/sgx_tdh/src/dh.rs
index 368a136..c364ee5 100644
--- a/sgx_tdh/src/dh.rs
+++ b/sgx_tdh/src/dh.rs
@@ -27,11 +27,13 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 //! # Diffie–Hellman (DH) Session Establishment Functions
-//! 
+//!
 //! These functions allow an ISV to establish secure session between two enclaves using the EC DH Key exchange protocol.
-//! 
+//!
 use sgx_types::*;
+use sgx_types::marker::ContiguousMemory;
 use sgx_trts::*;
+use sgx_trts::memeq::ConsttimeMemEq;
 use sgx_tcrypto::*;
 use sgx_tse::*;
 use core::mem;
@@ -63,17 +65,17 @@
 }
 
 impl SgxDhMsg3 {
-    /// 
+    ///
     /// Create a SgxDhMsg3 with default values.
-    /// 
+    ///
     pub fn new() -> Self {
         let dh_msg3 = SgxDhMsg3::default();
         dh_msg3
     }
 
-    /// 
+    ///
     /// Calculate the size of sgx_dh_msg3_t converted from SgxDhMsg3, really add the size of struct sgx_dh_msg3_t and msg3_body.additional_prop.
-    /// 
+    ///
     /// # Return value
     ///
     /// The size of sgx_dh_msg3_t needed.
@@ -87,21 +89,21 @@
         if additional_prop_len > (max as usize) - dh_msg3_size {
             return max;
         }
-     
+
         (dh_msg3_size + additional_prop_len) as u32
     }
 
     ///
     /// Convert SgxDhMsg3 to sgx_dh_msg3_t, this is an unsafe function.
-    /// 
+    ///
     /// # Parameters
-    /// 
+    ///
     /// **p**
-    /// 
+    ///
     /// The pointer of a sgx_dh_msg3_t buffer to save the buffer of SgxDhMsg3.
-    /// 
+    ///
     /// **len**
-    /// 
+    ///
     /// The size of the sgx_dh_msg3_t buffer.
     ///
     /// # Return value
@@ -139,34 +141,34 @@
 
         if additional_prop_len > 0 {
             let raw_msg3 = slice::from_raw_parts_mut(p as * mut u8, len as usize);
-            raw_msg3[dh_msg3_size..].copy_from_slice(&self.msg3_body.additional_prop); 
+            raw_msg3[dh_msg3_size..].copy_from_slice(&self.msg3_body.additional_prop);
         }
 
-        mem::forget(dh_msg3); 
+        mem::forget(dh_msg3);
         Some(p)
     }
 
-    /// 
+    ///
     /// Convert sgx_dh_msg3_t to SgxDhMsg3, this is an unsafe function.
-    /// 
+    ///
     /// # Parameters
-    /// 
+    ///
     /// **p**
-    /// 
+    ///
     /// The pointer of a sgx_dh_msg3_t buffer.
     ///
     /// **len**
-    /// 
+    ///
     /// The size of the sgx_dh_msg3_t buffer.
-    /// 
+    ///
     /// # Return value
-    /// 
+    ///
     /// **Some(SgxDhMsg3)**
     ///
     /// Indicates the conversion is successfully. The return value is SgxDhMsg3.
-    /// 
+    ///
     /// **None**
-    /// 
+    ///
     /// The parameters p and len are not available for the conversion.
     ///
     pub unsafe fn from_raw_dh_msg3_t(p: * mut sgx_dh_msg3_t, len: u32) -> Option<Self> {
@@ -177,7 +179,7 @@
         if rsgx_raw_is_within_enclave(p as * mut u8, len as usize) == false {
             return None;
         }
-        
+
         let raw_msg3 = Box::from_raw(p);
         let additional_prop_len = raw_msg3.msg3_body.additional_prop_length;
         let dh_msg3_size = mem::size_of::<sgx_dh_msg3_t>() as u32;
@@ -195,7 +197,7 @@
         if additional_prop_len > 0 {
             let mut additional_prop: Vec<u8> = vec![0_u8; additional_prop_len as usize];
             let ptr_additional_prop = p.offset(1) as * const u8;
-            ptr::copy_nonoverlapping(ptr_additional_prop, additional_prop.as_mut_ptr(), additional_prop_len as usize); 
+            ptr::copy_nonoverlapping(ptr_additional_prop, additional_prop.as_mut_ptr(), additional_prop_len as usize);
             dh_msg3.msg3_body.additional_prop = additional_prop.into_boxed_slice();
         }
 
@@ -219,7 +221,7 @@
 pub struct SgxDhResponder {
     state: SgxDhSessionState,
     prv_key: sgx_ec256_private_t,
-    pub_key: sgx_ec256_public_t, 
+    pub_key: sgx_ec256_public_t,
     smk_aek: sgx_key_128bit_t,
     shared_key: sgx_ec256_dh_shared_t,
 }
@@ -236,28 +238,30 @@
     }
 }
 
+unsafe impl ContiguousMemory for SgxDhResponder {}
+
 impl SgxDhResponder {
-    /// 
+    ///
     /// Initialize DH secure session responder.
-    /// 
+    ///
     /// Indicates role of responder  the caller plays in the secure session establishment.
-    /// 
+    ///
     /// The value of role of the responder of the session establishment must be `SGX_DH_SESSION_RESPONDER`.
     ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
+    ///
     pub fn init_session() -> Self {
         Self::default()
     }
     ///
-    /// Generates MSG1 for the responder of DH secure session establishment and records ECC key pair in session structure. 
+    /// Generates MSG1 for the responder of DH secure session establishment and records ECC key pair in session structure.
     ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
+    ///
     /// # Parameters
     ///
     /// **msg1**
@@ -266,25 +270,25 @@
     /// message, which is referenced by this parameter, must be within the enclave.
     /// The DH msg1 contains the responder’s public key and report based target
     /// info.
-    /// 
+    ///
     /// # Errors
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
+    ///
     /// Any of the input parameters is incorrect.
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_STATE**
-    /// 
+    ///
     /// The API is invoked in incorrect order or state.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// The enclave is out of memory.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
-    /// 
+    ///
     /// An unexpected error occurred.
-    /// 
+    ///
     pub fn gen_msg1(&mut self, msg1: &mut SgxDhMsg1) -> SgxError {
 
         if rsgx_data_is_within_enclave(self) == false {
@@ -310,78 +314,78 @@
             },
             _ => (),
         };
-        
+
         self.state = SgxDhSessionState::SGX_DH_SESSION_RESPONDER_WAIT_M2;
         Ok(())
     }
-    
-    /// 
+
+    ///
     /// The responder handles msg2 sent by initiator and then derives AEK, updates session information and generates msg3.
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
+    ///
     /// # Parameters
     ///
     /// **msg2**
     ///
     /// Point to dh message 2 buffer generated by session initiator, and the buffer must be in enclave address space.
-    /// 
+    ///
     /// **msg3**
-    /// 
+    ///
     /// Point to dh message 3 buffer generated by session responder in this function, and the buffer must be in enclave address space.
-    /// 
+    ///
     /// **aek**
     ///
     /// A pointer that points to instance of sgx_key_128bit_t. The aek is derived as follows:
-    /// 
+    ///
     /// ```
     /// KDK := CMAC(key0, LittleEndian(gab x-coordinate))
     /// AEK = AES-CMAC(KDK, 0x01||"AEK"||0x00||0x80||0x00)
     /// ```
     /// The key0 used in the key extraction operation is 16 bytes of 0x00. The plain
     /// text used in the AES-CMAC calculation of the KDK is the Diffie-Hellman shared
-    /// secret elliptic curve field element in Little Endian format.The plain text used 
+    /// secret elliptic curve field element in Little Endian format.The plain text used
     /// in the AEK calculation includes:
-    /// 
+    ///
     /// * a counter (0x01)
-    /// 
+    ///
     /// * a label: the ASCII representation of the string 'AEK' in Little Endian format
-    /// 
+    ///
     /// * a bit length (0x80)
-    /// 
+    ///
     /// **initiator_identity**
     ///
-    /// A pointer that points to instance of sgx_dh_session_enclave_identity_t. 
+    /// A pointer that points to instance of sgx_dh_session_enclave_identity_t.
     /// Identity information of initiator includes isv svn, isv product id, the
     /// enclave attributes, MRSIGNER, and MRENCLAVE. The buffer must be in
     /// enclave address space. The caller should check the identity of the peer and
     /// decide whether to trust the peer and use the aek.
-    /// 
+    ///
     /// # Errors
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
+    ///
     /// Any of the input parameters is incorrect.
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_STATE**
-    /// 
+    ///
     /// The API is invoked in incorrect order or state.
-    /// 
+    ///
     /// **SGX_ERROR_KDF_MISMATCH**
-    /// 
+    ///
     /// Indicates the key derivation function does not match.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// The enclave is out of memory.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
-    /// 
+    ///
     /// An unexpected error occurred.
-    /// 
-    pub fn proc_msg2(&mut self, 
+    ///
+    pub fn proc_msg2(&mut self,
                      msg2: &SgxDhMsg2,
                      msg3: &mut SgxDhMsg3,
                      aek: &mut sgx_key_128bit_t,
@@ -412,7 +416,7 @@
             self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
             return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
         }
-   
+
         let ecc_state = SgxEccHandle::new();
         try!(ecc_state.open().map_err(|ret| self.set_error(ret)));
         self.shared_key = try!(ecc_state.compute_shared_dhkey(&self.prv_key, &msg2.g_b).map_err(|ret| self.set_error(ret)));
@@ -440,7 +444,7 @@
     fn dh_generate_message1(&mut self, msg1: &mut SgxDhMsg1) -> SgxError {
 
         let target = sgx_target_info_t::default();
-        let report_data = sgx_report_data_t::default(); 
+        let report_data = sgx_report_data_t::default();
 
         let report = try!(rsgx_create_report(&target, &report_data));
 
@@ -452,13 +456,13 @@
         try!(ecc_state.open());
         let (prv_key, pub_key) = try!(ecc_state.create_key_pair());
 
-        self.prv_key = prv_key;                                                                    
+        self.prv_key = prv_key;
         self.pub_key = pub_key;
-        msg1.g_a = pub_key; 
+        msg1.g_a = pub_key;
 
         Ok(())
     }
-    
+
     fn dh_verify_message2(&self, msg2: &SgxDhMsg2) -> SgxError {
 
         let kdf_id = &msg2.report.body.report_data.d[SGX_SHA256_HASH_SIZE..SGX_SHA256_HASH_SIZE + 2];
@@ -469,7 +473,7 @@
         }
 
         let data_mac = try!(rsgx_rijndael128_cmac_msg(&self.smk_aek, &msg2.report));
-        if data_mac.eq(&msg2.cmac) == false {
+        if data_mac.consttime_memeq(&msg2.cmac) == false {
             return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
         }
 
@@ -484,7 +488,7 @@
         if msg_hash.eq(data_hash) == false {
             return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
         }
-        
+
         Ok(())
     }
 
@@ -507,20 +511,20 @@
         target.mr_enclave = msg2.report.body.mr_enclave;
         target.misc_select = msg2.report.body.misc_select;
         msg3.msg3_body.report = try!(rsgx_create_report(&target, &report_data));
-        
+
         let add_prop_len = msg3.msg3_body.additional_prop.len() as u32;
         let cmac_handle = SgxCmacHandle::new();
         try!(cmac_handle.init(&self.smk_aek));
         try!(cmac_handle.update_msg(&msg3.msg3_body.report));
         try!(cmac_handle.update_msg(&add_prop_len));
-        if add_prop_len > 0 { 
+        if add_prop_len > 0 {
             try!(cmac_handle.update_slice(&msg3.msg3_body.additional_prop));
         }
         msg3.cmac = try!(cmac_handle.get_hash());
-        
+
         Ok(())
     }
-    
+
     fn set_error(&mut self, sgx_ret: sgx_status_t) -> sgx_status_t {
 
         *self = Self::default();
@@ -530,7 +534,7 @@
             sgx_status_t::SGX_ERROR_KDF_MISMATCH => sgx_status_t::SGX_ERROR_KDF_MISMATCH,
             _ => sgx_status_t::SGX_ERROR_UNEXPECTED,
         };
-        ret   
+        ret
     }
 }
 
@@ -539,7 +543,7 @@
 pub struct SgxDhInitiator {
     state: SgxDhSessionState,
     smk_aek: sgx_key_128bit_t,
-    pub_key: sgx_ec256_public_t, 
+    pub_key: sgx_ec256_public_t,
     peer_pub_key: sgx_ec256_public_t,
     shared_key: sgx_ec256_dh_shared_t,
 }
@@ -556,54 +560,56 @@
     }
 }
 
+unsafe impl ContiguousMemory for SgxDhInitiator {}
+
 impl SgxDhInitiator {
-    /// 
+    ///
     /// Initialize DH secure session Initiator.
-    /// 
+    ///
     /// Indicates role of initiator the caller plays in the secure session establishment.
-    /// 
+    ///
     /// The value of role of the initiator of the session establishment must be `SGX_DH_SESSION_INITIATOR`.
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    /// 
+    ///
     pub fn init_session() -> Self {
         Self::default()
     }
 
-    /// 
-    /// The initiator of DH secure session establishment handles msg1 sent by responder and then generates msg2, 
+    ///
+    /// The initiator of DH secure session establishment handles msg1 sent by responder and then generates msg2,
     /// and records initiator’s ECC key pair in DH session structure.
     ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
+    ///
     /// # Parameters
-    /// 
+    ///
     /// **msg1**
     ///
     /// Point to dh message 1 buffer generated by session responder, and the buffer must be in enclave address space.
-    /// 
+    ///
     /// **msg2**
-    /// 
+    ///
     /// Point to dh message 2 buffer, and the buffer must be in enclave address space.
-    /// 
+    ///
     /// # Errors
     ///
     /// **SGX_ERROR_INVALID_PARAMETER**
     ///
     /// Any of the input parameters is incorrect.
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_STATE**
     ///
     /// The API is invoked in incorrect order or state.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// The enclave is out of memory.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
     ///
     /// An unexpected error occurred.
@@ -647,65 +653,65 @@
     /// session information and gets responder’s identity information.
     ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
+    ///
     /// # Parameters
-    /// 
+    ///
     /// **msg3**
-    /// 
+    ///
     /// Point to dh message 3 buffer generated by session responder, and the buffer must be in enclave address space.
-    /// 
+    ///
     /// **aek**
-    /// 
+    ///
     /// A pointer that points to instance of sgx_key_128bit_t. The aek is derived as follows:
-    /// 
+    ///
     /// ```
     /// KDK:= CMAC(key0, LittleEndian(gab x-coordinate))
     /// AEK = AES-CMAC(KDK, 0x01||"AEK"||0x00||0x80||0x00)
     /// ```
-    /// 
+    ///
     /// The key0 used in the key extraction operation is 16 bytes of 0x00. The plain
     /// text used in the AES-CMAC calculation of the KDK is the Diffie-Hellman shared
     /// secret elliptic curve field element in Little Endian format.
     /// The plain text used in the AEK calculation includes:
-    /// 
+    ///
     /// * a counter (0x01)
-    /// 
+    ///
     /// * a label: the ASCII representation of the string 'AEK' in Little Endian format
-    /// 
+    ///
     /// * a bit length (0x80)
-    /// 
+    ///
     /// **responder_identity**
-    /// 
+    ///
     /// Identity information of responder including isv svn, isv product id, the enclave
-    /// attributes, MRSIGNER, and MRENCLAVE. The buffer must be in enclave address space. 
-    /// The caller should check the identity of the peer and decide whether to trust the 
+    /// attributes, MRSIGNER, and MRENCLAVE. The buffer must be in enclave address space.
+    /// The caller should check the identity of the peer and decide whether to trust the
     /// peer and use the aek or the msg3_body.additional_prop field of msg3.
-    /// 
+    ///
     /// # Errors
     ///
     /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
+    ///
     /// Any of the input parameters is incorrect.
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_STATE**
-    /// 
+    ///
     /// The API is invoked in incorrect order or state.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// The enclave is out of memory.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
-    /// 
+    ///
     /// An unexpected error occurred.
-    /// 
-    pub fn proc_msg3(&mut self, 
-                     msg3: &SgxDhMsg3, 
+    ///
+    pub fn proc_msg3(&mut self,
+                     msg3: &SgxDhMsg3,
                      aek: &mut sgx_key_128bit_t,
                      responder_identity: &mut sgx_dh_session_enclave_identity_t) -> SgxError {
-        
+
         if rsgx_data_is_within_enclave(self) == false {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
         }
@@ -733,7 +739,7 @@
 
         try!(self.dh_verify_message3(msg3).map_err(|ret| self.set_error(ret)));
         * aek = try!(derive_key(&self.shared_key, &EC_AEK_LABEL).map_err(|ret| self.set_error(ret)));
-       
+
         *self = Self::default();
         self.state = SgxDhSessionState::SGX_DH_SESSION_ACTIVE;
 
@@ -763,7 +769,7 @@
         let mut report_data = sgx_report_data_t::default();
         report_data.d[..SGX_SHA256_HASH_SIZE].copy_from_slice(&msg_hash);
         report_data.d[SGX_SHA256_HASH_SIZE..SGX_SHA256_HASH_SIZE + 2].copy_from_slice(&AES_CMAC_KDF_ID);
-        
+
         msg2.report = try!(rsgx_create_report(&msg1.target, &report_data));
         msg2.cmac = try!(rsgx_rijndael128_cmac_msg(&self.smk_aek, &msg2.report));
 
@@ -783,18 +789,18 @@
         }
         let data_mac = try!(cmac_handle.get_hash());
 
-        if data_mac.eq(&msg3.cmac) == false {
+        if data_mac.consttime_memeq(&msg3.cmac) == false {
             return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
         }
 
         try!(rsgx_verify_report(&msg3.msg3_body.report));
-    
+
         let sha_handle = SgxShaHandle::new();
         try!(sha_handle.init());
         try!(sha_handle.update_msg(&self.pub_key));
         try!(sha_handle.update_msg(&self.peer_pub_key));
         let msg_hash = try!(sha_handle.get_hash());
-        
+
         let data_hash = &msg3.msg3_body.report.body.report_data.d[..SGX_SHA256_HASH_SIZE];
         if msg_hash.eq(data_hash) == false {
             return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
@@ -811,6 +817,6 @@
             sgx_status_t::SGX_ERROR_OUT_OF_MEMORY => sgx_status_t::SGX_ERROR_OUT_OF_MEMORY,
             _ => sgx_status_t::SGX_ERROR_UNEXPECTED,
         };
-        ret   
+        ret
     }
 }
diff --git a/sgx_tdh/src/ecp.rs b/sgx_tdh/src/ecp.rs
index dfe2459..a168af1 100644
--- a/sgx_tdh/src/ecp.rs
+++ b/sgx_tdh/src/ecp.rs
@@ -35,7 +35,7 @@
 pub const EC_AEK_LABEL: [u8; EC_LABEL_LENGTH] = [0x41, 0x45, 0x4B];
 pub const EC_DERIVATION_BUFFER_SIZE: usize = 7;
 
-pub fn derive_key(shared_key: &sgx_ec256_dh_shared_t, 
+pub fn derive_key(shared_key: &sgx_ec256_dh_shared_t,
                   label: &[u8; EC_LABEL_LENGTH]) -> SgxResult<sgx_ec_key_128bit_t> {
 
     let cmac_key = sgx_cmac_128bit_key_t::default();
@@ -62,5 +62,5 @@
         sgx_status_t::SGX_ERROR_OUT_OF_MEMORY => sgx_status_t::SGX_ERROR_OUT_OF_MEMORY,
         _ => sgx_status_t::SGX_ERROR_UNEXPECTED,
     };
-    ret   
-}
\ No newline at end of file
+    ret
+}
diff --git a/sgx_tdh/src/lib.rs b/sgx_tdh/src/lib.rs
index f63c926..a06b7ba 100644
--- a/sgx_tdh/src/lib.rs
+++ b/sgx_tdh/src/lib.rs
@@ -27,18 +27,18 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 //! # Diffie–Hellman (DH) Session Establishment Functions
-//! 
+//!
 //! These functions allow an ISV to establish secure session between two enclaves using the EC DH Key exchange protocol.
-//! 
+//!
 #![crate_name = "sgx_tdh"]
 #![crate_type = "rlib"]
 
 #![cfg_attr(not(feature = "use_std"), no_std)]
 
 #![cfg_attr(not(feature = "use_std"), feature(alloc, collections))]
-
 #![allow(non_camel_case_types)]
 #![allow(unused_assignments)]
+#![allow(deprecated)]
 
 #[cfg(feature = "use_std")]
 #[macro_use]
@@ -56,7 +56,7 @@
 extern crate sgx_tcrypto;
 extern crate sgx_tse;
 
-pub mod dh;
+mod dh;
 pub use self::dh::*;
 
 mod ecp;
diff --git a/sgx_tkey_exchange/Cargo.toml b/sgx_tkey_exchange/Cargo.toml
index dfe672c..2ead223 100644
--- a/sgx_tkey_exchange/Cargo.toml
+++ b/sgx_tkey_exchange/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tkey_exchange"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Baidu"]
 
 [features]
diff --git a/sgx_tkey_exchange/src/lib.rs b/sgx_tkey_exchange/src/lib.rs
index 355bd2a..97ebced 100644
--- a/sgx_tkey_exchange/src/lib.rs
+++ b/sgx_tkey_exchange/src/lib.rs
@@ -28,8 +28,8 @@
 
 //! # Trusted Key Exchange Library
 //!
-//! The library allow an ISV to exchange secrets between its server and its enclaves. They are used in 
-//! concert with untrusted Key Exchange functions. 
+//! The library allow an ISV to exchange secrets between its server and its enclaves. They are used in
+//! concert with untrusted Key Exchange functions.
 //!
 #![crate_name = "sgx_tkey_exchange"]
 #![crate_type = "rlib"]
@@ -44,7 +44,7 @@
 ///
 /// # Description
 ///
-/// This is the first API user should call for a key exchange process. The context returned from this 
+/// This is the first API user should call for a key exchange process. The context returned from this
 /// function is used as a handle for other APIs in the key exchange library.
 ///
 /// # Parameters
@@ -55,8 +55,8 @@
 ///
 /// **b_pse**
 ///
-/// If true, platform service information is needed in message 3. The caller should make sure a PSE session 
-/// has been established using rsgx_create_pse_session before attempting to establish a remote attestation 
+/// If true, platform service information is needed in message 3. The caller should make sure a PSE session
+/// has been established using rsgx_create_pse_session before attempting to establish a remote attestation
 /// and key exchange session involving platform service information.
 ///
 /// # Requirements
@@ -67,7 +67,7 @@
 ///
 /// # Return value
 ///
-/// The output context for the subsequent remote attestation and key exchange process, to be used in 
+/// The output context for the subsequent remote attestation and key exchange process, to be used in
 /// sgx_ra_get_msg1 and sgx_ra_proc_msg2.
 ///
 /// # Errors
@@ -88,12 +88,12 @@
 ///
 /// Indicates that an unexpected error occurred.
 ///
-pub fn rsgx_ra_init(p_pub_key: &sgx_ec256_public_t, b_pse: i32) -> SgxResult<sgx_ra_context_t> {    
-    
+pub fn rsgx_ra_init(p_pub_key: &sgx_ec256_public_t, b_pse: i32) -> SgxResult<sgx_ra_context_t> {
+
     let mut context: sgx_ra_context_t = 0;
     let ret = unsafe {
-        sgx_ra_init(p_pub_key as * const sgx_ec256_public_t, 
-                    b_pse, 
+        sgx_ra_init(p_pub_key as * const sgx_ec256_public_t,
+                    b_pse,
                     &mut context as * mut sgx_ra_context_t)
     };
     match ret {
@@ -103,12 +103,12 @@
 }
 
 ///
-/// The rsgx_ra_init_ex function creates a context for the remote attestation and key exchange process 
+/// The rsgx_ra_init_ex function creates a context for the remote attestation and key exchange process
 /// while it allows the use of a custom defined Key Derivation Function (KDF).
 ///
 /// # Description
 ///
-/// This is the first API user should call for a key exchange process. The context returned from this 
+/// This is the first API user should call for a key exchange process. The context returned from this
 /// function is used as a handle for other APIs in the key exchange library.
 ///
 /// # Parameters
@@ -119,14 +119,14 @@
 ///
 /// **b_pse**
 ///
-/// If true, platform service information is needed in message 3. The caller should make sure a PSE session 
-/// has been established using rsgx_create_pse_session before attempting to establish a remote attestation 
+/// If true, platform service information is needed in message 3. The caller should make sure a PSE session
+/// has been established using rsgx_create_pse_session before attempting to establish a remote attestation
 /// and key exchange session involving platform service information.
 ///
 /// **derive_key_cb**
 ///
-/// This a pointer to a call back routine matching the funtion prototype of sgx_ra_derive_secret_keys_t. 
-/// This function takes the Diffie-Hellman shared secret as input to allow the ISV enclave to generate 
+/// This a pointer to a call back routine matching the funtion prototype of sgx_ra_derive_secret_keys_t.
+/// This function takes the Diffie-Hellman shared secret as input to allow the ISV enclave to generate
 /// their own derived shared keys (SMK, SK, MK and VK).
 ///
 /// # Requirements
@@ -137,7 +137,7 @@
 ///
 /// # Return value
 ///
-/// The output context for the subsequent remote attestation and key exchange process, to be used in 
+/// The output context for the subsequent remote attestation and key exchange process, to be used in
 /// sgx_ra_get_msg1 and sgx_ra_proc_msg2.
 ///
 /// # Errors
@@ -160,7 +160,7 @@
 ///
 pub fn rsgx_ra_init_ex(p_pub_key: &sgx_ec256_public_t,
                        b_pse: i32,
-                       derive_key_cb: sgx_ra_derive_secret_keys_t) -> SgxResult<sgx_ra_context_t> {  
+                       derive_key_cb: sgx_ra_derive_secret_keys_t) -> SgxResult<sgx_ra_context_t> {
 
     let mut context: sgx_ra_context_t = 0;
     let ret = unsafe {
@@ -172,18 +172,18 @@
     match ret {
         sgx_status_t::SGX_SUCCESS => Ok(context),
         _ => Err(ret),
-    }  
+    }
 }
 
 ///
-/// The sgx_ra_get_keys function is used to get the negotiated keys of a remote attestation and key exchange session. 
+/// The sgx_ra_get_keys function is used to get the negotiated keys of a remote attestation and key exchange session.
 ///
-/// This function should only be called after the service provider accepts the remote attestation and key exchange 
+/// This function should only be called after the service provider accepts the remote attestation and key exchange
 /// protocol message 3 produced by sgx_ra_proc_msg2.
 ///
 /// # Description
 ///
-/// After a successful key exchange process, this API can be used in the enclave to get specific key associated 
+/// After a successful key exchange process, this API can be used in the enclave to get specific key associated
 /// with this remote attestation and key exchange session.
 ///
 /// # Parameters
@@ -214,7 +214,7 @@
 ///
 /// **SGX_ERROR_INVALID_STATE**
 ///
-/// Indicates this API is invoked in incorrect order, it can be called only after a success session has been established. 
+/// Indicates this API is invoked in incorrect order, it can be called only after a success session has been established.
 /// In other words, sgx_ra_proc_msg2 should have been called and no error returned.
 ///
 pub fn rsgx_ra_get_keys(context: sgx_ra_context_t, keytype: sgx_ra_key_type_t) -> SgxResult<sgx_ra_key_128_t> {
@@ -232,12 +232,12 @@
 ///
 /// rsgx_ra_close release context created by rsgx_ra_init or rsgx_ra_init_ex.
 ///
-/// Call the rsgx_ra_close function to release the remote attestation and key exchange context after 
+/// Call the rsgx_ra_close function to release the remote attestation and key exchange context after
 /// the process is done and the context isn’t needed anymore.
 ///
 /// # Description
 ///
-/// At the end of a key exchange process, the caller needs to use this API in an enclave to clear and 
+/// At the end of a key exchange process, the caller needs to use this API in an enclave to clear and
 /// free memory associated with this remote attestation session.
 ///
 /// # Parameters
diff --git a/sgx_trts/Cargo.toml b/sgx_trts/Cargo.toml
index fd1e9df..3729331 100644
--- a/sgx_trts/Cargo.toml
+++ b/sgx_trts/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_trts"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Baidu"]
 
 [features]
@@ -9,3 +9,4 @@
 
 [dependencies]
 sgx_types = { path = "../sgx_types" }
+
diff --git a/sgx_trts/src/enclave.rs b/sgx_trts/src/enclave.rs
new file mode 100644
index 0000000..440d031
--- /dev/null
+++ b/sgx_trts/src/enclave.rs
@@ -0,0 +1,376 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//! Get metadata
+
+use sgx_types::*;
+
+#[link(name = "sgx_tservice")]
+extern {
+    static g_global_data: global_data_t;
+}
+
+#[link(name = "sgx_trts")]
+extern {
+    pub fn get_thread_data() -> * const c_void;
+    pub fn get_enclave_base() -> * const c_void;
+    pub fn get_heap_base() -> * const c_void;
+    pub fn get_heap_size() -> size_t;
+}
+
+#[repr(C)]
+struct global_data_t {
+    enclave_size: usize,
+    heap_offset: usize,
+    heap_size: usize,
+    thread_policy: u32,
+    reserved: u32,
+    td_template: thread_data_t,
+}
+
+#[repr(C)]
+struct thread_data_t {
+    self_addr: usize,
+    last_sp: usize,
+    stack_base_addr: usize,
+    stack_limit_addr: usize,
+    first_ssa_gpr: usize,
+    stack_guard: usize,
+    reserved: usize,
+    ssa_frame_size: usize,
+    last_error: usize,
+    m_next: usize,
+    tls_addr: usize,
+    tls_array: usize,
+    exception_flag: usize,
+    cxx_thread_info: [usize; 6],
+}
+
+#[derive(Copy, Clone)]
+pub struct SgxGlobalData {
+    enclave_base: usize,
+    enclave_size: usize,
+    heap_base: usize,
+    heap_offset: usize,
+    heap_size: usize,
+    thread_policy: SgxThreadPolicy,
+}
+
+impl SgxGlobalData {
+
+    ///
+    /// get global_data.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn new() -> Self {
+        SgxGlobalData {
+           enclave_base: rsgx_get_enclave_base() as usize,
+           enclave_size: rsgx_get_enclave_size(),
+           heap_base: rsgx_get_heap_base() as usize,
+           heap_offset: rsgx_get_heap_offset(),
+           heap_size: rsgx_get_heap_size(),
+           thread_policy: rsgx_get_thread_policy(),
+        }
+    }
+
+    ///
+    /// enclave_base is to get enclave map base address.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn enclave_base(&self) -> usize {
+        self.enclave_base
+    }
+    ///
+    /// enclave_size is to get enclave map size.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn enclave_size(&self) -> usize {
+        self.enclave_size
+    }
+    ///
+    /// heap_base is to get heap base address.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn heap_base(&self) -> usize {
+        self.heap_base
+    }
+    ///
+    /// heap_offset is to get heap offset.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn heap_offset(&self) -> usize {
+        self.heap_offset
+    }
+    ///
+    /// heap_size is to get heap size.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn heap_size(&self) -> usize {
+        self.heap_size
+    }
+    ///
+    /// thread_policy is to get TCS policy.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn thread_policy(&self) -> SgxThreadPolicy {
+        self.thread_policy
+    }
+}
+
+#[allow(dead_code)]
+#[derive(Copy, Clone)]
+pub struct SgxThreadData {
+    td_addr: usize,
+    last_sp: usize,
+    stack_base_addr: usize,
+    stack_limit_addr: usize,
+    first_ssa_gpr: usize,
+    stack_guard: usize,
+    ssa_frame_size: usize,
+    last_error: usize,
+    tls_addr: usize,
+    tls_array: usize,
+    exception_flag: usize,
+    cxx_thread_info: [usize; 6],
+}
+
+impl SgxThreadData {
+
+    ///
+    /// get thread_data per thread.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn new() -> Self {
+        let td = unsafe {
+            let p = rsgx_get_thread_data() as * const thread_data_t;
+            &*p
+        };
+        SgxThreadData {
+            td_addr: td.self_addr,
+            last_sp: td.last_sp,
+            stack_base_addr: td.stack_base_addr,
+            stack_limit_addr: td.stack_limit_addr,
+            first_ssa_gpr: td.first_ssa_gpr,
+            stack_guard: td.stack_guard,
+            ssa_frame_size: td.ssa_frame_size,
+            last_error: td.last_error,
+            tls_addr: td.tls_addr,
+            tls_array: td.tls_array,
+            exception_flag: td.exception_flag,
+            cxx_thread_info: td.cxx_thread_info,
+        }
+    }
+
+    ///
+    /// td_base is to get TD base address per thread.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn td_base(&self) -> usize {
+        self.td_addr
+    }
+    ///
+    /// stack_base is to get stack base address per thread.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn stack_base(&self) -> usize {
+        self.stack_base_addr
+    }
+    ///
+    /// stack_limit is to get stack limit per thread.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn stack_limit(&self) -> usize {
+        self.stack_limit_addr
+    }
+    ///
+    /// tls_base is to get tls base address per thread.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn tls_base(&self) -> usize {
+        self.tls_addr
+    }
+    ///
+    /// last_error is to get last error per thread.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn last_error(&self) -> usize {
+        self.last_error
+    }
+    ///
+    /// exception_flag is to get exception flag per thread.
+    ///
+    /// **Note**
+    ///
+    /// This API is only an experimental funtion.
+    ///
+    pub fn exception_flag(&self) -> usize {
+        self.exception_flag
+    }
+}
+
+#[derive(Copy, Clone)]
+pub enum SgxThreadPolicy {
+    Bound,
+    Unbound
+}
+
+///
+/// rsgx_get_thread_data is to get TD base address per thread.
+///
+/// **Note**
+///
+/// This API is only an experimental funtion.
+///
+#[inline]
+pub fn rsgx_get_thread_data() -> * const u8 {
+
+    unsafe { get_thread_data() as * const u8 }
+}
+
+///
+/// rsgx_get_enclave_base is to get enclave image base address.
+///
+/// **Note**
+///
+/// This API is only an experimental funtion.
+///
+#[inline]
+pub fn rsgx_get_enclave_base() -> * const u8 {
+
+    unsafe { get_enclave_base() as * const u8 }
+}
+
+///
+/// rsgx_get_enclave_size is to get enclave image size.
+///
+/// **Note**
+///
+/// This API is only an experimental funtion.
+///
+#[inline]
+pub fn rsgx_get_enclave_size() -> usize {
+
+    unsafe{ g_global_data.enclave_size }
+}
+
+///
+/// rsgx_get_heap_base is to get enclave heap base address.
+///
+/// **Note**
+///
+/// This API is only an experimental funtion.
+///
+#[inline]
+pub fn rsgx_get_heap_base() -> * const u8 {
+
+    unsafe { get_heap_base() as * const u8 }
+}
+
+///
+/// rsgx_get_heap_offset is to get enclave heap offset.
+///
+/// **Note**
+///
+/// This API is only an experimental funtion.
+///
+#[inline]
+pub fn rsgx_get_heap_offset() -> usize {
+
+    unsafe{ g_global_data.heap_offset }
+}
+
+///
+/// rsgx_get_heap_size is to get enclave heap size.
+///
+/// **Note**
+///
+/// This API is only an experimental funtion.
+///
+#[inline]
+pub fn rsgx_get_heap_size() -> usize {
+
+    unsafe { get_heap_size() }
+}
+
+///
+/// rsgx_get_thread_policy is to get TCS management policy.
+///
+/// **Note**
+///
+/// This API is only an experimental funtion.
+///
+#[inline]
+pub fn rsgx_get_thread_policy() -> SgxThreadPolicy {
+
+    unsafe {
+        if g_global_data.thread_policy != 0 {
+            SgxThreadPolicy::Unbound
+        } else {
+            SgxThreadPolicy::Bound
+        }
+    }
+}
diff --git a/sgx_trts/src/lib.rs b/sgx_trts/src/lib.rs
index e815cba..47b800a 100644
--- a/sgx_trts/src/lib.rs
+++ b/sgx_trts/src/lib.rs
@@ -28,7 +28,7 @@
 
 //! # Trusted Runtime System
 //!
-//! The Intel(R) SGX trusted runtime system (tRTS) is a key component of the Intel(R) Software Guard Extensions SDK. 
+//! The Intel(R) SGX trusted runtime system (tRTS) is a key component of the Intel(R) Software Guard Extensions SDK.
 //! It provides the enclave entry point logic as well as other functions to be used by enclave developers.
 //!
 //! **Intel(R) Software Guard Extensions Helper Functions**
@@ -36,8 +36,8 @@
 //! **CustomExceptionHandling**
 //!
 //! # Intel(R) Software Guard Extensions Helper Functions
-//! 
-//! The tRTS provides the helper functions for you to determine whether a given address is within or outside 
+//!
+//! The tRTS provides the helper functions for you to determine whether a given address is within or outside
 //! enclave memory.
 //!
 //! The tRTS provides a wrapper to the RDRAND instruction to generate a true random number from hardware.
@@ -45,17 +45,17 @@
 //!
 //! # CustomExceptionHandling
 //!
-//! The Intel(R) Software Guard Extensions SDK provides an API to allow you to register functions, or exception handlers, 
-//! to handle a limited set of hardware exceptions. When one of the enclave supported hardware exceptions occurs within 
-//! the enclave, the registered exception handlers will be called in a specific order until an exception handler reports 
-//! that it has handled the exception. For example, issuing a CPUID instruction inside an Enclave will result in a #UD fault 
-//! (Invalid Opcode Exception). ISV enclave code can call rsgx_register_exception_handler to register a function of type 
-//! sgx_exception_handler_t to respond to this exception. To check a list of enclave supported exceptions, see Intel(R) 
+//! The Intel(R) Software Guard Extensions SDK provides an API to allow you to register functions, or exception handlers,
+//! to handle a limited set of hardware exceptions. When one of the enclave supported hardware exceptions occurs within
+//! the enclave, the registered exception handlers will be called in a specific order until an exception handler reports
+//! that it has handled the exception. For example, issuing a CPUID instruction inside an Enclave will result in a #UD fault
+//! (Invalid Opcode Exception). ISV enclave code can call rsgx_register_exception_handler to register a function of type
+//! sgx_exception_handler_t to respond to this exception. To check a list of enclave supported exceptions, see Intel(R)
 //! Software Guard Extensions Programming Reference.
-//! 
+//!
 //! **Note**
 //!
-//! Custom exception handling is only supported in HW mode. Although the exception handlers can be registered in simulation mode, 
+//! Custom exception handling is only supported in HW mode. Although the exception handlers can be registered in simulation mode,
 //! the exceptions cannot be caught and handled within the enclave.
 //!
 //! **Note**
@@ -64,7 +64,7 @@
 //!
 //! **Note**
 //!
-//! Custom exception handing only saves general purpose registers in sgx_ exception_info_t. You should be careful when touching 
+//! Custom exception handing only saves general purpose registers in sgx_ exception_info_t. You should be careful when touching
 //! other registers in the exception handlers.
 //!
 //! **Note**
@@ -76,317 +76,66 @@
 #![crate_type = "rlib"]
 
 #![cfg_attr(not(feature = "use_std"), no_std)]
+#![cfg_attr(not(feature = "use_std"), needs_panic_runtime)]
+#![feature(const_fn)]
+#![feature(allow_internal_unstable)]
+#![feature(core_intrinsics)]
+#![feature(alloc)]
+#![feature(oom)]
+#![cfg_attr(not(feature = "use_std"), feature(collections))]
+#![cfg_attr(not(feature = "use_std"), feature(unique, shared))]
+#![cfg_attr(not(feature = "use_std"), feature(integer_atomics))]
+#![cfg_attr(not(feature = "use_std"), feature(cfg_target_has_atomic))]
+#![cfg_attr(not(feature = "use_std"), feature(optin_builtin_traits))]
+#![cfg_attr(not(feature = "use_std"), feature(unboxed_closures))]
+#![cfg_attr(not(feature = "use_std"), feature(fn_traits))]
+#![cfg_attr(not(feature = "use_std"), feature(raw))]
+#![cfg_attr(not(feature = "use_std"), feature(lang_items))]
+#![cfg_attr(not(feature = "use_std"), feature(needs_panic_runtime))]
+#![cfg_attr(not(feature = "use_std"), feature(untagged_unions))]
+#![cfg_attr(not(feature = "use_std"), feature(unwind_attributes))]
+
 #![allow(non_camel_case_types)]
+#![allow(deprecated)]
 
 #[cfg(feature = "use_std")]
 extern crate std as core;
 
+extern crate alloc;
+#[cfg(not(feature = "use_std"))]
+extern crate collections;
+
+#[macro_use]
 extern crate sgx_types;
-use sgx_types::*;
-use core::mem;
 
-///
-/// rsgx_read_rand function is used to generate a random number inside the enclave.
-///
-/// # Description
-///
-/// The rsgx_read_rand function is provided to replace the standard pseudo-random sequence generation functions 
-/// inside the enclave, since these standard functions are not supported in the enclave, such as rand, srand, etc. 
-/// For HW mode, the function generates a real-random sequence; while for simulation mode, the function generates 
-/// a pseudo-random sequence.
-///
-/// # Parameters
-///
-/// **rand**
-///
-/// A pointer to the buffer that receives the random number. The rand buffer can be either within or outside the enclave, 
-/// but it is not allowed to be across the enclave boundary or wrapped around.
-///
-/// # Requirements
-///
-/// Library: libsgx_trts.a
-///
-/// # Errors
-///
-/// **SGX_ERROR_INVALID_PARAMETER**
-///
-/// Invalid input parameters detected.
-///
-/// **SGX_ERROR_UNEXPECTED**
-///
-/// Indicates an unexpected error occurs during the valid random number gen- eration process.
-///
-pub fn rsgx_read_rand(rand: &mut [u8]) -> SgxError {
+mod veh;
+pub use self::veh::*;
 
-    let ret = unsafe { sgx_read_rand(rand.as_mut_ptr(), rand.len()) };
-    match ret {
-        sgx_status_t::SGX_SUCCESS => Ok(()),
-        _ => Err(ret),
+mod trts;
+pub use self::trts::*;
+
+pub mod enclave;
+
+pub mod memeq;
+
+#[macro_use]
+pub mod local;
+pub use self::local::{LocalKey, LocalKeyState};
+
+#[cfg(not(feature = "use_std"))]
+pub mod panicking;
+
+#[cfg(not(feature = "use_std"))]
+pub mod panic;
+
+#[macro_use]
+mod macros;
+
+pub mod oom;
+
+init_global_object! {
+    INIT_OOM, init_oom_handler = {
+        alloc::oom::set_oom_handler(oom::rsgx_oom);
     }
 }
 
-
-pub type exception_handle = * const c_void;
-
-///
-/// rsgx_register_exception_handler register an exception handler.
-///
-/// rsgx_register_exception_handler allows developers to register an exception handler, and specify whether to prepend 
-/// (when is_first_handler is equal to 1) or append the handler to the handler chain.
-///
-/// # Description
-///
-/// The Intel(R) SGX SDK supports the registration of custom exception handler functions. You can write your own code to 
-/// handle a limited set of hardware exceptions. For example, a CPUID instruction inside an enclave will effectively result 
-/// in a #UD fault (Invalid Opcode Exception). ISV enclave code can have an exception handler to prevent the enclave from 
-/// being trapped into an exception condition. 
-///
-/// Calling rsgx_register_exception_handler allows you to register an exception handler, and specify whether to prepend 
-/// (when is_first_handler is nonzero) or append the handler to the handler chain.
-///
-/// After calling rsgx_register_exception_handler to prepend an exception handler, a subsequent call to this function may 
-/// add another exception handler at the beginning of the handler chain. Therefore the order in which exception handlers 
-/// are called does not only depend on the value of the is_first_handler parameter, but more importantly depends on the order 
-/// in which exception handlers are registered.
-///
-/// # Parameters
-///
-/// **is_first_handler**
-///
-/// Specify the order in which the handler should be called. If the parameter is nonzero, the handler is the first handler 
-/// to be called. If the parameter is zero, the handler is the last handler to be called.
-///
-/// **exception_handler**
-///
-/// The exception handler to be called
-///
-/// # Requirements
-///
-/// Library: libsgx_trts.a
-///
-/// # Return value
-///
-/// **Some(exception_handle)**
-///
-/// Indicates the exception handler is registered successfully. The return value is an open handle to the custom exception handler.
-///
-/// **None**
-///
-/// The exception handler was not registered.
-///
-pub fn rsgx_register_exception_handler(is_first_handler: u32, exception_handler: sgx_exception_handler_t) -> Option<exception_handle> {
-    
-    let handle = unsafe {
-        sgx_register_exception_handler(is_first_handler, exception_handler)
-    };
-
-    if handle.is_null() { None } else { Some(handle) }
-}
-
-///
-/// rsgx_unregister_exception_handler is used to unregister a custom exception handler.
-///
-/// # Description
-///
-/// The Intel(R) SGX SDK supports the registration of custom exception handler functions. An enclave developer 
-/// can write their own code to handle a limited set of hardware exceptions. 
-///
-/// Calling rsgx_unregister_exception_handler allows developers to unregister an exception handler that was registered earlier.
-///
-/// # Parameters
-///
-/// **handle**
-///
-/// A handle to the custom exception handler previously registered using the rsgx_register_exception_handler function.
-///
-/// # Requirements
-///
-/// Library: libsgx_trts.a
-///
-/// # Return value
-///
-/// **true**
-///
-/// The custom exception handler is unregistered successfully.
-///
-/// **false**
-///
-/// The exception handler was not unregistered (not a valid pointer, handler not found).
-///
-pub fn rsgx_unregister_exception_handler(handle: exception_handle) -> bool {
-
-    let ret = unsafe { sgx_unregister_exception_handler(handle) };
-    if ret == 0 { false } else { true }
-}
-
-///
-/// rsgx_data_is_within_enclave checks whether a given address is within enclave memory. 
-///
-#[inline]
-pub fn rsgx_data_is_within_enclave<T: Copy>(data: &T) -> bool {
-
-    rsgx_raw_is_within_enclave(data as * const _ as * const u8, mem::size_of::<T>())
-}
-
-///
-/// rsgx_slice_is_within_enclave checks whether a given address is within enclave memory. 
-///
-#[inline]
-pub fn rsgx_slice_is_within_enclave<T: Copy>(data: &[T]) -> bool {
-
-    rsgx_raw_is_within_enclave(data.as_ptr() as * const u8, mem::size_of::<T>() * data.len())
-}
-
-///
-/// rsgx_raw_is_within_enclave checks whether a given address is within enclave memory. 
-///
-/// The rsgx_raw_is_within_enclave function checks that the buffer located at the pointer addr with its 
-/// length of size is an address that is strictly within the calling enclave address space.
-///
-/// # Description
-/// 
-/// rsgx_raw_is_within_enclave simply compares the start and end address of the buffer with the calling 
-/// enclave address space. It does not check the property of the address. Given a function pointer, you 
-/// sometimes need to confirm whether such a function is within the enclave. In this case, it is recommended
-/// to use rsgx_raw_is_within_enclave with a size of 1.
-/// 
-/// # Parameters
-///
-/// **addr**
-///
-/// The start address of the buffer.
-///
-/// **size**
-///
-/// The size of the buffer.
-///
-/// # Requirements
-///
-/// Library: libsgx_trts.a
-///
-/// # Return value
-///
-/// **true**
-///
-/// The buffer is strictly within the enclave address space.
-///
-/// **false**
-///
-/// The whole buffer or part of the buffer is not within the enclave, or the buffer is wrapped around.
-///
-pub fn rsgx_raw_is_within_enclave(addr: * const u8, size: usize) -> bool {
-
-    let ret = unsafe { sgx_is_within_enclave(addr as * const c_void, size) };
-    if ret == 0 { false } else { true }
-}
-
-///
-/// rsgx_data_is_outside_enclave checks whether a given address is outside enclave memory. 
-///
-#[inline]
-pub fn rsgx_data_is_outside_enclave<T: Copy>(data: &T) -> bool {
-
-    rsgx_raw_is_outside_enclave(data as * const _ as * const u8,  mem::size_of::<T>())
-}
-
-///
-/// rsgx_slice_is_outside_enclave checks whether a given address is outside enclave memory. 
-///
-#[inline]
-pub fn rsgx_slice_is_outside_enclave<T: Copy>(data: &[T]) -> bool {
-
-    rsgx_raw_is_outside_enclave(data.as_ptr() as * const u8, mem::size_of::<T>() * data.len())
-}
-
-///
-/// rsgx_raw_is_outside_enclave checks whether a given address is outside enclave memory. 
-///
-/// The rsgx_raw_is_outside_enclave function checks that the buffer located at the pointer addr with its 
-/// length of size is an address that is strictly outside the calling enclave address space.
-///
-/// # Description
-/// 
-/// rsgx_raw_is_outside_enclave simply compares the start and end address of the buffer with the calling 
-/// enclave address space. It does not check the property of the address.
-/// 
-/// # Parameters
-///
-/// **addr**
-///
-/// The start address of the buffer.
-///
-/// **size**
-///
-/// The size of the buffer.
-///
-/// # Requirements
-///
-/// Library: libsgx_trts.a
-///
-/// # Return value
-///
-/// **true**
-///
-/// The buffer is strictly outside the enclave address space.
-///
-/// **false**
-///
-/// The whole buffer or part of the buffer is not outside the enclave, or the buffer is wrapped around.
-///
-pub fn rsgx_raw_is_outside_enclave(addr: * const u8, size: usize) -> bool {
-
-    let ret = unsafe { sgx_is_outside_enclave(addr as * const c_void, size) };
-    if ret == 0 { false } else { true }
-}
-
-///
-/// rsgx_get_thread_data is to get TD base address per thread.
-/// 
-/// **Note**
-///
-/// This API is only an experimental funtion.
-///
-#[inline]
-pub fn rsgx_get_thread_data() -> * const u8 {
-
-    unsafe { get_thread_data() as * const u8 }
-}
-
-///
-/// rsgx_get_enclave_base is to get enclave image base address.
-/// 
-/// **Note**
-///
-/// This API is only an experimental funtion.
-///
-#[inline]
-pub fn rsgx_get_enclave_base() -> * const u8 {
-
-    unsafe { get_enclave_base() as * const u8 }
-}
-
-///
-/// rsgx_get_heap_base is to get enclave heap base address.
-/// 
-/// **Note**
-///
-/// This API is only an experimental funtion.
-///
-#[inline]
-pub fn rsgx_get_heap_base() -> * const u8 {
-
-    unsafe { get_heap_base() as * const u8 }
-}
-
-///
-/// rsgx_get_heap_size is to get enclave heap size.
-/// 
-/// **Note**
-///
-/// This API is only an experimental funtion.
-///
-#[inline]
-pub fn rsgx_get_heap_size() -> usize {
-
-    unsafe { get_heap_size() }
-}
\ No newline at end of file
diff --git a/sgx_trts/src/local.rs b/sgx_trts/src/local.rs
new file mode 100644
index 0000000..93dbc05
--- /dev/null
+++ b/sgx_trts/src/local.rs
@@ -0,0 +1,223 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//! Thread local storage
+
+use super::enclave::{SgxGlobalData, SgxThreadPolicy};
+use core::cell::UnsafeCell;
+use core::mem;
+use core::intrinsics;
+
+pub struct LocalKey<T: 'static> {
+    inner: fn() -> Option<&'static UnsafeCell<Option<T>>>,
+    init: fn() -> T,
+}
+
+/// Declare a new thread local storage key of type [`sgx_trts::LocalKey`].
+///
+/// # Syntax
+///
+/// The macro wraps any number of static declarations and makes them thread local.
+/// Each static may be public or private, and attributes are allowed. Example:
+///
+/// ```
+/// use core::cell::RefCell;
+/// thread_local! {
+///     pub static FOO: RefCell<u32> = RefCell::new(1);
+///
+///     #[allow(unused)]
+///     static BAR: RefCell<f32> = RefCell::new(1.0);
+/// }
+/// # fn main() {}
+/// ```
+///
+#[macro_export]
+#[allow_internal_unstable]
+macro_rules! thread_local {
+    // rule 0: empty (base case for the recursion)
+    () => {};
+
+    // rule 1: process multiple declarations where the first one is private
+    ($(#[$attr:meta])* static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => (
+        thread_local!($(#[$attr])* static $name: $t = $init); // go to rule 2
+        thread_local!($($rest)*);
+    );
+
+    // rule 2: handle a single private declaration
+    ($(#[$attr:meta])* static $name:ident: $t:ty = $init:expr) => (
+        $(#[$attr])* static $name: $crate::LocalKey<$t> =
+            __thread_local_inner!($t, $init);
+    );
+
+    // rule 3: handle multiple declarations where the first one is public
+    ($(#[$attr:meta])* pub static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => (
+        thread_local!($(#[$attr])* pub static $name: $t = $init); // go to rule 4
+        thread_local!($($rest)*);
+    );
+
+    // rule 4: handle a single public declaration
+    ($(#[$attr:meta])* pub static $name:ident: $t:ty = $init:expr) => (
+        $(#[$attr])* pub static $name: $crate::LocalKey<$t> =
+            __thread_local_inner!($t, $init);
+    );
+}
+
+#[macro_export]
+#[allow_internal_unstable]
+macro_rules! __thread_local_inner {
+    ($t:ty, $init:expr) => {{
+
+        use core::cell::UnsafeCell;
+
+        fn __init() -> $t { $init }
+
+        fn __getit() -> Option<&'static UnsafeCell<Option<$t>>>
+        {
+            #[thread_local]
+            static __KEY: $crate::local::LocalKeyInner<$t> =
+                $crate::local::LocalKeyInner::new();
+
+            __KEY.get()
+        }
+
+        $crate::LocalKey::new(__getit, __init)
+    }}
+}
+
+/// Indicator of the state of a thread local storage key.
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
+pub enum LocalKeyState {
+    /// All keys are in this state whenever a thread starts. Keys will
+    /// transition to the `Valid` state once the first call to [`with`] happens
+    /// and the initialization expression succeeds.
+    ///
+    /// Keys in the `Uninitialized` state will yield a reference to the closure
+    /// passed to [`with`] so long as the initialization routine does not panic.
+    ///
+    Uninitialized,
+    /// Once a key has been accessed successfully, it will enter the `Valid`
+    /// state. Keys in the `Valid` state will remain so until the thread exits,
+    /// at which point the destructor will be run and the key will enter the
+    /// `Destroyed` state.
+    ///
+    /// Keys in the `Valid` state will be guaranteed to yield a reference to the
+    /// closure passed to [`with`].
+    ///
+    Valid,
+    /// if TLS data needs to be destructed, TCS policy must be Bound, The key will
+    /// enter the 'Error' state.
+    ///
+    Error,
+}
+
+impl<T: 'static> LocalKey<T> {
+
+    pub const fn new(inner: fn() -> Option<&'static UnsafeCell<Option<T>>>,
+                     init: fn() -> T) -> LocalKey<T> {
+        LocalKey {
+            inner: inner,
+            init: init,
+        }
+    }
+
+    /// Acquires a reference to the value in this TLS key.
+    ///
+    /// This will lazily initialize the value if this thread has not referenced
+    /// this key yet.
+    ///
+    /// # Panics
+    ///
+    /// This function will `panic!()` if TLS data needs to be destructed,
+    /// TCS policy must be Bound.
+    pub fn with<F, R>(&'static self, f: F) -> R where F: FnOnce(&T) -> R {
+
+        unsafe {
+            let slot = (self.inner)();
+            let slot = slot.expect("if TLS data needs to be destructed, TCS policy must be Bound.");
+            f(match *slot.get() {
+                Some(ref inner) => inner,
+                None => self.init(slot),
+            })
+        }
+    }
+
+    unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T {
+
+        let value = (self.init)();
+        let ptr = slot.get();
+
+        mem::replace(&mut *ptr, Some(value));
+
+        (*ptr).as_ref().unwrap()
+    }
+
+    /// Query the current state of this key.
+    ///
+    pub fn state(&'static self) -> LocalKeyState {
+        unsafe {
+            match (self.inner)() {
+                Some(cell) => {
+                    match *cell.get() {
+                        Some(..) => LocalKeyState::Valid,
+                        None => LocalKeyState::Uninitialized,
+                    }
+                }
+                None => LocalKeyState::Error,
+            }
+        }
+    }
+}
+
+pub struct LocalKeyInner<T> {
+    inner: UnsafeCell<Option<T>>,
+}
+
+unsafe impl<T> Sync for LocalKeyInner<T> { }
+
+impl<T> LocalKeyInner<T> {
+
+    pub const fn new() -> LocalKeyInner<T> {
+        LocalKeyInner {
+            inner: UnsafeCell::new(None),
+        }
+    }
+
+    pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
+        unsafe {
+            if intrinsics::needs_drop::<T>() {
+                match SgxGlobalData::new().thread_policy() {
+                    SgxThreadPolicy::Unbound => {
+                        return None;
+                    },
+                    SgxThreadPolicy::Bound => (),
+                }
+            }
+        }
+        Some(&self.inner)
+    }
+}
diff --git a/sgx_trts/src/macros.rs b/sgx_trts/src/macros.rs
new file mode 100644
index 0000000..c6d66d5
--- /dev/null
+++ b/sgx_trts/src/macros.rs
@@ -0,0 +1,54 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//! Global constructor support
+#[macro_export]
+macro_rules! init_global_object {
+    ($var_name:ident, $func_name:ident = $func:block) => {
+
+        cfg_if! {
+            if #[cfg(target_os = "linux")] {
+                #[link_section = ".init_array"]
+                #[no_mangle]
+                pub static $var_name: fn() = $func_name;
+            } else if #[cfg(target_os = "windows")]  {
+                #[no_mangle]
+                pub static $var_name: fn() = $func_name;
+            } else if #[cfg(target_os = "macos")]  {
+                #[no_mangle]
+                pub static $var_name: fn() = $func_name;
+            } else {
+
+            }
+        }
+        #[no_mangle]
+        pub fn $func_name() {
+            {$func};
+        }
+    }
+}
diff --git a/sgx_trts/src/memeq.rs b/sgx_trts/src/memeq.rs
new file mode 100644
index 0000000..9e80c98
--- /dev/null
+++ b/sgx_trts/src/memeq.rs
@@ -0,0 +1,95 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//! consttime memcmp
+
+use sgx_types::marker::{BytewiseEquality};
+use core::mem;
+use core::slice;
+
+pub trait ConsttimeMemEq<T: BytewiseEquality + ?Sized = Self> {
+    fn consttime_memeq(&self, other: &T) -> bool;
+
+    fn consttime_memne(&self, other: &T) -> bool { !self.consttime_memeq(other) }
+}
+
+impl<T> ConsttimeMemEq<[T]> for [T]
+    where T: Eq + BytewiseEquality
+{
+    fn consttime_memeq(&self, other: &[T]) -> bool {
+
+        if self.len() != other.len() {
+            return false;
+        }
+        if self.as_ptr() == other.as_ptr() {
+            return true;
+        }
+        let size = mem::size_of_val(self);
+        consttime_memequal(self.as_ptr() as * const u8,
+                           other.as_ptr() as * const u8,
+                           size) != 0
+    }
+}
+
+impl<T> ConsttimeMemEq<T> for T
+    where T: Eq + BytewiseEquality
+{
+    fn consttime_memeq(&self, other: &T) -> bool {
+
+        let size = mem::size_of_val(self);
+        if size == 0 {
+            return true;
+        }
+        consttime_memequal(self as * const T as * const u8,
+                           other as * const T as * const u8,
+                           size) != 0
+    }
+}
+
+fn consttime_memequal(b1: * const u8, b2: * const u8, l: usize) -> i32
+{
+    let mut res: i32 = 0;
+    let mut len = l;
+    let p1 = unsafe { slice::from_raw_parts(b1, l) };
+    let p2 = unsafe { slice::from_raw_parts(b2, l) };
+
+    while len > 0 {
+        len -= 1;
+        res |= (p1[len] ^ p2[len]) as i32;
+    }
+    /*
+     * Map 0 to 1 and [1, 256) to 0 using only constant-time
+     * arithmetic.
+     *
+     * This is not simply `!res' because although many CPUs support
+     * branchless conditional moves and many compilers will take
+     * advantage of them, certain compilers generate branches on
+     * certain CPUs for `!res'.
+     */
+    (1 & ((res - 1) >> 8))
+}
diff --git a/sgx_types/src/oom.rs b/sgx_trts/src/oom.rs
similarity index 60%
rename from sgx_types/src/oom.rs
rename to sgx_trts/src/oom.rs
index 70e7b4c..c77e7a6 100644
--- a/sgx_types/src/oom.rs
+++ b/sgx_trts/src/oom.rs
@@ -26,47 +26,29 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#[cfg(not(feature = "use_std"))]
 use core::sync::atomic::{AtomicPtr, Ordering};
-#[cfg(not(feature = "use_std"))]
-use core::{mem, fmt};
-use super::function;
+use core::mem;
 
-#[cfg(not(feature = "use_std"))]
-static PANIC_HANDLER: AtomicPtr<()> = AtomicPtr::new(default_panic_handler as * mut ());
+static SGX_OOM_HANDLER: AtomicPtr<()> = AtomicPtr::new(default_oom_handler as * mut ());
 
-#[cfg(not(feature = "use_std"))]
-fn default_panic_handler(msg: fmt::Arguments) {
+#[allow(unused_variables)]
+fn default_oom_handler() -> ! {
 
+    panic!("enclave allocate memory failed.");
 }
 
-#[cfg(not(feature = "use_std"))]
-pub fn set_panic_handler(handler: fn(fmt::Arguments)) {
-    PANIC_HANDLER.store(handler as * mut (), Ordering::SeqCst);
+pub fn rsgx_oom() -> ! {
+
+    let value = SGX_OOM_HANDLER.load(Ordering::SeqCst);
+    let handler: fn() -> ! = unsafe { mem::transmute(value) };
+    handler();
 }
 
-pub fn rsgx_abort() -> ! {
-    unsafe { function::abort() }
+/// Set a custom handler for out-of-memory conditions
+///
+/// To avoid recursive OOM failures, it is critical that the OOM handler does
+/// not allocate any memory itself.
+pub fn set_panic_handler(handler: fn() -> !) {
+
+    SGX_OOM_HANDLER.store(handler as * mut (), Ordering::SeqCst);
 }
-
-#[cfg(not(feature = "use_std"))]
-#[lang = "panic_fmt"] 
-#[no_mangle]
-pub extern fn rust_begin_panic(msg: fmt::Arguments, file: &'static str, line: u32) -> ! { 
-
-    let value = PANIC_HANDLER.load(Ordering::SeqCst);
-    let handler: fn(fmt::Arguments) = unsafe { mem::transmute(value) };
-    handler(msg);
-
-    rsgx_abort()
-}
-
-#[cfg(not(feature = "use_std"))]
-#[lang = "eh_personality"]
-#[no_mangle]
-pub extern fn rust_eh_personality() {}
-
-#[cfg(not(feature = "use_std"))]
-#[lang = "eh_unwind_resume"]
-#[no_mangle]
-pub extern fn rust_eh_unwind_resume() {}
\ No newline at end of file
diff --git a/sgx_trts/src/panic.rs b/sgx_trts/src/panic.rs
new file mode 100644
index 0000000..555919f
--- /dev/null
+++ b/sgx_trts/src/panic.rs
@@ -0,0 +1,283 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//! Panic support in the standard library
+
+use super::panicking;
+use core::any::Any;
+use alloc::boxed::Box;
+use core::cell::UnsafeCell;
+use core::fmt;
+use core::ops::{Deref, DerefMut};
+use core::ptr::{Unique, Shared};
+use core::sync::atomic;
+use alloc::rc::Rc;
+use alloc::arc::Arc;
+
+/// A marker trait which represents "panic safe" types in Rust.
+///
+/// This trait is implemented by default for many types and behaves similarly in
+/// terms of inference of implementation to the `Send` and `Sync` traits. The
+/// purpose of this trait is to encode what types are safe to cross a `catch_unwind`
+/// boundary with no fear of unwind safety.
+///
+/// ## What is unwind safety?
+///
+/// In Rust a function can "return" early if it either panics or calls a
+/// function which transitively panics. This sort of control flow is not always
+/// anticipated, and has the possibility of causing subtle bugs through a
+/// combination of two cricial components:
+///
+/// 1. A data structure is in a temporarily invalid state when the thread
+///    panics.
+/// 2. This broken invariant is then later observed.
+///
+/// Typically in Rust, it is difficult to perform step (2) because catching a
+/// panic involves either spawning a thread (which in turns makes it difficult
+/// to later witness broken invariants) or using the `catch_unwind` function in this
+/// module. Additionally, even if an invariant is witnessed, it typically isn't a
+/// problem in Rust because there are no uninitialized values (like in C or C++).
+///
+/// It is possible, however, for **logical** invariants to be broken in Rust,
+/// which can end up causing behavioral bugs. Another key aspect of unwind safety
+/// in Rust is that, in the absence of `unsafe` code, a panic cannot lead to
+/// memory unsafety.
+///
+/// That was a bit of a whirlwind tour of unwind safety, but for more information
+/// about unwind safety and how it applies to Rust, see an [associated RFC][rfc].
+///
+/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
+///
+/// ## What is `UnwindSafe`?
+///
+/// Now that we've got an idea of what unwind safety is in Rust, it's also
+/// important to understand what this trait represents. As mentioned above, one
+/// way to witness broken invariants is through the `catch_unwind` function in this
+/// module as it allows catching a panic and then re-using the environment of
+/// the closure.
+///
+/// Simply put, a type `T` implements `UnwindSafe` if it cannot easily allow
+/// witnessing a broken invariant through the use of `catch_unwind` (catching a
+/// panic). This trait is a marker trait, so it is automatically implemented for
+/// many types, and it is also structurally composed (e.g. a struct is unwind
+/// safe if all of its components are unwind safe).
+///
+/// Note, however, that this is not an unsafe trait, so there is not a succinct
+/// contract that this trait is providing. Instead it is intended as more of a
+/// "speed bump" to alert users of `catch_unwind` that broken invariants may be
+/// witnessed and may need to be accounted for.
+///
+/// ## Who implements `UnwindSafe`?
+///
+/// Types such as `&mut T` and `&RefCell<T>` are examples which are **not**
+/// unwind safe. The general idea is that any mutable state which can be shared
+/// across `catch_unwind` is not unwind safe by default. This is because it is very
+/// easy to witness a broken invariant outside of `catch_unwind` as the data is
+/// simply accessed as usual.
+///
+/// Types like `&SgxMutex<T>`, however, are unwind safe because they implement
+/// poisoning by default. They still allow witnessing a broken invariant, but
+/// they already provide their own "speed bumps" to do so.
+///
+/// ## When should `UnwindSafe` be used?
+///
+/// Is not intended that most types or functions need to worry about this trait.
+/// It is only used as a bound on the `catch_unwind` function and as mentioned above,
+/// the lack of `unsafe` means it is mostly an advisory. The `AssertUnwindSafe`
+/// wrapper struct in this module can be used to force this trait to be
+/// implemented for any closed over variables passed to the `catch_unwind` function
+/// (more on this below).
+pub trait UnwindSafe {}
+
+/// A marker trait representing types where a shared reference is considered
+/// unwind safe.
+///
+/// This trait is namely not implemented by `UnsafeCell`, the root of all
+/// interior mutability.
+///
+/// This is a "helper marker trait" used to provide impl blocks for the
+/// `UnwindSafe` trait, for more information see that documentation.
+pub trait RefUnwindSafe {}
+
+/// A simple wrapper around a type to assert that it is unwind safe.
+///
+/// When using `catch_unwind` it may be the case that some of the closed over
+/// variables are not unwind safe. For example if `&mut T` is captured the
+/// compiler will generate a warning indicating that it is not unwind safe. It
+/// may not be the case, however, that this is actually a problem due to the
+/// specific usage of `catch_unwind` if unwind safety is specifically taken into
+/// account. This wrapper struct is useful for a quick and lightweight
+/// annotation that a variable is indeed unwind safe.
+///
+pub struct AssertUnwindSafe<T>(
+    pub T
+);
+
+// Implementations of the `UnwindSafe` trait:
+//
+// * By default everything is unwind safe
+// * pointers T contains mutability of some form are not unwind safe
+// * Unique, an owning pointer, lifts an implementation
+// * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
+// * Our custom AssertUnwindSafe wrapper is indeed unwind safe
+impl UnwindSafe for .. {}
+impl<'a, T: ?Sized> !UnwindSafe for &'a mut T {}
+impl<'a, T: RefUnwindSafe + ?Sized> UnwindSafe for &'a T {}
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
+impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Shared<T> {}
+impl<T> UnwindSafe for AssertUnwindSafe<T> {}
+
+// not covered via the Shared impl above b/c the inner contents use
+// Cell/AtomicUsize, but the usage here is unwind safe so we can lift the
+// impl up one level to Arc/Rc itself
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Rc<T> {}
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<T> {}
+
+// Pretty simple implementations for the `RefUnwindSafe` marker trait,
+// basically just saying that this is a marker trait and `UnsafeCell` is the
+// only thing which doesn't implement it (which then transitively applies to
+// everything else).
+impl RefUnwindSafe for .. {}
+impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {}
+impl<T> RefUnwindSafe for AssertUnwindSafe<T> {}
+
+#[cfg(target_has_atomic = "ptr")]
+impl RefUnwindSafe for atomic::AtomicIsize {}
+#[cfg(target_has_atomic = "8")]
+impl RefUnwindSafe for atomic::AtomicI8 {}
+#[cfg(target_has_atomic = "16")]
+impl RefUnwindSafe for atomic::AtomicI16 {}
+#[cfg(target_has_atomic = "32")]
+impl RefUnwindSafe for atomic::AtomicI32 {}
+#[cfg(target_has_atomic = "64")]
+impl RefUnwindSafe for atomic::AtomicI64 {}
+
+#[cfg(target_has_atomic = "ptr")]
+impl RefUnwindSafe for atomic::AtomicUsize {}
+#[cfg(target_has_atomic = "8")]
+impl RefUnwindSafe for atomic::AtomicU8 {}
+#[cfg(target_has_atomic = "16")]
+impl RefUnwindSafe for atomic::AtomicU16 {}
+#[cfg(target_has_atomic = "32")]
+impl RefUnwindSafe for atomic::AtomicU32 {}
+#[cfg(target_has_atomic = "64")]
+impl RefUnwindSafe for atomic::AtomicU64 {}
+
+#[cfg(target_has_atomic = "8")]
+impl RefUnwindSafe for atomic::AtomicBool {}
+
+#[cfg(target_has_atomic = "ptr")]
+impl<T> RefUnwindSafe for atomic::AtomicPtr<T> {}
+
+impl<T> Deref for AssertUnwindSafe<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T> DerefMut for AssertUnwindSafe<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        &mut self.0
+    }
+}
+
+impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> {
+    type Output = R;
+
+    extern "rust-call" fn call_once(self, _args: ()) -> R {
+        (self.0)()
+    }
+}
+
+impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("AssertUnwindSafe")
+            .field(&self.0)
+            .finish()
+    }
+}
+
+/// Invokes a closure, capturing the cause of an unwinding panic if one occurs.
+///
+/// This function will return `Ok` with the closure's result if the closure
+/// does not panic, and will return `Err(cause)` if the closure panics. The
+/// `cause` returned is the object with which panic was originally invoked.
+///
+/// It is currently undefined behavior to unwind from Rust code into foreign
+/// code, so this function is particularly useful when Rust is called from
+/// another language (normally C). This can run arbitrary Rust code, capturing a
+/// panic and allowing a graceful handling of the error.
+///
+/// It is **not** recommended to use this function for a general try/catch
+/// mechanism. The `Result` type is more appropriate to use for functions that
+/// can fail on a regular basis. Additionally, this function is not guaranteed
+/// to catch all panics, see the "Notes" section below.
+///
+/// The closure provided is required to adhere to the `UnwindSafe` trait to ensure
+/// that all captured variables are safe to cross this boundary. The purpose of
+/// this bound is to encode the concept of [exception safety][rfc] in the type
+/// system. Most usage of this function should not need to worry about this
+/// bound as programs are naturally unwind safe without `unsafe` code. If it
+/// becomes a problem the associated `AssertUnwindSafe` wrapper type in this
+/// module can be used to quickly assert that the usage here is indeed unwind
+/// safe.
+///
+/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
+///
+/// # Notes
+///
+/// Note that this function **may not catch all panics** in Rust. A panic in
+/// Rust is not always implemented via unwinding, but can be implemented by
+/// aborting the process as well. This function *only* catches unwinding panics,
+/// not those that abort the process.
+///
+pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R, Box<Any + Send  + 'static>> {
+    unsafe {
+        panicking::try(f)
+    }
+}
+
+/// Triggers a panic without invoking the panic hook.
+///
+/// This is designed to be used in conjunction with `catch_unwind` to, for
+/// example, carry a panic across a layer of C code.
+///
+/// # Notes
+///
+/// Note that panics in Rust are not always implemented via unwinding, but they
+/// may be implemented by aborting the process. If this function is called when
+/// panics are implemented this way then this function will abort the process,
+/// not trigger an unwind.
+///
+pub fn resume_unwind(payload: Box<Any + Send>) -> ! {
+    panicking::update_count_then_panic(payload)
+}
diff --git a/sgx_trts/src/panicking.rs b/sgx_trts/src/panicking.rs
new file mode 100644
index 0000000..d6006ca
--- /dev/null
+++ b/sgx_trts/src/panicking.rs
@@ -0,0 +1,332 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//! Implementation of various bits and pieces of the `panic!` macro and
+//! associated runtime pieces.
+
+use core::mem;
+use core::fmt;
+use core::any::Any;
+use core::ptr;
+use core::raw;
+use core::sync::atomic::{AtomicPtr, Ordering};
+use alloc::boxed::Box;
+use collections::string::String;
+use super::*;
+
+static PANIC_HANDLER: AtomicPtr<()> = AtomicPtr::new(default_panic_handler as * mut ());
+
+#[allow(unused_variables)]
+fn default_panic_handler(msg: &str, file: &str, line: u32) {
+
+}
+
+/// Registers a custom panic handler, replacing any that was previously registered.
+pub fn set_panic_handler(handler: fn(&str, &str, u32)) {
+    PANIC_HANDLER.store(handler as * mut (), Ordering::SeqCst);
+}
+
+fn panic_handler<'a>(info: &'a PanicInfo) {
+
+    let msg: &str = match info.payload.downcast_ref::<&'static str>() {
+        Some(s) => *s,
+        None => match info.payload.downcast_ref::<String>() {
+            Some(s) => &s[..],
+            None => "Box<Any>",
+        }
+    };
+
+    let file = info.location.file;
+    let line = info.location.line;
+
+    let value = PANIC_HANDLER.load(Ordering::SeqCst);
+    let handler: fn(&str, &str, u32) = unsafe{ mem::transmute(value) };
+    handler(msg, file, line);
+}
+
+
+#[allow(improper_ctypes)]
+extern {
+    fn __rust_maybe_catch_panic(f: fn(*mut u8),
+                                data: *mut u8,
+                                data_ptr: *mut usize,
+                                vtable_ptr: *mut usize) -> u32;
+    #[unwind]
+    fn __rust_start_panic(data: usize, vtable: usize) -> u32;
+}
+
+/// A struct providing information about a panic.
+///
+#[derive(Debug)]
+pub struct PanicInfo<'a> {
+    payload: &'a (Any + Send),
+    location: Location<'a>,
+}
+
+impl<'a> PanicInfo<'a> {
+
+    /// Returns the payload associated with the panic.
+    ///
+    /// This will commonly, but not always, be a `&'static str` or [`String`].
+    ///
+    pub fn payload(&self) -> &(Any + Send) {
+        self.payload
+    }
+
+    /// Returns information about the location from which the panic originated,
+    /// if available.
+    ///
+    /// This method will currently always return [`Some`], but this may change
+    /// in future versions.
+    ///
+    pub fn location(&self) -> Option<&Location> {
+        Some(&self.location)
+    }
+}
+
+/// A struct containing information about the location of a panic.
+///
+/// This structure is created by the [`location`] method of [`PanicInfo`].
+///
+#[derive(Debug)]
+pub struct Location<'a> {
+    file: &'a str,
+    line: u32,
+}
+
+impl<'a> Location<'a> {
+
+    /// Returns the name of the source file from which the panic originated.
+    ///
+    pub fn file(&self) -> &str {
+        self.file
+    }
+    /// Returns the line number from which the panic originated.
+    ///
+    pub fn line(&self) -> u32 {
+        self.line
+    }
+}
+
+pub fn update_panic_count(amt: isize) -> usize {
+
+    use core::cell::Cell;
+    thread_local! { static PANIC_COUNT: Cell<usize> = Cell::new(0) }
+
+    PANIC_COUNT.with(|c| {
+        let next = (c.get() as isize + amt) as usize;
+        c.set(next);
+        return next
+    })
+}
+
+/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
+pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
+    #[allow(unions_with_drop_fields)]
+    union Data<F, R> {
+        f: F,
+        r: R,
+    }
+
+    // We do some sketchy operations with ownership here for the sake of
+    // performance. We can only  pass pointers down to
+    // `__rust_maybe_catch_panic` (can't pass objects by value), so we do all
+    // the ownership tracking here manually using a union.
+    //
+    // We go through a transition where:
+    //
+    // * First, we set the data to be the closure that we're going to call.
+    // * When we make the function call, the `do_call` function below, we take
+    //   ownership of the function pointer. At this point the `Data` union is
+    //   entirely uninitialized.
+    // * If the closure successfully returns, we write the return value into the
+    //   data's return slot. Note that `ptr::write` is used as it's overwriting
+    //   uninitialized data.
+    // * Finally, when we come back out of the `__rust_maybe_catch_panic` we're
+    //   in one of two states:
+    //
+    //      1. The closure didn't panic, in which case the return value was
+    //         filled in. We move it out of `data` and return it.
+    //      2. The closure panicked, in which case the return value wasn't
+    //         filled in. In this case the entire `data` union is invalid, so
+    //         there is no need to drop anything.
+    //
+    // Once we stack all that together we should have the "most efficient'
+    // method of calling a catch panic whilst juggling ownership.
+    let mut any_data = 0_usize;
+    let mut any_vtable = 0_usize;
+    let mut data = Data {
+        f: f,
+    };
+
+    let r = __rust_maybe_catch_panic(do_call::<F, R>,
+                                     &mut data as *mut _ as *mut u8,
+                                     &mut any_data,
+                                     &mut any_vtable);
+
+    return if r == 0 {
+        debug_assert!(update_panic_count(0) == 0);
+        Ok(data.r)
+    } else {
+        update_panic_count(-1);
+        debug_assert!(update_panic_count(0) == 0);
+        Err(mem::transmute(raw::TraitObject {
+            data: any_data as *mut _,
+            vtable: any_vtable as *mut _,
+        }))
+    };
+
+    fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
+        unsafe {
+            let data = data as *mut Data<F, R>;
+            let f = ptr::read(&mut (*data).f);
+            ptr::write(&mut (*data).r, f());
+        }
+    }
+}
+
+/// Determines whether the current thread is unwinding because of panic.
+pub fn panicking() -> bool {
+    update_panic_count(0) != 0
+}
+
+/// Entry point of panic from the libcore crate.
+#[lang = "panic_fmt"]
+#[unwind]
+pub extern fn rust_begin_panic(msg: fmt::Arguments,
+                               file: &'static str,
+                               line: u32) -> ! {
+    begin_panic_fmt(&msg, &(file, line))
+}
+
+/// The entry point for panicking with a formatted message.
+///
+/// This is designed to reduce the amount of code required at the call
+/// site as much as possible (so that `panic!()` has as low an impact
+/// on (e.g.) the inlining of other functions as possible), by moving
+/// the actual formatting into this shared place.
+#[inline(never)] #[cold]
+pub fn begin_panic_fmt(msg: &fmt::Arguments,
+                       file_line: &(&'static str, u32)) -> ! {
+
+    use core::fmt::Write;
+    use collections::string::String;
+
+    // We do two allocations here, unfortunately. But (a) they're
+    // required with the current scheme, and (b) we don't handle
+    // panic + OOM properly anyway (see comment in begin_panic
+    // below).
+
+    let mut s = String::new();
+    let _ = s.write_fmt(*msg);
+    begin_panic(s, file_line)
+}
+
+/// This is the entry point of panicking for panic!() and assert!().
+#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
+pub fn begin_panic<M: Any + Send>(msg: M, file_line: &(&'static str, u32)) -> ! {
+    // Note that this should be the only allocation performed in this code path.
+    // Currently this means that panic!() on OOM will invoke this code path,
+    // but then again we're not really ready for panic on OOM anyway. If
+    // we do start doing this, then we should propagate this allocation to
+    // be performed in the parent of this thread instead of the thread that's
+    // panicking.
+
+    rust_panic_with_hook(Box::new(msg), file_line)
+}
+
+/// Executes the primary logic for a panic, including checking for recursive
+/// panics and panic hooks.
+///
+/// This is the entry point or panics from libcore, formatted panics, and
+/// `Box<Any>` panics. Here we'll verify that we're not panicking recursively,
+/// run panic hooks, and then delegate to the actual implementation of panics.
+#[inline(never)]
+#[cold]
+fn rust_panic_with_hook(msg: Box<Any + Send>,
+                        file_line: &(&'static str, u32)) -> ! {
+    let (file, line) = *file_line;
+
+    let panics = update_panic_count(1);
+
+    // If this is the third nested call (e.g. panics == 2, this is 0-indexed),
+    // the panic hook probably triggered the last panic, otherwise the
+    // double-panic check would have aborted the process. In this case abort the
+    // process real quickly as we don't want to try calling it again as it'll
+    // probably just panic again.
+    if panics > 2 {
+        //util::dumb_print(format_args!("thread panicked while processing \
+        //                               panic. aborting.\n"));
+
+        rsgx_abort()
+    }
+
+    {
+        let info = PanicInfo {
+            payload: &*msg,
+            location: Location {
+                file: file,
+                line: line,
+            },
+        };
+
+        panic_handler(&info);
+    }
+
+
+    if panics > 1 {
+        // If a thread panics while it's already unwinding then we
+        // have limited options. Currently our preference is to
+        // just abort. In the future we may consider resuming
+        // unwinding or otherwise exiting the thread cleanly.
+        //util::dumb_print(format_args!("thread panicked while panicking. \
+        //                               aborting.\n"));
+        rsgx_abort()
+    }
+
+    rust_panic(msg)
+}
+
+/// Shim around rust_panic. Called by resume_unwind.
+pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! {
+    update_panic_count(1);
+    rust_panic(msg)
+}
+
+/// A private no-mangle function on which to slap yer breakpoints.
+#[no_mangle]
+#[allow(unused_variables)]
+#[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints
+pub fn rust_panic(msg: Box<Any + Send>) -> ! {
+    let code = unsafe {
+        let obj = mem::transmute::<_, raw::TraitObject>(msg);
+        __rust_start_panic(obj.data as usize, obj.vtable as usize)
+    };
+    //rtabort!("failed to initiate panic, error {}", code)
+    rsgx_abort()
+}
diff --git a/sgx_trts/src/trts.rs b/sgx_trts/src/trts.rs
new file mode 100644
index 0000000..850d32a
--- /dev/null
+++ b/sgx_trts/src/trts.rs
@@ -0,0 +1,202 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use sgx_types::*;
+use sgx_types::marker::ContiguousMemory;
+use core::mem;
+
+///
+/// rsgx_read_rand function is used to generate a random number inside the enclave.
+///
+/// # Description
+///
+/// The rsgx_read_rand function is provided to replace the standard pseudo-random sequence generation functions
+/// inside the enclave, since these standard functions are not supported in the enclave, such as rand, srand, etc.
+/// For HW mode, the function generates a real-random sequence; while for simulation mode, the function generates
+/// a pseudo-random sequence.
+///
+/// # Parameters
+///
+/// **rand**
+///
+/// A pointer to the buffer that receives the random number. The rand buffer can be either within or outside the enclave,
+/// but it is not allowed to be across the enclave boundary or wrapped around.
+///
+/// # Requirements
+///
+/// Library: libsgx_trts.a
+///
+/// # Errors
+///
+/// **SGX_ERROR_INVALID_PARAMETER**
+///
+/// Invalid input parameters detected.
+///
+/// **SGX_ERROR_UNEXPECTED**
+///
+/// Indicates an unexpected error occurs during the valid random number generation process.
+///
+pub fn rsgx_read_rand(rand: &mut [u8]) -> SgxError {
+
+    let ret = unsafe { sgx_read_rand(rand.as_mut_ptr(), rand.len()) };
+    match ret {
+        sgx_status_t::SGX_SUCCESS => Ok(()),
+        _ => Err(ret),
+    }
+}
+
+///
+/// rsgx_data_is_within_enclave checks whether a given address is within enclave memory.
+///
+#[inline]
+pub fn rsgx_data_is_within_enclave<T: Copy + ContiguousMemory>(data: &T) -> bool {
+
+    rsgx_raw_is_within_enclave(data as * const _ as * const u8, mem::size_of::<T>())
+}
+
+///
+/// rsgx_slice_is_within_enclave checks whether a given address is within enclave memory.
+///
+#[inline]
+pub fn rsgx_slice_is_within_enclave<T: Copy + ContiguousMemory>(data: &[T]) -> bool {
+
+    rsgx_raw_is_within_enclave(data.as_ptr() as * const u8, mem::size_of_val(data))
+}
+
+///
+/// rsgx_raw_is_within_enclave checks whether a given address is within enclave memory.
+///
+/// The rsgx_raw_is_within_enclave function checks that the buffer located at the pointer addr with its
+/// length of size is an address that is strictly within the calling enclave address space.
+///
+/// # Description
+///
+/// rsgx_raw_is_within_enclave simply compares the start and end address of the buffer with the calling
+/// enclave address space. It does not check the property of the address. Given a function pointer, you
+/// sometimes need to confirm whether such a function is within the enclave. In this case, it is recommended
+/// to use rsgx_raw_is_within_enclave with a size of 1.
+///
+/// # Parameters
+///
+/// **addr**
+///
+/// The start address of the buffer.
+///
+/// **size**
+///
+/// The size of the buffer.
+///
+/// # Requirements
+///
+/// Library: libsgx_trts.a
+///
+/// # Return value
+///
+/// **true**
+///
+/// The buffer is strictly within the enclave address space.
+///
+/// **false**
+///
+/// The whole buffer or part of the buffer is not within the enclave, or the buffer is wrapped around.
+///
+pub fn rsgx_raw_is_within_enclave(addr: * const u8, size: usize) -> bool {
+
+    let ret = unsafe { sgx_is_within_enclave(addr as * const c_void, size) };
+    if ret == 0 { false } else { true }
+}
+
+///
+/// rsgx_data_is_outside_enclave checks whether a given address is outside enclave memory.
+///
+#[inline]
+pub fn rsgx_data_is_outside_enclave<T: Copy + ContiguousMemory>(data: &T) -> bool {
+
+    rsgx_raw_is_outside_enclave(data as * const _ as * const u8,  mem::size_of::<T>())
+}
+
+///
+/// rsgx_slice_is_outside_enclave checks whether a given address is outside enclave memory.
+///
+#[inline]
+pub fn rsgx_slice_is_outside_enclave<T: Copy + ContiguousMemory>(data: &[T]) -> bool {
+
+    rsgx_raw_is_outside_enclave(data.as_ptr() as * const u8, mem::size_of_val(data))
+}
+
+///
+/// rsgx_raw_is_outside_enclave checks whether a given address is outside enclave memory.
+///
+/// The rsgx_raw_is_outside_enclave function checks that the buffer located at the pointer addr with its
+/// length of size is an address that is strictly outside the calling enclave address space.
+///
+/// # Description
+///
+/// rsgx_raw_is_outside_enclave simply compares the start and end address of the buffer with the calling
+/// enclave address space. It does not check the property of the address.
+///
+/// # Parameters
+///
+/// **addr**
+///
+/// The start address of the buffer.
+///
+/// **size**
+///
+/// The size of the buffer.
+///
+/// # Requirements
+///
+/// Library: libsgx_trts.a
+///
+/// # Return value
+///
+/// **true**
+///
+/// The buffer is strictly outside the enclave address space.
+///
+/// **false**
+///
+/// The whole buffer or part of the buffer is not outside the enclave, or the buffer is wrapped around.
+///
+pub fn rsgx_raw_is_outside_enclave(addr: * const u8, size: usize) -> bool {
+
+    let ret = unsafe { sgx_is_outside_enclave(addr as * const c_void, size) };
+    if ret == 0 { false } else { true }
+}
+
+#[link(name = "sgx_trts")]
+extern {
+    //
+    // trts_pic.S
+    //
+    pub fn abort() -> !;
+}
+pub fn rsgx_abort() -> ! {
+    unsafe { abort() }
+}
diff --git a/sgx_trts/src/veh.rs b/sgx_trts/src/veh.rs
new file mode 100644
index 0000000..5266ede
--- /dev/null
+++ b/sgx_trts/src/veh.rs
@@ -0,0 +1,122 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use sgx_types::*;
+
+pub type exception_handle = * const c_void;
+
+///
+/// rsgx_register_exception_handler register an exception handler.
+///
+/// rsgx_register_exception_handler allows developers to register an exception handler, and specify whether to prepend
+/// (when is_first_handler is equal to 1) or append the handler to the handler chain.
+///
+/// # Description
+///
+/// The Intel(R) SGX SDK supports the registration of custom exception handler functions. You can write your own code to
+/// handle a limited set of hardware exceptions. For example, a CPUID instruction inside an enclave will effectively result
+/// in a #UD fault (Invalid Opcode Exception). ISV enclave code can have an exception handler to prevent the enclave from
+/// being trapped into an exception condition.
+///
+/// Calling rsgx_register_exception_handler allows you to register an exception handler, and specify whether to prepend
+/// (when is_first_handler is nonzero) or append the handler to the handler chain.
+///
+/// After calling rsgx_register_exception_handler to prepend an exception handler, a subsequent call to this function may
+/// add another exception handler at the beginning of the handler chain. Therefore the order in which exception handlers
+/// are called does not only depend on the value of the is_first_handler parameter, but more importantly depends on the order
+/// in which exception handlers are registered.
+///
+/// # Parameters
+///
+/// **is_first_handler**
+///
+/// Specify the order in which the handler should be called. If the parameter is nonzero, the handler is the first handler
+/// to be called. If the parameter is zero, the handler is the last handler to be called.
+///
+/// **exception_handler**
+///
+/// The exception handler to be called
+///
+/// # Requirements
+///
+/// Library: libsgx_trts.a
+///
+/// # Return value
+///
+/// **Some(exception_handle)**
+///
+/// Indicates the exception handler is registered successfully. The return value is an open handle to the custom exception handler.
+///
+/// **None**
+///
+/// The exception handler was not registered.
+///
+pub fn rsgx_register_exception_handler(is_first_handler: u32, exception_handler: sgx_exception_handler_t) -> Option<exception_handle> {
+
+    let handle = unsafe {
+        sgx_register_exception_handler(is_first_handler, exception_handler)
+    };
+
+    if handle.is_null() { None } else { Some(handle) }
+}
+
+///
+/// rsgx_unregister_exception_handler is used to unregister a custom exception handler.
+///
+/// # Description
+///
+/// The Intel(R) SGX SDK supports the registration of custom exception handler functions. An enclave developer
+/// can write their own code to handle a limited set of hardware exceptions.
+///
+/// Calling rsgx_unregister_exception_handler allows developers to unregister an exception handler that was registered earlier.
+///
+/// # Parameters
+///
+/// **handle**
+///
+/// A handle to the custom exception handler previously registered using the rsgx_register_exception_handler function.
+///
+/// # Requirements
+///
+/// Library: libsgx_trts.a
+///
+/// # Return value
+///
+/// **true**
+///
+/// The custom exception handler is unregistered successfully.
+///
+/// **false**
+///
+/// The exception handler was not unregistered (not a valid pointer, handler not found).
+///
+pub fn rsgx_unregister_exception_handler(handle: exception_handle) -> bool {
+
+    let ret = unsafe { sgx_unregister_exception_handler(handle) };
+    if ret == 0 { false } else { true }
+}
diff --git a/sgx_tse/Cargo.toml b/sgx_tse/Cargo.toml
index d83690d..2462cad 100644
--- a/sgx_tse/Cargo.toml
+++ b/sgx_tse/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tse"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Baidu"]
 
 [features]
diff --git a/sgx_tse/src/lib.rs b/sgx_tse/src/lib.rs
index 1511363..3725995 100644
--- a/sgx_tse/src/lib.rs
+++ b/sgx_tse/src/lib.rs
@@ -28,7 +28,7 @@
 
 //! # Trusted SE Library
 //!
-//! The library provides functions for getting specific keys and for creating and verifying an enclave report. 
+//! The library provides functions for getting specific keys and for creating and verifying an enclave report.
 //!
 #![crate_name = "sgx_tse"]
 #![crate_type = "rlib"]
@@ -39,32 +39,32 @@
 use sgx_types::*;
 
 ///
-/// The rsgx_create_report function tries to use the information of the target enclave and other information 
+/// The rsgx_create_report function tries to use the information of the target enclave and other information
 /// to create a cryptographic report of the enclave.
 ///
 /// This function is a wrapper for the SGX EREPORT instruction.
 ///
 /// # Description
-/// 
-/// Use the function rsgx_create_report to create a cryptographic report that describes the contents of the 
-/// calling enclave. The report can be used by other enclaves to verify that the enclave is running on the 
+///
+/// Use the function rsgx_create_report to create a cryptographic report that describes the contents of the
+/// calling enclave. The report can be used by other enclaves to verify that the enclave is running on the
 /// same platform. When an enclave calls rsgx_verify_report to verify a report, it will succeed only if
-/// the report was generated using the target_info for said enclave. This function is a wrapper for the SGX EREPORT 
+/// the report was generated using the target_info for said enclave. This function is a wrapper for the SGX EREPORT
 /// instruction.
 ///
-/// Before the source enclave calls rsgx_create_report to generate a report, it needs to populate target_info with 
-/// information about the target enclave that will verify the report. The target enclave may obtain this information 
-/// calling rsgx_create_report with a default value for target_info and pass it to the source enclave at the beginning 
+/// Before the source enclave calls rsgx_create_report to generate a report, it needs to populate target_info with
+/// information about the target enclave that will verify the report. The target enclave may obtain this information
+/// calling rsgx_create_report with a default value for target_info and pass it to the source enclave at the beginning
 /// of the inter-enclave attestation process.
 ///
 /// # Parameters
 ///
 /// **target_info**
 ///
-/// A pointer to the sgx_target_info_t object that contains the information of the target enclave, 
+/// A pointer to the sgx_target_info_t object that contains the information of the target enclave,
 /// which will be able to cryptographically verify the report calling rsgx_verify_report.efore calling this function.
 ///
-/// If value is default, sgx_create_report retrieves information about the calling enclave, 
+/// If value is default, sgx_create_report retrieves information about the calling enclave,
 /// but the generated report cannot be verified by any enclave.
 ///
 /// **report_data**
@@ -83,7 +83,7 @@
 ///
 /// **SGX_ERROR_INVALID_PARAMETER**
 ///
-/// An error is reported if any of the parameters memory is not within the enclave or the reserved fields 
+/// An error is reported if any of the parameters memory is not within the enclave or the reserved fields
 /// of the data structure are not set to zero.
 ///
 /// **SGX_ERROR_OUT_OF_MEMORY**
@@ -102,24 +102,24 @@
     match ret {
         sgx_status_t::SGX_SUCCESS => Ok(report),
         _ => Err(ret),
-    }  
+    }
 }
 
 ///
-/// The rsgx_verify_report function provides software verification for the report which is expected to be 
+/// The rsgx_verify_report function provides software verification for the report which is expected to be
 /// generated by the rsgx_create_report function.
 ///
 /// # Description
-/// 
-/// The rsgx_verify_report performs a cryptographic CMAC function of the input sgx_report_data_t object 
-/// in the report using the report key. Then the function compares the input report MAC value with the 
+///
+/// The rsgx_verify_report performs a cryptographic CMAC function of the input sgx_report_data_t object
+/// in the report using the report key. Then the function compares the input report MAC value with the
 /// calculated MAC value to determine whether the report is valid or not.
 ///
 /// # Parameters
 ///
 /// **report**
 ///
-/// A pointer to an sgx_report_t object that contains the cryptographic report to be verified. 
+/// A pointer to an sgx_report_t object that contains the cryptographic report to be verified.
 /// The report buffer must be within the enclave.
 ///
 /// # Requirements
@@ -155,17 +155,17 @@
 /// This function is a wrapper for the SGX EGETKEY instruction.
 ///
 /// # Description
-/// 
-/// The rsgx_get_key function generates a 128-bit secret key from the processor specific key hierarchy with 
-/// the key_request information. If the function fails with an error code, the key buffer will be filled with 
-/// random numbers. The key_request structure needs to be initialized properly to obtain the requested key type. 
+///
+/// The rsgx_get_key function generates a 128-bit secret key from the processor specific key hierarchy with
+/// the key_request information. If the function fails with an error code, the key buffer will be filled with
+/// random numbers. The key_request structure needs to be initialized properly to obtain the requested key type.
 /// See sgx_key_request_t for structure details.
 ///
 /// # Parameters
 ///
 /// **key_request**
 ///
-/// A pointer to a sgx_key_request_t object used for selecting the appropriate key and any additional parameters 
+/// A pointer to a sgx_key_request_t object used for selecting the appropriate key and any additional parameters
 /// required in the derivation of that key. The pointer must be located within the enclave.
 ///
 /// See details on the sgx_key_request_t to understand initializing this structure before calling this function.
diff --git a/sgx_tseal/Cargo.toml b/sgx_tseal/Cargo.toml
index f2ea399..d3e231c 100644
--- a/sgx_tseal/Cargo.toml
+++ b/sgx_tseal/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tseal"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Baidu"]
 
 [features]
diff --git a/sgx_tseal/src/aad.rs b/sgx_tseal/src/aad.rs
index 351278e..5a0ff1d 100644
--- a/sgx_tseal/src/aad.rs
+++ b/sgx_tseal/src/aad.rs
@@ -26,100 +26,49 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-//! 
+//!
 //! Provides APIs to authenticate and verify the input data with AES-GMAC.
 //!
 use sgx_types::*;
-use core::mem;
-use core::ptr;
+use sgx_types::marker::ContiguousMemory;
 use core::slice;
+use core::mem;
+use core::marker::PhantomData;
 use super::internal::*;
 #[cfg(not(feature = "use_std"))]
 use alloc::boxed::Box;
 
 /// The structure about sealed data, for authenticate and verify.
-pub struct SgxMacAadata<T: ?Sized> {
+pub struct SgxMacAadata<'a, T: 'a + ?Sized> {
     inner: SgxInternalSealedData,
-    marker: * const T,
+    marker: PhantomData<&'a T>,
 }
 
-impl<T> Default for SgxMacAadata<T> {
-    fn default() -> SgxMacAadata<T> {
+impl<'a, T: 'a + ?Sized> Default for SgxMacAadata<'a, T> {
+    fn default() -> SgxMacAadata<'a, T> {
         SgxMacAadata {
             inner: SgxInternalSealedData::new(),
-            marker: ptr::null(), 
+            marker: PhantomData,
         }
     }
 }
 
-impl<T> Default for SgxMacAadata<[T]> {
-    fn default() -> SgxMacAadata<[T]> {
-        let p = Box::<[T]>::default();
-        SgxMacAadata {
-            inner: SgxInternalSealedData::new(),
-            marker: Box::into_raw(p),
-        }
-    }
-}
-
-impl<T: ?Sized> Clone for SgxMacAadata<T> {
-    fn clone(&self) -> SgxMacAadata<T> {
+impl<'a, T: 'a + Clone + ?Sized> Clone for SgxMacAadata<'a, T> {
+    fn clone(&self) -> SgxMacAadata<'a, T> {
         SgxMacAadata {
            inner: self.inner.clone(),
-           marker: self.marker,
+           marker: PhantomData,
         }
     }
 }
 
-impl<T> SgxMacAadata<T> {
-    ///
-    /// Create a SgxMacAadata with default values.
-    /// 
-    pub fn new() -> Self {
-        SgxMacAadata::default()
-    }
+impl<'a, T: 'a + Copy + ContiguousMemory> SgxMacAadata<'a, T> {
 
-    /// 
-    /// Convert a pointer of sgx_sealed_data_t buffer to SgxMacAadata.
     ///
-    /// # Requirements
-    /// 
-    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
-    /// # Parameters
-    ///
-    /// **p**
-    ///
-    /// The mutable pointer of sgx_sealed_data_t buffer.
-    ///
-    /// **len**
-    ///
-    /// The size of the parameter `p`.
-    ///
-    /// # Return value 
-    ///
-    /// **Some(SgxMacAadata)**
-    ///
-    /// Indicates the conversion is successfully. The return value is SgxMacAadata.
-    ///
-    /// **None**
-    /// 
-    /// Maybe the size of T is zero.
-    /// 
-    pub unsafe fn from_raw_sealed_data_t(p: * mut sgx_sealed_data_t, len: u32) -> Option<Self> {
-        
-        let size = mem::size_of::<T>();
-        if size == 0 {
-            return None;
-        } 
-        SgxInternalSealedData::from_raw_sealed_data_t(p, len).map(|x| SgxMacAadata{inner: x, marker: ptr::null()})
-    }
-
-    /// 
     /// This function is used to authenticate the input data with AES-GMAC.
     ///
     /// # Descryption
-    /// 
+    ///
     /// The mac_aadata function retrieves a key unique to the enclave and
     /// uses that key to generate the authentication tag based on the input data buffer. This function can be utilized to provide authentication assurance for additional data (of practically unlimited length per invocation) that is not
     /// encrypted. The data origin authentication can be demonstrated on future
@@ -127,57 +76,60 @@
     /// Use `calc_raw_sealed_data_size` to calculate the number of bytes to
     /// allocate for the SgxMacAadata structure. The input sealed data buffer
     /// must be allocated within the enclave
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
+    ///
     /// # Parameters
     ///
     /// **additional_text**
     ///
     /// Pointer to the plain text to provide authentication for.
     ///
-    /// # Return value 
+    /// # Return value
     ///
     /// The sealed data in SgxMacAadata.
     ///
     /// # Errors
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
+    ///
     /// Indicates an error if the parameters do not meet any of the following conditions:
-    /// 
+    ///
     /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
     /// * encrypt_text must be non-zero.
     /// * encrypt_text buffer must be within the enclave.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// The enclave is out of memory.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
     ///
     /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
     /// random number.
-    /// 
+    ///
     pub fn mac_aadata(additional_text: &T) -> SgxResult<Self> {
 
         let size = mem::size_of::<T>();
         if size == 0 {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
-        } 
-        let aad_slice: &[u8] = unsafe{slice::from_raw_parts(additional_text as * const _ as * const u8, size)};      
+        }
+        let aad_slice: &[u8] = unsafe {
+            slice::from_raw_parts(additional_text as * const _ as * const u8, mem::size_of_val(additional_text))
+        };
+
         let result = SgxInternalSealedData::mac_aadata(aad_slice);
-        result.map(|x| SgxMacAadata {inner: x, marker: ptr::null()})
+        result.map(|x| SgxMacAadata {inner: x, marker: PhantomData})
     }
 
-    /// 
+    ///
     /// This function is used to authenticate the input data with AES-GMAC. This is
     /// the expert mode version of the function mac_aadata.
     ///
     /// # Descryption
-    /// 
+    ///
     /// The mac_aadata_ex is an extended version of mac_aadata. It
     /// provides parameters for you to identify how to derive the sealing key (key
     /// policy and attributes_mask). Typical callers of the seal library should be
@@ -186,58 +138,58 @@
     /// understanding of the impact of using a policy and/or attribute_mask that
     /// is different from that in mac_aadata.
     /// # Requirements
-    /// 
-    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
-    /// # Parameters
-    /// 
-    /// **key_policy**
-    /// 
-    /// Specifies the policy to use in the key derivation. Function sgx_seal_data uses the MRSIGNER policy. 
     ///
-    /// Key policy name | Value | Description 
+    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
+    ///
+    /// # Parameters
+    ///
+    /// **key_policy**
+    ///
+    /// Specifies the policy to use in the key derivation. Function sgx_seal_data uses the MRSIGNER policy.
+    ///
+    /// Key policy name | Value | Description
     /// ---|---|---
-    /// KEYPOLICY_MRENCLAVE | 0x0001 | -Derive key using the enclave??s ENCLAVE measurement register  
-    /// KEYPOLICY_MRSIGNER |0x0002 | -Derive key using the enclave??s SIGNER measurement register 
-    /// 
+    /// KEYPOLICY_MRENCLAVE | 0x0001 | -Derive key using the enclave??s ENCLAVE measurement register
+    /// KEYPOLICY_MRSIGNER |0x0002 | -Derive key using the enclave??s SIGNER measurement register
+    ///
     /// **attribute_mask**
-    /// 
-    /// Identifies which platform/enclave attributes to use in the key derivation. See  
-    /// the definition of sgx_attributes_t to determine which attributes will be  
-    /// checked.  Function sgx_seal_data uses flags=0xfffffffffffffff3,?xfrm=0. 
-    /// 
+    ///
+    /// Identifies which platform/enclave attributes to use in the key derivation. See
+    /// the definition of sgx_attributes_t to determine which attributes will be
+    /// checked.  Function sgx_seal_data uses flags=0xfffffffffffffff3,?xfrm=0.
+    ///
     /// **misc_mask**
     ///
     /// The misc mask bits for the enclave. Reserved for future function extension.
     ///
     /// **additional_text**
     ///
-    /// Pointer to the additional Message Authentication Code (MAC) data. 
+    /// Pointer to the additional Message Authentication Code (MAC) data.
     /// This additional data is optional and no data is necessary.
     ///
-    /// # Return value 
+    /// # Return value
     ///
     /// The sealed data in SgxSealedData.
     ///
     /// # Errors
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
+    ///
     /// Indicates an error if the parameters do not meet any of the following conditions:
-    /// 
+    ///
     /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
     /// * encrypt_text must be non-zero.
     /// * encrypt_text buffer must be within the enclave.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// The enclave is out of memory.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
     ///
     /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
     /// random number.
-    /// 
+    ///
     pub fn mac_aadata_ex(key_policy: u16,
                          attribute_mask: sgx_attributes_t,
                          misc_mask: sgx_misc_select_t,
@@ -246,59 +198,62 @@
         let size = mem::size_of::<T>();
         if size == 0 {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
-        } 
-        let aad_slice: &[u8] = unsafe{slice::from_raw_parts(additional_text as * const _ as * const u8, size)};
-        let result = SgxInternalSealedData::mac_aadata_ex(key_policy, 
-                                                          attribute_mask, 
-                                                          misc_mask, 
+        }
+        let aad_slice: &[u8] = unsafe {
+            slice::from_raw_parts(additional_text as * const _ as * const u8, mem::size_of_val(additional_text))
+        };
+
+        let result = SgxInternalSealedData::mac_aadata_ex(key_policy,
+                                                          attribute_mask,
+                                                          misc_mask,
                                                           aad_slice);
-        result.map(|x| SgxMacAadata {inner: x, marker: ptr::null()})
+        result.map(|x| SgxMacAadata {inner: x, marker: PhantomData})
     }
 
     ///
     /// This function is used to verify the authenticity of the input sealed data structure using AES-GMAC. This function verifies the MAC generated with sgx_mac_aadataorsgx_mac_aadata_ex.
     ///
     /// # Descryption
-    /// 
+    ///
     /// The sgx_unmac_aadata function verifies the tag with AES-GMAC. Use this
     /// function to demonstrate the authenticity of data that was preserved by an
     /// earlier instantiation of this enclave.
     ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
     ///
-    /// # Return value 
+    /// # Return value
     ///
     /// The pointer of the additional data.
     ///
     /// # Errors
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
+    ///
     /// The size of T may be zero.
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_CPUSVN**
-    /// 
+    ///
     /// The CPUSVN in the data blob is beyond the CPUSVN value of the platform.
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_ISVSVN**
-    /// 
+    ///
     /// The ISVSVN in the data blob is greater than the ISVSVN value of the enclave.
-    /// 
+    ///
     /// **SGX_ERROR_MAC_MISMATCH**
-    /// 
+    ///
     /// The tag verification fails. The error may be caused by a platform update, software update, or corruption of the sealed_data_t structure.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// The enclave is out of memory.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
     ///
     /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
     /// random number.
-    /// 
+    ///
     pub fn unmac_aadata(&self) -> SgxResult<Box<T>> {
 
         let size = mem::size_of::<T>();
@@ -309,148 +264,26 @@
         if size != aad_len {
             return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
         }
+
         self.inner.unmac_aadata().map(|x| {
             let ptr = Box::into_raw(x.additional);
-            unsafe{Box::from_raw(ptr as * mut _ as * mut T)}
+            unsafe{Box::from_raw(ptr as * mut T)}
         })
     }
-}
 
-impl<T> SgxMacAadata<[T]> {
     ///
-    /// Create a SgxMacAadata with default values.
-    /// 
-    pub fn new() -> Self {
-        SgxMacAadata::default()
-    }
-
-    /// 
     /// Convert a pointer of sgx_sealed_data_t buffer to SgxMacAadata.
     ///
     pub unsafe fn from_raw_sealed_data_t(p: * mut sgx_sealed_data_t, len: u32) -> Option<Self> {
-        
+
         let size = mem::size_of::<T>();
         if size == 0 {
             return None;
-        } 
+        }
         let opt = SgxInternalSealedData::from_raw_sealed_data_t(p, len);
-        opt.map(|x| {
-            let p = Box::<[T]>::default();
-            SgxMacAadata{inner: x, marker: Box::into_raw(p)}
-        })
+        opt.map(|x| SgxMacAadata{inner: x, marker: PhantomData})
     }
 
-    /// 
-    /// This function is used to authenticate the input data with AES-GMAC.
-    ///
-    pub fn mac_aadata(additional_text: &[T]) -> SgxResult<Self> {
-
-        let size = mem::size_of::<T>() * additional_text.len();
-        if size == 0 {
-            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
-        }
-        let aad_slice: &[u8] = unsafe{slice::from_raw_parts(additional_text.as_ptr() as * const _ as * const u8, size)};      
-        let result = SgxInternalSealedData::mac_aadata(aad_slice);
-        result.map(|x| {
-            let p = Box::<[T]>::default();
-            SgxMacAadata {
-                inner: x,
-                marker: Box::into_raw(p),
-            }
-        })
-    }
-
-    /// 
-    /// This function is used to authenticate the input data with AES-GMAC. This is
-    /// the expert mode version of the function mac_aadata.
-    ///
-    pub fn mac_aadata_ex(key_policy: u16,
-                         attribute_mask: sgx_attributes_t,
-                         misc_mask: sgx_misc_select_t,
-                         additional_text: &[T]) -> SgxResult<Self> {
-
-        let size = mem::size_of::<T>() * additional_text.len();
-        if size == 0 {
-            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
-        }
-        let aad_slice: &[u8] = unsafe{slice::from_raw_parts(additional_text.as_ptr() as * const _ as * const u8, size)};
-        let result = SgxInternalSealedData::mac_aadata_ex(key_policy, 
-                                                          attribute_mask, 
-                                                          misc_mask, 
-                                                          aad_slice);
-        result.map(|x| {
-            let p = Box::<[T]>::default();
-            SgxMacAadata {
-                inner: x,
-                marker: Box::into_raw(p),
-            }
-        })
-    }
-
-    ///
-    /// This function is used to verify the authenticity of the input sealed data structure using AES-GMAC. This function verifies the MAC generated with sgx_mac_aadataorsgx_mac_aadata_ex.
-    ///
-    pub fn unmac_aadata(&self) -> SgxResult<Box<[T]>> {
-
-        let size = mem::size_of::<T>();
-        if size == 0 {
-            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
-        }
-        let aad_len = self.get_add_mac_txt_len() as usize;
-        if size > aad_len {
-            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
-        }
-        if (aad_len % size) != 0 {
-            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
-        }
-        self.inner.unmac_aadata().map(|x| {
-            let ptr = Box::into_raw(x.additional);
-            unsafe{Box::from_raw(ptr as * mut _ as * mut [T])}
-        })
-    }
-}
-
-impl<T: ?Sized> SgxMacAadata<T> {
-    ///
-    /// Get the size of payload in SgxMacAadata.
-    ///
-    pub fn get_payload_size(&self) -> u32 {
-        self.inner.get_payload_size()
-    }
-    ///
-    /// Get a slice of payload in SgxMacAadata.
-    ///
-    pub fn get_payload_tag(&self) -> &[u8; SGX_SEAL_TAG_SIZE] {
-        self.inner.get_payload_tag()
-    }
-    ///
-    /// Get the pointer of sgx_key_request_t in SgxMacAadata.
-    ///
-    pub fn get_key_request(&self) -> &sgx_key_request_t {
-        self.inner.get_key_request()
-    }
-
-    ///
-    /// Get a slice of additional text in SgxMacAadata.
-    ///
-    pub fn get_additional_txt(&self) -> &[u8] {
-        self.inner.get_additional_txt()
-    }
-
-    ///
-    /// Calculate the size of the sealed data in SgxMacAadata.
-    ///
-    pub fn calc_raw_sealed_data_size(add_mac_txt_size: u32, encrypt_txt_size: u32) -> u32  {
-        SgxInternalSealedData::calc_raw_sealed_data_size(add_mac_txt_size, encrypt_txt_size)
-    }
-
-    ///
-    /// Get the size of the additional mactext in SgxMacAadata.
-    ///
-    pub fn get_add_mac_txt_len(&self) -> u32 {
-        self.inner.get_add_mac_txt_len()
-    } 
-
     ///
     /// Convert SgxMacAadata to the pointer of sgx_sealed_data_t.
     ///
@@ -477,4 +310,166 @@
     pub unsafe fn to_raw_sealed_data_t(&self, p: * mut sgx_sealed_data_t, len: u32) -> Option<* mut sgx_sealed_data_t> {
         self.inner.to_raw_sealed_data_t(p, len)
     }
-}
\ No newline at end of file
+}
+
+impl<'a, T: 'a + Copy + ContiguousMemory> SgxMacAadata<'a, [T]> {
+
+    ///
+    /// This function is used to authenticate the input data with AES-GMAC.
+    ///
+    pub fn mac_aadata(additional_text: &[T]) -> SgxResult<Self> {
+
+        let size = mem::size_of::<T>();
+        let len = mem::size_of_val(additional_text);
+        if size == 0 || len == 0 {
+            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
+        }
+        let aad_slice: &[u8] = unsafe {
+            slice::from_raw_parts(additional_text.as_ptr() as * const u8, len)
+        };
+
+        let result = SgxInternalSealedData::mac_aadata(aad_slice);
+        result.map(|x| SgxMacAadata {inner: x, marker: PhantomData})
+    }
+
+    ///
+    /// This function is used to authenticate the input data with AES-GMAC. This is
+    /// the expert mode version of the function mac_aadata.
+    ///
+    pub fn mac_aadata_ex(key_policy: u16,
+                         attribute_mask: sgx_attributes_t,
+                         misc_mask: sgx_misc_select_t,
+                         additional_text: &[T]) -> SgxResult<Self> {
+
+        let size = mem::size_of::<T>();
+        let len = mem::size_of_val(additional_text);
+        if size == 0 || len == 0 {
+            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
+        }
+        let aad_slice: &[u8] = unsafe {
+            slice::from_raw_parts(additional_text.as_ptr() as * const u8, len)
+        };
+        let result = SgxInternalSealedData::mac_aadata_ex(key_policy,
+                                                          attribute_mask,
+                                                          misc_mask,
+                                                          aad_slice);
+        result.map(|x| SgxMacAadata {inner: x, marker: PhantomData})
+    }
+
+    ///
+    /// This function is used to verify the authenticity of the input sealed data structure using AES-GMAC. This function verifies the MAC generated with sgx_mac_aadataorsgx_mac_aadata_ex.
+    ///
+    pub fn unmac_aadata(&self) -> SgxResult<Box<[T]>> {
+
+        let size = mem::size_of::<T>();
+        if size == 0 {
+            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
+        }
+        let aad_len = self.get_add_mac_txt_len() as usize;
+        if size > aad_len {
+            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
+        }
+        if (aad_len % size) != 0 {
+            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
+        }
+         self.inner.unmac_aadata().map(|x| {
+            let ptr = (x.additional).as_ptr() as * mut T;
+            unsafe {
+                let mut slice = slice::from_raw_parts_mut(ptr, aad_len/size);
+                Box::from_raw(slice as * mut [T])
+            }
+        })
+    }
+
+    ///
+    /// Convert a pointer of sgx_sealed_data_t buffer to SgxMacAadata.
+    ///
+    pub unsafe fn from_raw_sealed_data_t(p: * mut sgx_sealed_data_t, len: u32) -> Option<Self> {
+
+        let size = mem::size_of::<T>();
+        if size == 0 {
+            return None;
+        }
+        let opt = SgxInternalSealedData::from_raw_sealed_data_t(p, len);
+        opt.map(|x| SgxMacAadata{inner: x, marker: PhantomData})
+    }
+
+    ///
+    /// Convert SgxMacAadata to the pointer of sgx_sealed_data_t.
+    ///
+    /// # Parameters
+    ///
+    /// **p**
+    ///
+    /// The pointer of sgx_sealed_data_t to save the data in SgxMacAadata.
+    ///
+    /// **len**
+    ///
+    /// The size of the pointer of sgx_sealed_data_t.
+    ///
+    /// # Error
+    ///
+    /// **Some(* mut sgx_sealed_data_t)**
+    ///
+    /// Indicates the conversion is successfully. The return value is the pointer of sgx_sealed_data_t.
+    ///
+    /// **None**
+    ///
+    /// May be the parameter p and len is not avaliable.
+    ///
+    pub unsafe fn to_raw_sealed_data_t(&self, p: * mut sgx_sealed_data_t, len: u32) -> Option<* mut sgx_sealed_data_t> {
+        self.inner.to_raw_sealed_data_t(p, len)
+    }
+}
+
+impl<'a, T: 'a + ?Sized> SgxMacAadata<'a, T> {
+
+    ///
+    /// Create a SgxMacAadata with default values.
+    ///
+    pub fn new() -> Self {
+        SgxMacAadata::default()
+    }
+
+    ///
+    /// Get the size of payload in SgxMacAadata.
+    ///
+    pub fn get_payload_size(&self) -> u32 {
+        self.inner.get_payload_size()
+    }
+
+    ///
+    /// Get a slice of payload in SgxMacAadata.
+    ///
+    pub fn get_payload_tag(&self) -> &[u8; SGX_SEAL_TAG_SIZE] {
+        self.inner.get_payload_tag()
+    }
+
+    ///
+    /// Get the pointer of sgx_key_request_t in SgxMacAadata.
+    ///
+    pub fn get_key_request(&self) -> &sgx_key_request_t {
+        self.inner.get_key_request()
+    }
+
+    ///
+    /// Get a slice of additional text in SgxMacAadata.
+    ///
+    pub fn get_additional_txt(&self) -> &[u8] {
+        self.inner.get_additional_txt()
+    }
+
+    ///
+    /// Calculate the size of the sealed data in SgxMacAadata.
+    ///
+    pub fn calc_raw_sealed_data_size(add_mac_txt_size: u32, encrypt_txt_size: u32) -> u32  {
+        SgxInternalSealedData::calc_raw_sealed_data_size(add_mac_txt_size, encrypt_txt_size)
+    }
+
+    ///
+    /// Get the size of the additional mactext in SgxMacAadata.
+    ///
+    pub fn get_add_mac_txt_len(&self) -> u32 {
+        self.inner.get_add_mac_txt_len()
+    }
+}
diff --git a/sgx_tseal/src/internal.rs b/sgx_tseal/src/internal.rs
index 087607e..0c2bf1e 100644
--- a/sgx_tseal/src/internal.rs
+++ b/sgx_tseal/src/internal.rs
@@ -32,15 +32,57 @@
 use sgx_tse::*;
 use core::mem;
 use core::ptr;
-use super::seal::SgxUnsealedData;
 #[cfg(not(feature = "use_std"))]
 use alloc::boxed::Box;
 #[cfg(not(feature = "use_std"))]
 use collections::vec::Vec;
 
-const SGX_MISCSEL_EXINFO: uint32_t     = 0x00000001;
-const TSEAL_DEFAULT_MISCMASK: uint32_t = (!SGX_MISCSEL_EXINFO);
+//const SGX_MISCSEL_EXINFO: uint32_t     = 0x00000001;
+//const TSEAL_DEFAULT_MISCMASK: uint32_t = (!SGX_MISCSEL_EXINFO);
 
+/* intel sgx sdk 1.8 */
+/* Set the bits which have no security implications to 0 for sealed data migration */
+/* Bits which have no security implications in attributes.flags:
+ *    Reserved bit[55:6]  - 0xFFFFFFFFFFFFC0ULL
+ *    SGX_FLAGS_MODE64BIT
+ *    SGX_FLAGS_PROVISION_KEY
+ *    SGX_FLAGS_EINITTOKEN_KEY */
+const FLAGS_NON_SECURITY_BITS: uint64_t = (0x00FFFFFFFFFFFFC0 | SGX_FLAGS_MODE64BIT | SGX_FLAGS_PROVISION_KEY| SGX_FLAGS_EINITTOKEN_KEY);
+const TSEAL_DEFAULT_FLAGSMASK: uint64_t = (!FLAGS_NON_SECURITY_BITS);
+
+const MISC_NON_SECURITY_BITS: uint32_t =  0x0FFFFFFF;  /* bit[27:0]: have no security implications */
+const TSEAL_DEFAULT_MISCMASK: uint32_t =  (!MISC_NON_SECURITY_BITS);
+
+#[derive(Clone, Default)]
+pub struct SgxInternalUnsealedData {
+    pub payload_size: u32,
+    pub decrypt: Box<[u8]>,
+    pub additional: Box<[u8]>,
+}
+
+impl SgxInternalUnsealedData {
+    ///
+    /// Get the payload size of the SgxInternalUnsealedData.
+    ///
+    #[allow(dead_code)]
+    pub fn get_payload_size(&self) -> u32 {
+        self.payload_size
+    }
+    ///
+    /// Get the pointer of decrypt buffer in SgxInternalUnsealedData.
+    ///
+    #[allow(dead_code)]
+    pub fn get_decrypt_txt(&self) -> &[u8] {
+        &*self.decrypt
+    }
+    ///
+    /// Get the pointer of additional buffer in SgxInternalUnsealedData.
+    ///
+    #[allow(dead_code)]
+    pub fn get_additional_txt(&self) -> &[u8] {
+        &*self.additional
+    }
+}
 
 #[derive(Clone, Default)]
 struct SgxPayload {
@@ -77,7 +119,7 @@
     pub fn get_additional_txt(&self) -> &[u8] {
         &*self.payload_data.additional
     }
-    
+
     pub fn calc_raw_sealed_data_size(add_mac_txt_size: u32, encrypt_txt_size: u32) -> u32 {
 
         let max = u32::max_value();
@@ -89,7 +131,7 @@
         let payload_size: u32 = add_mac_txt_size + encrypt_txt_size;
         if payload_size > max - sealed_data_size {
             return max;
-        }           
+        }
         sealed_data_size + payload_size
     }
 
@@ -104,9 +146,9 @@
             data_size as u32
         }
     }
-    
+
     pub fn get_encrypt_txt_len(&self) -> u32 {
-        
+
         let data_size = self.payload_data.encrypt.len();
         if data_size > self.payload_data.payload_size as usize {
             u32::max_value()
@@ -122,7 +164,7 @@
         if p.is_null() {
             return None;
         }
-        if rsgx_raw_is_within_enclave(p as * mut u8, len as usize) == false && 
+        if rsgx_raw_is_within_enclave(p as * mut u8, len as usize) == false &&
            rsgx_raw_is_outside_enclave(p as * mut u8, len as usize) == false {
             return None;
         }
@@ -139,7 +181,7 @@
         let sealed_data_size = sgx_calc_sealed_data_size(additional_len, encrypt_len);
         if sealed_data_size == u32::max_value() {
             return None;
-        }  
+        }
         if len < sealed_data_size {
             return None;
         }
@@ -153,13 +195,13 @@
             let ptr_additional = ptr_encrypt.offset(encrypt_len as isize);
             ptr::copy_nonoverlapping(self.payload_data.additional.as_ptr(), ptr_additional, additional_len as usize);
         }
-        
+
         let mut raw_sealed_data = Box::from_raw(p);
         raw_sealed_data.key_request = self.key_request;
         raw_sealed_data.plain_text_offset = encrypt_len;
         raw_sealed_data.aes_data.payload_size = self.payload_data.payload_size;
         raw_sealed_data.aes_data.payload_tag = self.payload_data.payload_tag;
-        mem::forget(raw_sealed_data); 
+        mem::forget(raw_sealed_data);
 
         Some(p)
     }
@@ -169,7 +211,7 @@
         if p.is_null() {
             return None;
         }
-        if rsgx_raw_is_within_enclave(p as * mut u8, len as usize) == false && 
+        if rsgx_raw_is_within_enclave(p as * mut u8, len as usize) == false &&
            rsgx_raw_is_outside_enclave(p as * mut u8, len as usize) == false {
             return None;
         }
@@ -200,7 +242,7 @@
         if len < sealed_data_size {
             return None;
         }
-         
+
         let ptr_encrypt = ptr_sealed_data.offset(mem::size_of::<sgx_sealed_data_t>() as isize);
         let mut encrypt: Vec<u8> =  Vec::new();
         if encrypt_len > 0 {
@@ -208,7 +250,7 @@
             temp.set_len(encrypt_len as usize);
             ptr::copy_nonoverlapping(ptr_encrypt as * const u8, temp.as_mut_ptr(), encrypt_len as usize);
             encrypt = temp;
-        } 
+        }
 
         let mut additional: Vec<u8> = Vec::new();
         if additional_len > 0 {
@@ -217,7 +259,7 @@
             temp.set_len(additional_len as usize);
             ptr::copy_nonoverlapping(ptr_additional as * const u8, temp.as_mut_ptr(), additional_len as usize);
             additional = temp;
-        } 
+        }
 
         let mut sealed_data = Self::default();
         sealed_data.key_request = raw_sealed_data.key_request;
@@ -230,12 +272,13 @@
 
         Some(sealed_data)
     }
-    
-    pub fn seal_data(additional_text: &[u8], encrypt_text: &[u8]) -> SgxResult<Self> {
-        
-        let attribute_mask = sgx_attributes_t{flags: SGX_FLAGS_RESERVED | SGX_FLAGS_INITTED | SGX_FLAGS_DEBUG, xfrm: 0};
 
-        Self::seal_data_ex(SGX_KEYPOLICY_MRSIGNER, 
+    pub fn seal_data(additional_text: &[u8], encrypt_text: &[u8]) -> SgxResult<Self> {
+
+        //let attribute_mask = sgx_attributes_t{flags: SGX_FLAGS_RESERVED | SGX_FLAGS_INITTED | SGX_FLAGS_DEBUG, xfrm: 0};
+        /* intel sgx sdk 1.8 */
+        let attribute_mask = sgx_attributes_t{flags: TSEAL_DEFAULT_FLAGSMASK, xfrm: 0};
+        Self::seal_data_ex(SGX_KEYPOLICY_MRSIGNER,
                            attribute_mask,
                            TSEAL_DEFAULT_MISCMASK,
                            additional_text,
@@ -245,9 +288,9 @@
     pub fn seal_data_ex(key_policy: u16,
                         attribute_mask: sgx_attributes_t,
                         misc_mask: sgx_misc_select_t,
-                        additional_text: &[u8], 
+                        additional_text: &[u8],
                         encrypt_text: &[u8]) -> SgxResult<Self> {
-        
+
         let additional_len = additional_text.len();
         let encrypt_len = encrypt_text.len();
 
@@ -260,12 +303,12 @@
         if encrypt_len == 0 {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
         }
-        
+
         if (key_policy & (!(SGX_KEYPOLICY_MRENCLAVE | SGX_KEYPOLICY_MRSIGNER)) != 0) ||
            ((key_policy &  (SGX_KEYPOLICY_MRENCLAVE | SGX_KEYPOLICY_MRSIGNER)) == 0) {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
         }
-        if ((attribute_mask.flags & SGX_FLAGS_INITTED) == 0) || 
+        if ((attribute_mask.flags & SGX_FLAGS_INITTED) == 0) ||
            ((attribute_mask.flags & SGX_FLAGS_DEBUG) == 0) {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
         }
@@ -283,17 +326,17 @@
 
         let target_info = sgx_target_info_t::default();
         let report_data = sgx_report_data_t::default();
-        let mut key_id = sgx_key_id_t::default(); 
+        let mut key_id = sgx_key_id_t::default();
 
         let mut report = try!(rsgx_create_report(&target_info, &report_data));
-        
+
         let error = rsgx_read_rand(&mut key_id.id);
         if error.is_err() {
             report = sgx_report_t::default();
             key_id = sgx_key_id_t::default();
             return Err(error.unwrap_err());
         }
-       
+
         let key_request = sgx_key_request_t{key_name: SGX_KEYSELECT_SEAL,
                                             key_policy: key_policy,
                                             isv_svn: report.body.isv_svn,
@@ -316,9 +359,9 @@
 
         result
     }
- 
-    pub fn unseal_data(&self) -> SgxResult<SgxUnsealedData<[u8]>> {
-        
+
+    pub fn unseal_data(&self) -> SgxResult<SgxInternalUnsealedData> {
+
         let additional_len = self.get_add_mac_txt_len();
         let encrypt_len = self.get_encrypt_txt_len();
 
@@ -345,15 +388,15 @@
                 return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
             }
         }
-        
+
         self.unseal_data_helper()
     }
 
     pub fn mac_aadata(additional_text: &[u8]) -> SgxResult<Self> {
-        
+
         let attribute_mask = sgx_attributes_t{flags: SGX_FLAGS_RESERVED | SGX_FLAGS_INITTED | SGX_FLAGS_DEBUG, xfrm: 0};
 
-        Self::mac_aadata_ex(SGX_KEYPOLICY_MRSIGNER, 
+        Self::mac_aadata_ex(SGX_KEYPOLICY_MRSIGNER,
                             attribute_mask,
                             TSEAL_DEFAULT_MISCMASK,
                             additional_text)
@@ -363,7 +406,7 @@
                          attribute_mask: sgx_attributes_t,
                          misc_mask: sgx_misc_select_t,
                          additional_text: &[u8]) -> SgxResult<Self> {
-        
+
         let additional_len = additional_text.len();
         if additional_len >= u32::max_value() as usize {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
@@ -374,7 +417,7 @@
         if additional_len == 0 {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
         }
-        
+
         if (key_policy & (!(SGX_KEYPOLICY_MRENCLAVE | SGX_KEYPOLICY_MRSIGNER)) != 0) ||
            ((key_policy &  (SGX_KEYPOLICY_MRENCLAVE | SGX_KEYPOLICY_MRSIGNER)) == 0) {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
@@ -387,20 +430,20 @@
            (rsgx_slice_is_outside_enclave(additional_text) == false) {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
         }
-        
+
         let target_info = sgx_target_info_t::default();
         let report_data = sgx_report_data_t::default();
-        let mut key_id = sgx_key_id_t::default(); 
+        let mut key_id = sgx_key_id_t::default();
 
         let mut report = try!(rsgx_create_report(&target_info, &report_data));
-        
+
         let error = rsgx_read_rand(&mut key_id.id);
         if error.is_err() {
             report = sgx_report_t::default();
             key_id = sgx_key_id_t::default();
             return Err(error.unwrap_err());
         }
-        
+
         let key_request = sgx_key_request_t{key_name: SGX_KEYSELECT_SEAL,
                                             key_policy: key_policy,
                                             isv_svn: report.body.isv_svn,
@@ -424,8 +467,8 @@
         result
     }
 
-    pub fn unmac_aadata(&self) -> SgxResult<SgxUnsealedData<[u8]>> {
-        
+    pub fn unmac_aadata(&self) -> SgxResult<SgxInternalUnsealedData> {
+
         let additional_len = self.get_add_mac_txt_len();
         let encrypt_len = self.get_encrypt_txt_len();
 
@@ -454,13 +497,13 @@
 
         self.unseal_data_helper()
     }
-  
-    fn seal_data_iv(additional_text: &[u8], 
+
+    fn seal_data_iv(additional_text: &[u8],
                     encrypt_text: &[u8],
                     payload_iv: &[u8],
                     key_request: &sgx_key_request_t) -> SgxResult<Self>  {
 
-        
+
         let mut seal_key = try!(rsgx_get_key(key_request).map_err(|ret| {
             if ret != sgx_status_t::SGX_ERROR_OUT_OF_MEMORY {
                 sgx_status_t::SGX_ERROR_UNEXPECTED
@@ -468,16 +511,16 @@
                 ret
             }
         }));
-    
+
         let mut sealed_data = SgxInternalSealedData::default();
         sealed_data.payload_data.encrypt = vec![0_u8; encrypt_text.len()].into_boxed_slice();
 
-        let error = rsgx_rijndael128GCM_encrypt(&seal_key, 
-                                              encrypt_text, 
-                                              payload_iv, 
-                                              &additional_text, 
-                                              &mut sealed_data.payload_data.encrypt,
-                                              &mut sealed_data.payload_data.payload_tag);
+        let error = rsgx_rijndael128GCM_encrypt(&seal_key,
+                                                encrypt_text,
+                                                payload_iv,
+                                                &additional_text,
+                                                &mut sealed_data.payload_data.encrypt,
+                                                &mut sealed_data.payload_data.payload_tag);
         if error.is_err() {
             seal_key = sgx_key_128bit_t::default();
             return Err(error.unwrap_err());
@@ -493,11 +536,11 @@
         Ok(sealed_data)
     }
 
-    fn unseal_data_helper(&self) -> SgxResult<SgxUnsealedData<[u8]>> {
+    fn unseal_data_helper(&self) -> SgxResult<SgxInternalUnsealedData> {
 
         let mut seal_key = try!(rsgx_get_key(self.get_key_request()).map_err(|ret| {
-            if (ret == sgx_status_t::SGX_ERROR_INVALID_CPUSVN) || 
-               (ret == sgx_status_t::SGX_ERROR_INVALID_ISVSVN) || 
+            if (ret == sgx_status_t::SGX_ERROR_INVALID_CPUSVN) ||
+               (ret == sgx_status_t::SGX_ERROR_INVALID_ISVSVN) ||
                (ret == sgx_status_t::SGX_ERROR_OUT_OF_MEMORY) {
                 ret
             } else {
@@ -506,15 +549,15 @@
         }));
 
         let payload_iv = [0_u8; SGX_SEAL_IV_SIZE];
-        let mut unsealed_data: SgxUnsealedData<[u8]> = SgxUnsealedData::default();
+        let mut unsealed_data: SgxInternalUnsealedData = SgxInternalUnsealedData::default();
         unsealed_data.decrypt = vec![0_u8; self.payload_data.encrypt.len()].into_boxed_slice();
 
-        let error = rsgx_rijndael128GCM_decrypt(&seal_key, 
-                                              self.get_encrypt_txt(), 
-                                              &payload_iv,
-                                              self.get_additional_txt(),
-                                              self.get_payload_tag(),
-                                              &mut unsealed_data.decrypt);
+        let error = rsgx_rijndael128GCM_decrypt(&seal_key,
+                                                self.get_encrypt_txt(),
+                                                &payload_iv,
+                                                self.get_additional_txt(),
+                                                self.get_payload_tag(),
+                                                &mut unsealed_data.decrypt);
         if error.is_err() {
             seal_key = sgx_key_128bit_t::default();
             return Err(error.unwrap_err());
@@ -529,4 +572,4 @@
 
         Ok(unsealed_data)
     }
-}
\ No newline at end of file
+}
diff --git a/sgx_tseal/src/lib.rs b/sgx_tseal/src/lib.rs
index 6100b09..e389f96 100644
--- a/sgx_tseal/src/lib.rs
+++ b/sgx_tseal/src/lib.rs
@@ -27,15 +27,15 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 //! # Intel(R) Software Guard Extensions Sealing and Unsealing Functions
-//! 
+//!
 //! The library provides the following functions:
-//! 
+//!
 //! * Exposes APIs to create sealed data which is both confidentiality andintegrity protected.
 //! * Exposes an API to unseal sealed data inside the enclave.
 //! * Provides APIs to authenticate and verify the input data with AES-GMAC.
-//! 
+//!
 //! The library also provides APIs to help calculate the sealed data size, encrypt text length, and Message Authentication Code (MAC) text length.
-//! 
+//!
 //! # Description
 //!
 //! When an enclave is instantiated, it provides protections (confidentiality and
@@ -74,7 +74,7 @@
 //! hash function. GCM can also provide authentication assurance for additional
 //! data (of practically unlimited length per invocation) that is not encrypted. GCM
 //! can also provide authentication assurance for additional data (of practically
-//! unlimited length per invocation) that is not encrypted. If the GCM input contains 
+//! unlimited length per invocation) that is not encrypted. If the GCM input contains
 //! only data that is not to be encrypted, the resulting specialization of GCM,
 //! called GMAC (Galois Message Authentication Code), is simply an authentication
 //! mode for the input data. The mac_aadata API call restricts the input to
@@ -89,6 +89,7 @@
 
 #![allow(non_camel_case_types)]
 #![allow(unused_assignments)]
+#![allow(deprecated)]
 #[cfg(feature = "use_std")]
 #[macro_use]
 extern crate std as core;
@@ -105,10 +106,10 @@
 extern crate sgx_tcrypto;
 extern crate sgx_tse;
 
-pub mod seal;
+mod seal;
 pub use self::seal::*;
 
-pub mod aad;
+mod aad;
 pub use self::aad::*;
 
-mod internal;
\ No newline at end of file
+mod internal;
diff --git a/sgx_tseal/src/seal.rs b/sgx_tseal/src/seal.rs
index f2d84ff..400cf9e 100644
--- a/sgx_tseal/src/seal.rs
+++ b/sgx_tseal/src/seal.rs
@@ -30,168 +30,121 @@
 //! Intel(R) Software Guard Extensions Sealing and Unsealing Functions
 //!
 //! # Intel(R) Software Guard Extensions Sealing and Unsealing Functions
-//! 
+//!
 //! The API of the model provides the following functions:
-//! 
+//!
 //! * Exposes APIs to create sealed data which is both confidentiality andintegrity protected.
 //! * Exposes an API to unseal sealed data inside the enclave.
 //!
 //! The library also provides APIs to help calculate the sealed data size, encrypt text length, and Message Authentication Code (MAC) text length.
 //!
 use sgx_types::*;
-use core::mem;
-use core::ptr;
+use sgx_types::marker::ContiguousMemory;
 use core::slice;
+use core::mem;
+use core::marker::PhantomData;
 use super::internal::*;
 #[cfg(not(feature = "use_std"))]
 use alloc::boxed::Box;
 
 /// The structure about the unsealed data.
-pub struct SgxUnsealedData<T: ?Sized> {
+pub struct SgxUnsealedData<'a, T: 'a + ?Sized> {
     pub payload_size: u32,
     pub decrypt: Box<T>,
     pub additional: Box<[u8]>,
+    marker: PhantomData<&'a T>,
 }
 
-impl<T: ?Sized> SgxUnsealedData<T> {
-    /// 
+impl<'a, T: 'a + ?Sized> SgxUnsealedData<'a, T> {
+    ///
     /// Get the payload size of the SgxUnsealedData.
-    /// 
+    ///
     pub fn get_payload_size(&self) -> u32 {
         self.payload_size
     }
     ///
     /// Get the pointer of decrypt buffer in SgxUnsealedData.
-    ///  
+    ///
     pub fn get_decrypt_txt(&self) -> &T {
         &*self.decrypt
     }
     ///
     /// Get the pointer of additional buffer in SgxUnsealedData.
-    /// 
+    ///
     pub fn get_additional_txt(&self) -> &[u8] {
         &*self.additional
     }
 }
 
-impl<T: Default> Default for SgxUnsealedData<T> {
-    fn default() -> SgxUnsealedData<T> {
+impl<'a, T: 'a + Default> Default for SgxUnsealedData<'a, T> {
+    fn default() -> SgxUnsealedData<'a, T> {
         SgxUnsealedData {
             payload_size: 0_u32,
             decrypt: Box::<T>::default(),
-            additional: Box::<[u8]>::default()
+            additional: Box::<[u8]>::default(),
+            marker: PhantomData,
         }
     }
 }
 
-impl<T> Default for SgxUnsealedData<[T]> {
-    fn default() -> SgxUnsealedData<[T]> {
+impl<'a, T: 'a + Default> Default for SgxUnsealedData<'a, [T]> {
+    fn default() -> SgxUnsealedData<'a, [T]> {
         SgxUnsealedData {
             payload_size: 0_u32,
             decrypt: Box::<[T]>::default(),
-            additional: Box::<[u8]>::default()
+            additional: Box::<[u8]>::default(),
+            marker: PhantomData,
         }
     }
 }
 
-impl<T: Clone + ?Sized> Clone for SgxUnsealedData<T> {
-    fn clone(&self) -> SgxUnsealedData<T> {
+impl<'a, T: 'a + Clone + ?Sized> Clone for SgxUnsealedData<'a, T> {
+    fn clone(&self) -> SgxUnsealedData<'a, T> {
         SgxUnsealedData {
            payload_size: self.payload_size,
            decrypt: self.decrypt.clone(),
-           additional: self.additional.clone()
+           additional: self.additional.clone(),
+           marker: PhantomData,
         }
     }
 }
 
-/// The structure about the sealed data. 
-pub struct SgxSealedData<T: ?Sized> {
+/// The structure about the sealed data.
+pub struct SgxSealedData<'a, T: 'a + ?Sized> {
     inner: SgxInternalSealedData,
-    marker: * const T,
+    marker: PhantomData<&'a T>,
 }
 
-impl<T> Default for SgxSealedData<T> {
-    fn default() -> SgxSealedData<T> {
+impl<'a, T: 'a + ?Sized> Default for SgxSealedData<'a, T> {
+    fn default() -> SgxSealedData<'a, T> {
         SgxSealedData {
             inner: SgxInternalSealedData::new(),
-            marker: ptr::null(), 
+            marker: PhantomData,
         }
     }
 }
 
-impl<T> Default for SgxSealedData<[T]> {
-    fn default() -> SgxSealedData<[T]> {
-        let p = Box::<[T]>::default();
-        SgxSealedData {
-            inner: SgxInternalSealedData::new(),
-            marker: Box::into_raw(p),
-        }
-    }
-}
-
-impl<T: ?Sized> Clone for SgxSealedData<T> {
-    fn clone(&self) -> SgxSealedData<T> {
+impl<'a, T: 'a + Clone + ?Sized> Clone for SgxSealedData<'a, T> {
+    fn clone(&self) -> SgxSealedData<'a, T> {
         SgxSealedData {
            inner: self.inner.clone(),
-           marker: self.marker,
+           marker: PhantomData,
         }
     }
 }
 
-/// The encrypt_text to seal is T, and T must have Copy trait. 
-impl<T: Copy> SgxSealedData<T> {
-    ///
-    /// Create a SgxSealedData with default values.
-    /// 
-    pub fn new() -> Self {
-        SgxSealedData::default()
-    }
+/// The encrypt_text to seal is T, and T must have Copy and ContiguousMemory trait.
+impl<'a, T: 'a + Copy + ContiguousMemory> SgxSealedData<'a, T> {
 
-    /// 
-    /// Convert a pointer of sgx_sealed_data_t buffer to SgxSealedData.
     ///
-    /// # Requirements
-    /// 
-    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
-    /// # Parameters
-    ///
-    /// **p**
-    ///
-    /// The mutable pointer of sgx_sealed_data_t buffer.
-    ///
-    /// **len**
-    ///
-    /// The size of the parameter `p`.
-    ///
-    /// # Return value 
-    ///
-    /// **Some(SgxSealedData)**
-    ///
-    /// Indicates the conversion is successfully. The return value is SgxSealedData.
-    ///
-    /// **None**
-    /// 
-    /// Maybe the size of T is zero.
-    /// 
-    pub unsafe fn from_raw_sealed_data_t(p: * mut sgx_sealed_data_t, len: u32) -> Option<Self> {
-        
-        let size = mem::size_of::<T>();
-        if size == 0 {
-            return None;
-        } 
-        SgxInternalSealedData::from_raw_sealed_data_t(p, len).map(|x| SgxSealedData{inner: x, marker: ptr::null()})
-    }
-
-    /// 
     /// This function is used to AES-GCM encrypt the input data. Two input data sets
-    /// are provided: one is the data to be encrypted; the second is optional additional data 
+    /// are provided: one is the data to be encrypted; the second is optional additional data
     /// that will not be encrypted but will be part of the GCM MAC calculation which also covers the data to be encrypted.
     ///
     /// # Description
     ///
     /// The seal_data function retrieves a key unique to the enclave and uses
-    /// that key to encrypt the input data buffer. This function can be utilized to preserve secret 
+    /// that key to encrypt the input data buffer. This function can be utilized to preserve secret
     /// data after the enclave is destroyed. The sealed data blob can be
     /// unsealed on future instantiations of the enclave.
     /// The additional data buffer will not be encrypted but will be part of the MAC
@@ -201,60 +154,67 @@
     /// Use `calc_raw_sealed_data_size` to calculate the number of bytes to
     /// allocate for the `SgxSealedData` structure. The input sealed data buffer and
     /// text2encrypt buffers must be allocated within the enclave.
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
+    ///
     /// # Parameters
     ///
     /// **additional_text**
     ///
-    /// Pointer to the additional Message Authentication Code (MAC) data. 
+    /// Pointer to the additional Message Authentication Code (MAC) data.
     /// This additional data is optional and no data is necessary.
     ///
     /// **encrypt_text**
     ///
     /// Pointer to the data stream to be encrypted, which is &T. Must be within the enclave.
     ///
-    /// # Return value 
+    /// # Return value
     ///
     /// The sealed data in SgxSealedData.
     ///
     /// # Errors
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
+    ///
     /// Indicates an error if the parameters do not meet any of the following conditions:
-    /// 
+    ///
     /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
     /// * encrypt_text must be non-zero.
     /// * encrypt_text buffer must be within the enclave.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// The enclave is out of memory.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
     ///
     /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
     /// random number.
-    /// 
-    pub fn seal_data(additional_text: &[u8], encrypt_text: &T) -> SgxResult<Self> {
+    ///
+    pub fn seal_data(additional_text: &[u8], encrypt_text: &'a T) -> SgxResult<Self> {
 
         let size = mem::size_of::<T>();
         if size == 0 {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
-        } 
-        let encrypt_slice: &[u8] = unsafe{slice::from_raw_parts(encrypt_text as * const _ as * const u8, size)};      
+        }
+        let encrypt_slice: &[u8] = unsafe {
+            slice::from_raw_parts(encrypt_text as * const _ as * const u8, mem::size_of_val(encrypt_text))
+        };
         let result = SgxInternalSealedData::seal_data(additional_text, encrypt_slice);
-        result.map(|x| SgxSealedData {inner: x, marker: ptr::null()})
+        result.map(|x| {
+            SgxSealedData {
+                inner: x,
+                marker: PhantomData,
+            }
+        })
     }
 
-    /// 
+    ///
     /// This function is used to AES-GCM encrypt the input data. Two input data sets
-    /// are provided: one is the data to be encrypted; the second is optional additional 
-    /// data that will not be encrypted but will be part of the GCM MAC calculation 
+    /// are provided: one is the data to be encrypted; the second is optional additional
+    /// data that will not be encrypted but will be part of the GCM MAC calculation
     /// which also covers the data to be encrypted. This is the expert mode
     /// version of function `seal_data`.
     ///
@@ -265,83 +225,90 @@
     /// policy and attributes_mask). Typical callers of the seal library should be
     /// able to use `seal_data` and the default values provided for key_
     /// policy (MR_SIGNER) and an attribute mask which includes the RESERVED,
-    /// INITED and DEBUG bits. Users of this function should have a clear understanding 
+    /// INITED and DEBUG bits. Users of this function should have a clear understanding
     /// of the impact on using a policy and/or attribute_mask that is different from that in seal_data.
-    /// 
-    /// # Requirements
-    /// 
-    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
-    /// # Parameters
-    /// 
-    /// **key_policy**
-    /// 
-    /// Specifies the policy to use in the key derivation. Function sgx_seal_data uses the MRSIGNER policy. 
     ///
-    /// Key policy name | Value | Description 
+    /// # Requirements
+    ///
+    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
+    ///
+    /// # Parameters
+    ///
+    /// **key_policy**
+    ///
+    /// Specifies the policy to use in the key derivation. Function sgx_seal_data uses the MRSIGNER policy.
+    ///
+    /// Key policy name | Value | Description
     /// ---|---|---
-    /// KEYPOLICY_MRENCLAVE | 0x0001 | -Derive key using the enclave??s ENCLAVE measurement register  
-    /// KEYPOLICY_MRSIGNER |0x0002 | -Derive key using the enclave??s SIGNER measurement register 
-    /// 
+    /// KEYPOLICY_MRENCLAVE | 0x0001 | -Derive key using the enclave??s ENCLAVE measurement register
+    /// KEYPOLICY_MRSIGNER |0x0002 | -Derive key using the enclave??s SIGNER measurement register
+    ///
     /// **attribute_mask**
-    /// 
-    /// Identifies which platform/enclave attributes to use in the key derivation. See  
-    /// the definition of sgx_attributes_t to determine which attributes will be  
-    /// checked.  Function sgx_seal_data uses flags=0xfffffffffffffff3,?xfrm=0. 
-    /// 
+    ///
+    /// Identifies which platform/enclave attributes to use in the key derivation. See
+    /// the definition of sgx_attributes_t to determine which attributes will be
+    /// checked.  Function sgx_seal_data uses flags=0xfffffffffffffff3,?xfrm=0.
+    ///
     /// **misc_mask**
     ///
     /// The misc mask bits for the enclave. Reserved for future function extension.
     ///
     /// **additional_text**
     ///
-    /// Pointer to the additional Message Authentication Code (MAC) data. 
+    /// Pointer to the additional Message Authentication Code (MAC) data.
     /// This additional data is optional and no data is necessary.
     ///
     /// **encrypt_text**
     ///
     /// Pointer to the data stream to be encrypted, which is &T. Must not be NULL. Must be within the enclave.
     ///
-    /// # Return value 
+    /// # Return value
     ///
     /// The sealed data in SgxSealedData.
     ///
     /// # Errors
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
+    ///
     /// Indicates an error if the parameters do not meet any of the following conditions:
-    /// 
+    ///
     /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
     /// * encrypt_text must be non-zero.
     /// * encrypt_text buffer must be within the enclave.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// The enclave is out of memory.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
     ///
     /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
     /// random number.
-    /// 
+    ///
     pub fn seal_data_ex(key_policy: u16,
                         attribute_mask: sgx_attributes_t,
                         misc_mask: sgx_misc_select_t,
-                        additional_text: &[u8], 
-                        encrypt_text: &T) -> SgxResult<Self> {
+                        additional_text: &[u8],
+                        encrypt_text: &'a T) -> SgxResult<Self> {
 
         let size = mem::size_of::<T>();
         if size == 0 {
             return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
-        } 
-        let encrypt_slice: &[u8] = unsafe{slice::from_raw_parts(encrypt_text as * const _ as * const u8, size)};
-        let result = SgxInternalSealedData::seal_data_ex(key_policy, 
-                                                         attribute_mask, 
-                                                         misc_mask, 
-                                                         additional_text, 
+        }
+        let encrypt_slice: &[u8] = unsafe {
+            slice::from_raw_parts(encrypt_text as * const _ as * const u8, mem::size_of_val(encrypt_text))
+        };
+        let result = SgxInternalSealedData::seal_data_ex(key_policy,
+                                                         attribute_mask,
+                                                         misc_mask,
+                                                         additional_text,
                                                          encrypt_slice);
-        result.map(|x| SgxSealedData {inner: x, marker: ptr::null()})
+        result.map(|x| {
+            SgxSealedData {
+                inner: x,
+                marker: PhantomData,
+            }
+        })
     }
 
     ///
@@ -350,49 +317,49 @@
     /// optional additional data that was part of the GCM MAC calculation but was not
     /// encrypted. This function provides the converse of seal_data and
     /// seal_data_ex.
-    /// 
+    ///
     /// # Descryption
-    /// 
+    ///
     /// The unseal_data function AES-GCM decrypts the sealed data so that
     /// the enclave data can be restored. This function can be utilized to restore
     /// secret data that was preserved after an earlier instantiation of this enclave
     /// saved this data.
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
     ///
-    /// # Return value 
+    /// # Return value
     ///
     /// The unsealed data in SgxUnsealedData.
     ///
     /// # Errors
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
+    ///
     /// The size of T may be zero.
-    /// 
+    ///
     /// **SGX_ERROR_INVALID_CPUSVN**
-    /// 
+    ///
     /// The CPUSVN in the sealed data blob is beyond the CPUSVN value of the platform.
     /// SGX_ERROR_INVALID_ISVSVN The ISVSVN in the sealed data blob is greater than the ISVSVN value of the enclave.
-    /// 
+    ///
     /// **SGX_ERROR_MAC_MISMATCH**
-    /// 
-    /// The tag verification failed during unsealing. The error may be caused by a platform update, 
-    /// software update, or sealed data blob corruption. This error is also reported if other corruption 
+    ///
+    /// The tag verification failed during unsealing. The error may be caused by a platform update,
+    /// software update, or sealed data blob corruption. This error is also reported if other corruption
     /// of the sealed data structure is detected.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// The enclave is out of memory.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
     ///
     /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
     /// random number.
-    /// 
-    pub fn unseal_data(&self) -> SgxResult<SgxUnsealedData<T>> {
+    ///
+    pub fn unseal_data(&self) -> SgxResult<SgxUnsealedData<'a, T>> {
 
         let size = mem::size_of::<T>();
         if size == 0 {
@@ -406,29 +373,20 @@
             let ptr = Box::into_raw(x.decrypt);
             SgxUnsealedData {
                 payload_size: x.payload_size,
-                decrypt: unsafe{Box::from_raw(ptr as * mut _ as * mut T)},
+                decrypt: unsafe{Box::from_raw(ptr as * mut T)},
                 additional: x.additional,
+                marker: PhantomData,
             }
         })
     }
-}
 
-/// The encrypt_text to seal is [T], and T must have Copy trait. 
-impl<T: Copy> SgxSealedData<[T]> {
     ///
-    /// Create a SgxSealedData with default values.
-    /// 
-    pub fn new() -> Self {
-        SgxSealedData::default()
-    }
-
-    /// 
     /// Convert a pointer of sgx_sealed_data_t buffer to SgxSealedData.
     ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
+    ///
     /// # Parameters
     ///
     /// **p**
@@ -439,323 +397,30 @@
     ///
     /// The size of the parameter `p`.
     ///
-    /// # Return value 
+    /// # Return value
     ///
     /// **Some(SgxSealedData)**
     ///
     /// Indicates the conversion is successfully. The return value is SgxSealedData.
     ///
     /// **None**
-    /// 
+    ///
     /// Maybe the size of T is zero.
-    /// 
+    ///
     pub unsafe fn from_raw_sealed_data_t(p: * mut sgx_sealed_data_t, len: u32) -> Option<Self> {
-        
+
         let size = mem::size_of::<T>();
         if size == 0 {
             return None;
-        } 
+        }
         let opt = SgxInternalSealedData::from_raw_sealed_data_t(p, len);
         opt.map(|x| {
-            let p = Box::<[T]>::default();
-            SgxSealedData{inner: x, marker: Box::into_raw(p)}
-        })
-    }
-
-    /// 
-    /// This function is used to AES-GCM encrypt the input data. Two input data sets
-    /// are provided: one is the data to be encrypted; the second is optional additional data 
-    /// that will not be encrypted but will be part of the GCM MAC calculation which also covers the data to be encrypted.
-    ///
-    /// # Descryption
-    ///
-    /// The seal_data function retrieves a key unique to the enclave and uses
-    /// that key to encrypt the input data buffer. This function can be utilized to preserve secret 
-    /// data after the enclave is destroyed. The sealed data blob can be
-    /// unsealed on future instantiations of the enclave.
-    /// The additional data buffer will not be encrypted but will be part of the MAC
-    /// calculation that covers the encrypted data as well. This data may include
-    /// information about the application, version, data, etc which can be utilized to
-    /// identify the sealed data blob since it will remain plain text
-    /// Use `calc_raw_sealed_data_size` to calculate the number of bytes to
-    /// allocate for the `SgxSealedData` structure. The input sealed data buffer and
-    /// text2encrypt buffers must be allocated within the enclave.
-    /// 
-    /// # Requirements
-    /// 
-    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
-    /// # Parameters
-    ///
-    /// **additional_text**
-    ///
-    /// Pointer to the additional Message Authentication Code (MAC) data. 
-    /// This additional data is optional and no data is necessary.
-    ///
-    /// **encrypt_text**
-    ///
-    /// Pointer to the data stream to be encrypted, which is &[T]. Must be within the enclave.
-    ///
-    /// # Return value 
-    ///
-    /// The sealed data in SgxSealedData.
-    ///
-    /// # Errors
-    /// 
-    /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
-    /// Indicates an error if the parameters do not meet any of the following conditions:
-    /// 
-    /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
-    /// * encrypt_text must be non-zero.
-    /// * encrypt_text buffer must be within the enclave.
-    /// 
-    /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
-    /// The enclave is out of memory.
-    /// 
-    /// **SGX_ERROR_UNEXPECTED**
-    ///
-    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
-    /// random number.
-    /// 
-    pub fn seal_data(additional_text: &[u8], encrypt_text: &[T]) -> SgxResult<Self> {
-
-        let size = mem::size_of::<T>() * encrypt_text.len();
-        if size == 0 {
-            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
-        }
-        let encrypt_slice: &[u8] = unsafe{slice::from_raw_parts(encrypt_text.as_ptr() as * const _ as * const u8, size)};      
-        let result = SgxInternalSealedData::seal_data(additional_text, encrypt_slice);
-        result.map(|x| {
-            let p = Box::<[T]>::default();
-            SgxSealedData {
+            SgxSealedData{
                 inner: x,
-                marker: Box::into_raw(p),
-            }
+                marker: PhantomData}
         })
     }
 
-    /// 
-    /// This function is used to AES-GCM encrypt the input data. Two input data sets
-    /// are provided: one is the data to be encrypted; the second is optional additional 
-    /// data that will not be encrypted but will be part of the GCM MAC calculation 
-    /// which also covers the data to be encrypted. This is the expert mode
-    /// version of function `seal_data`.
-    ///
-    /// # Descryption
-    ///
-    /// The `seal_data_ex` is an extended version of `seal_data`. It
-    /// provides parameters for you to identify how to derive the sealing key (key
-    /// policy and attributes_mask). Typical callers of the seal library should be
-    /// able to use `seal_data` and the default values provided for key_
-    /// policy (MR_SIGNER) and an attribute mask which includes the RESERVED,
-    /// INITED and DEBUG bits. Users of this function should have a clear understanding 
-    /// of the impact on using a policy and/or attribute_mask that is different from that in seal_data.
-    /// 
-    /// # Requirements
-    /// 
-    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///  
-    /// # Parameters
-    /// 
-    /// **key_policy**
-    /// 
-    /// Specifies the policy to use in the key derivation. Function sgx_seal_data uses the MRSIGNER policy. 
-    ///
-    /// Key policy name | Value | Description 
-    /// ---|---|---
-    /// KEYPOLICY_MRENCLAVE | 0x0001 | -Derive key using the enclave??s ENCLAVE measurement register  
-    /// KEYPOLICY_MRSIGNER |0x0002 | -Derive key using the enclave??s SIGNER measurement register 
-    /// 
-    /// **attribute_mask**
-    /// 
-    /// Identifies which platform/enclave attributes to use in the key derivation. See  
-    /// the definition of sgx_attributes_t to determine which attributes will be  
-    /// checked.  Function sgx_seal_data uses flags=0xfffffffffffffff3,?xfrm=0. 
-    /// 
-    /// **misc_mask**
-    ///
-    /// The misc mask bits for the enclave. Reserved for future function extension.
-    ///
-    /// **additional_text**
-    ///
-    /// Pointer to the additional Message Authentication Code (MAC) data. 
-    /// This additional data is optional and no data is necessary.
-    ///
-    /// **encrypt_text**
-    ///
-    /// Pointer to the data stream to be encrypted, which is &[T]. Must not be NULL. Must be within the enclave.
-    ///
-    /// # Return value 
-    ///
-    /// The sealed data in SgxSealedData.
-    ///
-    /// # Errors
-    /// 
-    /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
-    /// Indicates an error if the parameters do not meet any of the following conditions:
-    /// 
-    /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
-    /// * encrypt_text must be non-zero.
-    /// * encrypt_text buffer must be within the enclave.
-    /// 
-    /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
-    /// The enclave is out of memory.
-    /// 
-    /// **SGX_ERROR_UNEXPECTED**
-    ///
-    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
-    /// random number.
-    /// 
-    pub fn seal_data_ex(key_policy: u16,
-                        attribute_mask: sgx_attributes_t,
-                        misc_mask: sgx_misc_select_t,
-                        additional_text: &[u8], 
-                        encrypt_text: &[T]) -> SgxResult<Self> {
-
-        let size = mem::size_of::<T>() * encrypt_text.len();
-        if size == 0 {
-            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
-        }
-        let encrypt_slice: &[u8] = unsafe{slice::from_raw_parts(encrypt_text.as_ptr() as * const _ as * const u8, size)};
-        let result = SgxInternalSealedData::seal_data_ex(key_policy, 
-                                                         attribute_mask, 
-                                                         misc_mask, 
-                                                         additional_text, 
-                                                         encrypt_slice);
-        result.map(|x| {
-            let p = Box::<[T]>::default();
-            SgxSealedData {
-                inner: x,
-                marker: Box::into_raw(p),
-            }
-        })
-    }
-
-    ///
-    /// This function is used to AES-GCM decrypt the input sealed data structure.
-    /// Two output data sets result: one is the decrypted data; the second is the
-    /// optional additional data that was part of the GCM MAC calculation but was not
-    /// encrypted. This function provides the converse of seal_data and
-    /// seal_data_ex.
-    /// 
-    /// # Descryption
-    /// 
-    /// The unseal_data function AES-GCM decrypts the sealed data so that
-    /// the enclave data can be restored. This function can be utilized to restore
-    /// secret data that was preserved after an earlier instantiation of this enclave
-    /// saved this data.
-    /// 
-    /// # Requirements
-    /// 
-    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
-    ///
-    /// # Return value 
-    ///
-    /// The unsealed data in SgxUnsealedData.
-    ///
-    /// # Errors
-    /// 
-    /// **SGX_ERROR_INVALID_PARAMETER**
-    /// 
-    /// The size of T may be zero.
-    /// 
-    /// **SGX_ERROR_INVALID_CPUSVN**
-    /// 
-    /// The CPUSVN in the sealed data blob is beyond the CPUSVN value of the platform.
-    /// SGX_ERROR_INVALID_ISVSVN The ISVSVN in the sealed data blob is greater than the ISVSVN value of the enclave.
-    /// 
-    /// **SGX_ERROR_MAC_MISMATCH**
-    /// 
-    /// The tag verification failed during unsealing. The error may be caused by a platform update, 
-    /// software update, or sealed data blob corruption. This error is also reported if other corruption 
-    /// of the sealed data structure is detected.
-    /// 
-    /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
-    /// The enclave is out of memory.
-    /// 
-    /// **SGX_ERROR_UNEXPECTED**
-    ///
-    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
-    /// random number.
-    /// 
-    pub fn unseal_data(&self) -> SgxResult<SgxUnsealedData<[T]>> {
-
-        let size = mem::size_of::<T>();
-        if size == 0 {
-            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
-        }
-        let encrypt_len = self.get_encrypt_txt_len() as usize;
-        if size > encrypt_len {
-            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
-        }
-        if (encrypt_len % size) != 0 {
-            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
-        }
-        self.inner.unseal_data().map(|x| {
-            let ptr = Box::into_raw(x.decrypt);
-            SgxUnsealedData {
-                payload_size: x.payload_size,
-                decrypt: unsafe{Box::from_raw(ptr as * mut _ as * mut [T])},
-                additional: x.additional,
-            }
-        })
-    }
-}
-
-impl<T: ?Sized> SgxSealedData<T> {
-    ///
-    /// Get the size of payload in SgxSealedData.
-    ///
-    pub fn get_payload_size(&self) -> u32 {
-        self.inner.get_payload_size()
-    }
-    ///
-    /// Get a slice of payload in SgxSealedData.
-    ///
-    pub fn get_payload_tag(&self) -> &[u8; SGX_SEAL_TAG_SIZE] {
-        self.inner.get_payload_tag()
-    }
-    ///
-    /// Get the pointer of sgx_key_request_t in SgxSealedData.
-    ///
-    pub fn get_key_request(&self) -> &sgx_key_request_t {
-        self.inner.get_key_request()
-    }
-    ///
-    /// Get a slice of encrypt text in SgxSealedData.
-    ///
-    pub fn get_encrypt_txt(&self) -> &[u8] {
-        self.inner.get_encrypt_txt()
-    }
-    ///
-    /// Get a slice of additional text in SgxSealedData.
-    ///
-    pub fn get_additional_txt(&self) -> &[u8] {
-        self.inner.get_additional_txt()
-    }
-    ///
-    /// Calculate the size of the sealed data in SgxSealedData.
-    ///
-    pub fn calc_raw_sealed_data_size(add_mac_txt_size: u32, encrypt_txt_size: u32) -> u32  {
-        SgxInternalSealedData::calc_raw_sealed_data_size(add_mac_txt_size, encrypt_txt_size)
-    }
-    ///
-    /// Get the size of the additional mactext in SgxSealedData.
-    ///
-    pub fn get_add_mac_txt_len(&self) -> u32 {
-        self.inner.get_add_mac_txt_len()
-    } 
-    ///
-    /// Get the size of the encrypt text in SgxSealedData.
-    ///
-    pub fn get_encrypt_txt_len(&self) -> u32 {
-        self.inner.get_encrypt_txt_len()
-    }
     ///
     /// Convert SgxSealedData to the pointer of sgx_sealed_data_t.
     ///
@@ -782,4 +447,395 @@
     pub unsafe fn to_raw_sealed_data_t(&self, p: * mut sgx_sealed_data_t, len: u32) -> Option<* mut sgx_sealed_data_t> {
         self.inner.to_raw_sealed_data_t(p, len)
     }
-}
\ No newline at end of file
+}
+
+/// The encrypt_text to seal is [T], and T must have Copy and ContiguousMemory trait.
+impl<'a, T: 'a + Copy + ContiguousMemory> SgxSealedData<'a, [T]> {
+
+    ///
+    /// This function is used to AES-GCM encrypt the input data. Two input data sets
+    /// are provided: one is the data to be encrypted; the second is optional additional data
+    /// that will not be encrypted but will be part of the GCM MAC calculation which also covers the data to be encrypted.
+    ///
+    /// # Descryption
+    ///
+    /// The seal_data function retrieves a key unique to the enclave and uses
+    /// that key to encrypt the input data buffer. This function can be utilized to preserve secret
+    /// data after the enclave is destroyed. The sealed data blob can be
+    /// unsealed on future instantiations of the enclave.
+    /// The additional data buffer will not be encrypted but will be part of the MAC
+    /// calculation that covers the encrypted data as well. This data may include
+    /// information about the application, version, data, etc which can be utilized to
+    /// identify the sealed data blob since it will remain plain text
+    /// Use `calc_raw_sealed_data_size` to calculate the number of bytes to
+    /// allocate for the `SgxSealedData` structure. The input sealed data buffer and
+    /// text2encrypt buffers must be allocated within the enclave.
+    ///
+    /// # Requirements
+    ///
+    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
+    ///
+    /// # Parameters
+    ///
+    /// **additional_text**
+    ///
+    /// Pointer to the additional Message Authentication Code (MAC) data.
+    /// This additional data is optional and no data is necessary.
+    ///
+    /// **encrypt_text**
+    ///
+    /// Pointer to the data stream to be encrypted, which is &[T]. Must be within the enclave.
+    ///
+    /// # Return value
+    ///
+    /// The sealed data in SgxSealedData.
+    ///
+    /// # Errors
+    ///
+    /// **SGX_ERROR_INVALID_PARAMETER**
+    ///
+    /// Indicates an error if the parameters do not meet any of the following conditions:
+    ///
+    /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
+    /// * encrypt_text must be non-zero.
+    /// * encrypt_text buffer must be within the enclave.
+    ///
+    /// **SGX_ERROR_OUT_OF_MEMORY**
+    ///
+    /// The enclave is out of memory.
+    ///
+    /// **SGX_ERROR_UNEXPECTED**
+    ///
+    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
+    /// random number.
+    ///
+    pub fn seal_data(additional_text: &[u8], encrypt_text: &'a [T]) -> SgxResult<Self> {
+
+        let size = mem::size_of::<T>();
+        let len = mem::size_of_val(encrypt_text);
+        if size == 0 || len == 0 {
+            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
+        }
+        let encrypt_slice: &[u8] = unsafe {
+            slice::from_raw_parts(encrypt_text.as_ptr() as * const u8, len)
+        };
+
+        let result = SgxInternalSealedData::seal_data(additional_text, encrypt_slice);
+        result.map(|x| {
+            SgxSealedData {
+                inner: x,
+                marker: PhantomData,
+            }
+        })
+    }
+
+    ///
+    /// This function is used to AES-GCM encrypt the input data. Two input data sets
+    /// are provided: one is the data to be encrypted; the second is optional additional
+    /// data that will not be encrypted but will be part of the GCM MAC calculation
+    /// which also covers the data to be encrypted. This is the expert mode
+    /// version of function `seal_data`.
+    ///
+    /// # Descryption
+    ///
+    /// The `seal_data_ex` is an extended version of `seal_data`. It
+    /// provides parameters for you to identify how to derive the sealing key (key
+    /// policy and attributes_mask). Typical callers of the seal library should be
+    /// able to use `seal_data` and the default values provided for key_
+    /// policy (MR_SIGNER) and an attribute mask which includes the RESERVED,
+    /// INITED and DEBUG bits. Users of this function should have a clear understanding
+    /// of the impact on using a policy and/or attribute_mask that is different from that in seal_data.
+    ///
+    /// # Requirements
+    ///
+    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
+    ///
+    /// # Parameters
+    ///
+    /// **key_policy**
+    ///
+    /// Specifies the policy to use in the key derivation. Function sgx_seal_data uses the MRSIGNER policy.
+    ///
+    /// Key policy name | Value | Description
+    /// ---|---|---
+    /// KEYPOLICY_MRENCLAVE | 0x0001 | -Derive key using the enclave??s ENCLAVE measurement register
+    /// KEYPOLICY_MRSIGNER |0x0002 | -Derive key using the enclave??s SIGNER measurement register
+    ///
+    /// **attribute_mask**
+    ///
+    /// Identifies which platform/enclave attributes to use in the key derivation. See
+    /// the definition of sgx_attributes_t to determine which attributes will be
+    /// checked.  Function sgx_seal_data uses flags=0xfffffffffffffff3,?xfrm=0.
+    ///
+    /// **misc_mask**
+    ///
+    /// The misc mask bits for the enclave. Reserved for future function extension.
+    ///
+    /// **additional_text**
+    ///
+    /// Pointer to the additional Message Authentication Code (MAC) data.
+    /// This additional data is optional and no data is necessary.
+    ///
+    /// **encrypt_text**
+    ///
+    /// Pointer to the data stream to be encrypted, which is &[T]. Must not be NULL. Must be within the enclave.
+    ///
+    /// # Return value
+    ///
+    /// The sealed data in SgxSealedData.
+    ///
+    /// # Errors
+    ///
+    /// **SGX_ERROR_INVALID_PARAMETER**
+    ///
+    /// Indicates an error if the parameters do not meet any of the following conditions:
+    ///
+    /// * additional_text buffer can be within or outside the enclave, but cannot cross the enclave boundary.
+    /// * encrypt_text must be non-zero.
+    /// * encrypt_text buffer must be within the enclave.
+    ///
+    /// **SGX_ERROR_OUT_OF_MEMORY**
+    ///
+    /// The enclave is out of memory.
+    ///
+    /// **SGX_ERROR_UNEXPECTED**
+    ///
+    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
+    /// random number.
+    ///
+    pub fn seal_data_ex(key_policy: u16,
+                        attribute_mask: sgx_attributes_t,
+                        misc_mask: sgx_misc_select_t,
+                        additional_text: &[u8],
+                        encrypt_text: &'a [T]) -> SgxResult<Self> {
+
+        let size = mem::size_of::<T>();
+        let len = mem::size_of_val(encrypt_text);
+        if size == 0 || len == 0 {
+            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
+        }
+        let encrypt_slice: &[u8] = unsafe {
+            slice::from_raw_parts(encrypt_text.as_ptr() as * const u8, len)
+        };
+
+        let result = SgxInternalSealedData::seal_data_ex(key_policy,
+                                                         attribute_mask,
+                                                         misc_mask,
+                                                         additional_text,
+                                                         encrypt_slice);
+        result.map(|x| {
+            SgxSealedData {
+                inner: x,
+                marker: PhantomData,
+            }
+        })
+    }
+
+    ///
+    /// This function is used to AES-GCM decrypt the input sealed data structure.
+    /// Two output data sets result: one is the decrypted data; the second is the
+    /// optional additional data that was part of the GCM MAC calculation but was not
+    /// encrypted. This function provides the converse of seal_data and
+    /// seal_data_ex.
+    ///
+    /// # Descryption
+    ///
+    /// The unseal_data function AES-GCM decrypts the sealed data so that
+    /// the enclave data can be restored. This function can be utilized to restore
+    /// secret data that was preserved after an earlier instantiation of this enclave
+    /// saved this data.
+    ///
+    /// # Requirements
+    ///
+    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
+    ///
+    /// # Return value
+    ///
+    /// The unsealed data in SgxUnsealedData.
+    ///
+    /// # Errors
+    ///
+    /// **SGX_ERROR_INVALID_PARAMETER**
+    ///
+    /// The size of T may be zero.
+    ///
+    /// **SGX_ERROR_INVALID_CPUSVN**
+    ///
+    /// The CPUSVN in the sealed data blob is beyond the CPUSVN value of the platform.
+    /// SGX_ERROR_INVALID_ISVSVN The ISVSVN in the sealed data blob is greater than the ISVSVN value of the enclave.
+    ///
+    /// **SGX_ERROR_MAC_MISMATCH**
+    ///
+    /// The tag verification failed during unsealing. The error may be caused by a platform update,
+    /// software update, or sealed data blob corruption. This error is also reported if other corruption
+    /// of the sealed data structure is detected.
+    ///
+    /// **SGX_ERROR_OUT_OF_MEMORY**
+    ///
+    /// The enclave is out of memory.
+    ///
+    /// **SGX_ERROR_UNEXPECTED**
+    ///
+    /// Indicates a crypto library failure or the RDRAND instruction fails to generate a
+    /// random number.
+    ///
+    pub fn unseal_data(&self) -> SgxResult<SgxUnsealedData<'a, [T]>> {
+
+        let size = mem::size_of::<T>();
+        if size == 0 {
+            return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
+        }
+        let encrypt_len = self.get_encrypt_txt_len() as usize;
+        if size > encrypt_len {
+            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
+        }
+        if (encrypt_len % size) != 0 {
+            return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
+        }
+
+        self.inner.unseal_data().map(|x| {
+            let ptr = (x.decrypt).as_ptr() as * mut T;
+            let mut slice = unsafe{slice::from_raw_parts_mut(ptr, encrypt_len/size)};
+            SgxUnsealedData {
+                payload_size: x.payload_size,
+                decrypt: unsafe{Box::from_raw(slice as * mut [T])},
+                additional: x.additional,
+                marker: PhantomData,
+            }
+        })
+    }
+
+    ///
+    /// Convert a pointer of sgx_sealed_data_t buffer to SgxSealedData.
+    ///
+    /// # Requirements
+    ///
+    /// Library: libsgx_tservice.a or libsgx_tservice_sim.a (simulation)
+    ///
+    /// # Parameters
+    ///
+    /// **p**
+    ///
+    /// The mutable pointer of sgx_sealed_data_t buffer.
+    ///
+    /// **len**
+    ///
+    /// The size of the parameter `p`.
+    ///
+    /// # Return value
+    ///
+    /// **Some(SgxSealedData)**
+    ///
+    /// Indicates the conversion is successfully. The return value is SgxSealedData.
+    ///
+    /// **None**
+    ///
+    /// Maybe the size of T is zero.
+    ///
+    pub unsafe fn from_raw_sealed_data_t(p: * mut sgx_sealed_data_t, len: u32) -> Option<Self> {
+
+        let size = mem::size_of::<T>();
+        if size == 0 {
+            return None;
+        }
+        let opt = SgxInternalSealedData::from_raw_sealed_data_t(p, len);
+        opt.map(|x| {
+            SgxSealedData{
+                inner: x,
+                marker: PhantomData}
+        })
+    }
+
+    ///
+    /// Convert SgxSealedData to the pointer of sgx_sealed_data_t.
+    ///
+    /// # Parameters
+    ///
+    /// **p**
+    ///
+    /// The pointer of sgx_sealed_data_t to save the data in SgxSealedData.
+    ///
+    /// **len**
+    ///
+    /// The size of the pointer of sgx_sealed_data_t.
+    ///
+    /// # Error
+    ///
+    /// **Some(* mut sgx_sealed_data_t)**
+    ///
+    /// Indicates the conversion is successfully. The return value is the pointer of sgx_sealed_data_t.
+    ///
+    /// **None**
+    ///
+    /// May be the parameter p and len is not avaliable.
+    ///
+    pub unsafe fn to_raw_sealed_data_t(&self, p: * mut sgx_sealed_data_t, len: u32) -> Option<* mut sgx_sealed_data_t> {
+        self.inner.to_raw_sealed_data_t(p, len)
+    }
+}
+
+impl<'a, T: 'a + ?Sized> SgxSealedData<'a, T> {
+
+    ///
+    /// Create a SgxSealedData with default values.
+    ///
+    pub fn new() -> Self {
+        SgxSealedData::default()
+    }
+
+    ///
+    /// Get the size of payload in SgxSealedData.
+    ///
+    pub fn get_payload_size(&self) -> u32 {
+        self.inner.get_payload_size()
+    }
+
+    ///
+    /// Get a slice of payload in SgxSealedData.
+    ///
+    pub fn get_payload_tag(&self) -> &[u8; SGX_SEAL_TAG_SIZE] {
+        self.inner.get_payload_tag()
+    }
+
+    ///
+    /// Get the pointer of sgx_key_request_t in SgxSealedData.
+    ///
+    pub fn get_key_request(&self) -> &sgx_key_request_t {
+        self.inner.get_key_request()
+    }
+
+    ///
+    /// Get a slice of encrypt text in SgxSealedData.
+    ///
+    pub fn get_encrypt_txt(&self) -> &[u8] {
+        self.inner.get_encrypt_txt()
+    }
+
+    ///
+    /// Get a slice of additional text in SgxSealedData.
+    ///
+    pub fn get_additional_txt(&self) -> &[u8] {
+        self.inner.get_additional_txt()
+    }
+
+    ///
+    /// Calculate the size of the sealed data in SgxSealedData.
+    ///
+    pub fn calc_raw_sealed_data_size(add_mac_txt_size: u32, encrypt_txt_size: u32) -> u32  {
+        SgxInternalSealedData::calc_raw_sealed_data_size(add_mac_txt_size, encrypt_txt_size)
+    }
+
+    ///
+    /// Get the size of the additional mactext in SgxSealedData.
+    ///
+    pub fn get_add_mac_txt_len(&self) -> u32 {
+        self.inner.get_add_mac_txt_len()
+    }
+
+    ///
+    /// Get the size of the encrypt text in SgxSealedData.
+    ///
+    pub fn get_encrypt_txt_len(&self) -> u32 {
+        self.inner.get_encrypt_txt_len()
+    }
+}
diff --git a/sgx_tservice/Cargo.toml b/sgx_tservice/Cargo.toml
index c5fe694..179702a 100644
--- a/sgx_tservice/Cargo.toml
+++ b/sgx_tservice/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tservice"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Baidu"]
 
 [features]
diff --git a/sgx_tservice/src/lib.rs b/sgx_tservice/src/lib.rs
index 983fbfc..bc803a5 100644
--- a/sgx_tservice/src/lib.rs
+++ b/sgx_tservice/src/lib.rs
@@ -28,8 +28,8 @@
 
 //! # Trust Service Library
 //!
-//! The Intel(R) Software Guard Extensions SDK provides a trusted library named 
-//! sgx_tservice for secure data manipulation and protection. The sgx_tservice library 
+//! The Intel(R) Software Guard Extensions SDK provides a trusted library named
+//! sgx_tservice for secure data manipulation and protection. The sgx_tservice library
 //! provides the following modules:
 //!
 //! **Trust Platform Service Functions**
@@ -46,6 +46,6 @@
 
 extern crate sgx_types;
 
-pub mod tae;
+mod tae;
 pub use self::tae::*;
 
diff --git a/sgx_tservice/src/tae.rs b/sgx_tservice/src/tae.rs
index 7f8bc45..b1d738b 100644
--- a/sgx_tservice/src/tae.rs
+++ b/sgx_tservice/src/tae.rs
@@ -28,31 +28,27 @@
 
 //! Trust Platform Service Functions
 //!
-//! The sgx_tservice library provides the following functions that allow an ISV 
+//! The sgx_tservice library provides the following functions that allow an ISV
 //! to use platform services and get platform services security property.
 //!
-//! This API is only available in simulation mode.
-//!
 use sgx_types::*;
 use core::cell::Cell;
 
 ///
-/// rsgx_create_pse_session creates a session with the PSE. 
-///
-/// This API is only available in simulation mode.
+/// rsgx_create_pse_session creates a session with the PSE.
 ///
 /// # Description
 ///
 /// An Intel(R) SGX enclave first calls rsgx_create_pse_session() in the process to request platform service.
 ///
-/// It's suggested that the caller should wait (typically several seconds to tens of seconds) and retry 
+/// It's suggested that the caller should wait (typically several seconds to tens of seconds) and retry
 /// this API if SGX_ERROR_BUSY is returned.
 ///
 /// # Requirements
 ///
 /// Header: sgx_tae_service.edl
 ///
-/// Library: libsgx_tservice_sim.a (simulation)
+/// Library: libsgx_tservice.a
 ///
 /// # Errors
 ///
@@ -100,8 +96,6 @@
 ///
 /// rsgx_close_pse_session closes a session created by rsgx_create_pse_ session.
 ///
-/// This API is only available in simulation mode.
-///
 /// # Description
 ///
 /// An Intel(R) SGX enclave calls rsgx_close_pse_session() when there is no need to request platform service.
@@ -110,7 +104,7 @@
 ///
 /// Header: sgx_tae_service.edl
 ///
-/// Library: libsgx_tservice_sim.a (simulation)
+/// Library: libsgx_tservice.a
 ///
 /// # Errors
 ///
@@ -138,26 +132,24 @@
 ///
 /// rsgx_get_ps_sec_prop gets a data structure describing the security property of the platform service.
 ///
-/// This API is only available in simulation mode.
-///
 /// # Description
 ///
 /// Gets a data structure that describes the security property of the platform service.
 ///
-/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave 
+/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
 /// before calling this API.
 ///
 /// # Parameters
 ///
 /// **security_property**
 ///
-/// A pointer to the buffer that receives the security property descriptor of the platform service. 
+/// A pointer to the buffer that receives the security property descriptor of the platform service.
 ///
 /// # Requirements
 ///
 /// Header: sgx_tae_service.edl
 ///
-/// Library: libsgx_tservice_sim.a (simulation)
+/// Library: libsgx_tservice.a
 ///
 /// # Errors
 ///
@@ -179,26 +171,65 @@
 }
 
 ///
-/// rsgx_get_trusted_time gets trusted time from the AE service.
-///
-/// This API is only available in simulation mode.
+/// rsgx_get_ps_sec_prop_ex gets a data structure describing the security property of the platform service.
 ///
 /// # Description
 ///
-/// current_time contains time in seconds and time_source_nonce contains nonce associate with the time. 
-/// The caller should compare time_ source_nonce against the value returned from the previous call of 
-/// this API if it needs to calculate the time passed between two readings of the Trusted Timer. If the 
-/// time_source_nonce of the two readings do not match, the difference between the two readings does not 
+/// Gets a data structure that describes the security property of the platform service.
+///
+/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
+/// before calling this API.
+///
+/// # Parameters
+///
+/// **security_property**
+///
+/// A pointer to the buffer that receives the security property descriptor of the platform service.
+///
+/// # Requirements
+///
+/// Header: sgx_tae_service.edl
+///
+/// Library: libsgx_tservice.a
+///
+/// # Errors
+///
+/// **SGX_ERROR_INVALID_PARAMETER**
+///
+/// Any of the pointers is invalid.
+///
+/// **SGX_ERROR_AE_SESSION_INVALID**
+///
+/// Session is not created or has been closed by architectural enclave service.
+///
+pub fn rsgx_get_ps_sec_prop_ex(security_property: &mut sgx_ps_sec_prop_desc_ex_t) -> SgxError {
+
+    let ret = unsafe { sgx_get_ps_sec_prop_ex(security_property as * mut sgx_ps_sec_prop_desc_ex_t) };
+    match ret {
+        sgx_status_t::SGX_SUCCESS => Ok(()),
+        _ => Err(ret),
+    }
+}
+
+///
+/// rsgx_get_trusted_time gets trusted time from the AE service.
+///
+/// # Description
+///
+/// current_time contains time in seconds and time_source_nonce contains nonce associate with the time.
+/// The caller should compare time_ source_nonce against the value returned from the previous call of
+/// this API if it needs to calculate the time passed between two readings of the Trusted Timer. If the
+/// time_source_nonce of the two readings do not match, the difference between the two readings does not
 /// necessarily reflect time passed.
 ///
-/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave 
+/// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
 /// before calling this API.
 ///
 /// # Parameters
 ///
 /// **current_time**
 ///
-/// Trusted Time Stamp in seconds relative to a reference point. The reference point does not change as long as 
+/// Trusted Time Stamp in seconds relative to a reference point. The reference point does not change as long as
 /// the time_source_nonce has not changed.
 ///
 /// **time_source_nonce**
@@ -209,7 +240,7 @@
 ///
 /// Header: sgx_tae_service.edl
 ///
-/// Library: libsgx_tservice_sim.a (simulation)
+/// Library: libsgx_tservice.a
 ///
 /// # Errors
 ///
@@ -245,7 +276,7 @@
 ///
 /// Indicates an unexpected error occurs.
 ///
-pub fn rsgx_get_trusted_time(current_time: &mut sgx_time_t, 
+pub fn rsgx_get_trusted_time(current_time: &mut sgx_time_t,
                              time_source_nonce: &mut sgx_time_source_nonce_t) -> SgxError {
 
     let ret = unsafe { sgx_get_trusted_time(current_time as * mut sgx_time_t, time_source_nonce as * mut sgx_time_source_nonce_t) };
@@ -263,7 +294,7 @@
     unsafe {
         sgx_create_monotonic_counter_ex(owner_policy,
                                         owner_attribute_mask as * const sgx_attributes_t,
-                                        counter_uuid as * mut sgx_mc_uuid_t,                                                  
+                                        counter_uuid as * mut sgx_mc_uuid_t,
                                         counter_value as * mut u32)
     }
 }
@@ -290,7 +321,7 @@
 }
 
 fn rsgx_read_monotonic_counter(counter_uuid: &sgx_mc_uuid_t, counter_value: &mut u32) -> sgx_status_t {
-    
+
     unsafe {
         sgx_read_monotonic_counter(counter_uuid as * const sgx_mc_uuid_t, counter_value as * mut u32)
     }
@@ -307,25 +338,23 @@
     ///
     /// creates a monotonic counter with default owner policy and default user attribute mask.
     ///
-    /// This API is only available in simulation mode.
-    ///
     /// # Description
     ///
-    /// Call new to create a monotonic counter with the default owner policy 0x1, which means enclaves 
+    /// Call new to create a monotonic counter with the default owner policy 0x1, which means enclaves
     /// with same signing key can access the monotonic counter and default owner_attribute_mask 0xFFFFFFFFFFFFFFCB.
     ///
-    /// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave 
+    /// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
     /// before calling this API.
     ///
-    /// Creating a monotonic counter (MC) involves writing to the non-volatile memory available in the platform. 
-    /// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform. 
-    /// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed 
+    /// Creating a monotonic counter (MC) involves writing to the non-volatile memory available in the platform.
+    /// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform.
+    /// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed
     /// the limit, the MC operation may return SGX_ERROR_BUSY for several minutes.
     ///
-    /// Intel(R) SGX limits the number of MCs an enclave can create. To avoid exhausting the available quota, 
-    /// an SGX application should record the MC UUID that rsgx_create_monotonic_counter returns and destroy a MC 
-    /// when it is not needed any more. If an enclave reaches its quota and previously created MC UUIDs have not 
-    /// been recorded, you may restore the MC service after uninstalling the SGX PSW and installing it again. 
+    /// Intel(R) SGX limits the number of MCs an enclave can create. To avoid exhausting the available quota,
+    /// an SGX application should record the MC UUID that rsgx_create_monotonic_counter returns and destroy a MC
+    /// when it is not needed any more. If an enclave reaches its quota and previously created MC UUIDs have not
+    /// been recorded, you may restore the MC service after uninstalling the SGX PSW and installing it again.
     /// This procedure deletes all MCs created by any enclave in that system.
     ///
     /// # Parameters
@@ -338,7 +367,7 @@
     ///
     /// Header: sgx_tae_service.edl
     ///
-    /// Library: libsgx_tservice_sim.a (simulation)
+    /// Library: libsgx_tservice.a
     ///
     /// # Return value
     ///
@@ -391,7 +420,7 @@
     /// Indicates an unexpected error occurs.
     ///
     pub fn new(counter_value: &mut u32) -> SgxResult<Self> {
-         
+
         let mut counter_uuid = sgx_mc_uuid_t::default();
         let ret = rsgx_create_monotonic_counter(&mut counter_uuid, counter_value);
 
@@ -404,24 +433,22 @@
     ///
     /// creates a monotonic counter.
     ///
-    /// This API is only available in simulation mode.
-    ///
     /// # Description
     ///
     /// Call new_ex to create a monotonic counter with the given owner_policy and owner_attribute_mask.
     ///
-    /// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave 
+    /// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
     /// before calling this API.
     ///
-    /// Creating a monotonic counter (MC) involves writing to the non-volatile memory available in the platform. 
-    /// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform. 
-    /// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed 
+    /// Creating a monotonic counter (MC) involves writing to the non-volatile memory available in the platform.
+    /// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform.
+    /// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed
     /// the limit, the MC operation may return SGX_ERROR_BUSY for several minutes.
     ///
-    /// Intel(R) SGX limits the number of MCs an enclave can create. To avoid exhausting the available quota, 
-    /// an SGX application should record the MC UUID that rsgx_create_monotonic_counter_ex returns and destroy a MC 
-    /// when it is not needed any more. If an enclave reaches its quota and previously created MC UUIDs have not 
-    /// been recorded, you may restore the MC service after uninstalling the SGX PSW and installing it again. 
+    /// Intel(R) SGX limits the number of MCs an enclave can create. To avoid exhausting the available quota,
+    /// an SGX application should record the MC UUID that rsgx_create_monotonic_counter_ex returns and destroy a MC
+    /// when it is not needed any more. If an enclave reaches its quota and previously created MC UUIDs have not
+    /// been recorded, you may restore the MC service after uninstalling the SGX PSW and installing it again.
     /// This procedure deletes all MCs created by any enclave in that system.
     ///
     /// # Parameters
@@ -442,12 +469,12 @@
     /// **counter_value**
     ///
     /// A pointer to the buffer that receives the monotonic counter value.
-    /// 
+    ///
     /// # Requirements
     ///
     /// Header: sgx_tae_service.edl
     ///
-    /// Library: libsgx_tservice_sim.a (simulation)
+    /// Library: libsgx_tservice.a
     ///
     /// # Return value
     ///
@@ -512,29 +539,27 @@
 
     ///
     /// destroys a monotonic counter created by new or new_ex.
-    /// 
-    /// This API is only available in simulation mode.
     ///
     /// # Description
     ///
     /// Calling destory after a monotonic counter is not needed anymore.
     ///
-    /// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave 
+    /// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
     /// before calling this API.
     ///
     /// destory fails if the calling enclave does not match the owner policy and the attributes specified in the
     /// call that created the monotonic counter.
     ///
-    /// Destroying a Monotonic Counter (MC) involves writing to the non-volatile memory available in the platform. 
-    /// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform. 
-    /// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed the 
+    /// Destroying a Monotonic Counter (MC) involves writing to the non-volatile memory available in the platform.
+    /// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform.
+    /// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed the
     /// limit, the MC operation may return SGX_ERROR_BUSY for several minutes.
     ///
     /// # Requirements
     ///
     /// Header: sgx_tae_service.edl
     ///
-    /// Library: libsgx_tservice_sim.a (simulation)
+    /// Library: libsgx_tservice.a
     ///
     /// # Errors
     ///
@@ -555,7 +580,7 @@
     /// The enclave doesn't have the access right to specified Monotonic Counter.
     ///
     /// **SGX_ERROR_AE_SESSION_INVALID**
-    /// 
+    ///
     /// Session is not created or has been closed by architectural enclave service.
     ///
     /// **SGX_ERROR_SERVICE_UNAVAILABLE**
@@ -565,21 +590,21 @@
     /// **SGX_ERROR_SERVICE_TIMEOUT**
     ///
     /// A request to the AE service timed out.
-    /// 
+    ///
     /// **SGX_ERROR_NETWORK_FAILURE**
-    /// 
+    ///
     /// Network connecting or proxy setting issue was encountered.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// Not enough memory is available to complete this operation.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_EPC**
-    /// 
+    ///
     /// There is not enough EPC memory to load one of the Architecture Enclaves needed to complete this operation.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
-    /// 
+    ///
     /// Indicates an unexpected error occurs.
     ///
     pub fn destory(&self) -> SgxError {
@@ -599,29 +624,27 @@
 
     ///
     /// increments a monotonic counter value by 1.
-    /// 
-    /// This API is only available in simulation mode.
     ///
     /// # Description
     ///
     /// Call increment to increase a monotonic counter value by 1.
     ///
-    /// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave 
+    /// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
     /// before calling this API.
     ///
-    /// increment fails if the calling enclave does not match the owner policy and the attributes specified in the 
+    /// increment fails if the calling enclave does not match the owner policy and the attributes specified in the
     /// call that created the monotonic counter.
     ///
-    /// Incrementing a monotonic counter (MC) involves writing to the non-volatile memory available in the platform. 
-    /// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform. 
-    /// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed the limit, 
+    /// Incrementing a monotonic counter (MC) involves writing to the non-volatile memory available in the platform.
+    /// Repeated write operations could cause the memory to wear out during the normal lifecycle of the platform.
+    /// Intel(R) SGX prevents this by limiting the rate at which MC operations can be performed. If you exceed the limit,
     /// the MC operation may return SGX_ERROR_BUSY for several minutes.
     ///
     /// # Requirements
     ///
     /// Header: sgx_tae_service.edl
     ///
-    /// Library: libsgx_tservice_sim.a (simulation)
+    /// Library: libsgx_tservice.a
     ///
     /// # Errors
     ///
@@ -642,7 +665,7 @@
     /// The enclave doesn't have the access right to specified Monotonic Counter.
     ///
     /// **SGX_ERROR_AE_SESSION_INVALID**
-    /// 
+    ///
     /// Session is not created or has been closed by architectural enclave service.
     ///
     /// **SGX_ERROR_SERVICE_UNAVAILABLE**
@@ -652,21 +675,21 @@
     /// **SGX_ERROR_SERVICE_TIMEOUT**
     ///
     /// A request to the AE service timed out.
-    /// 
+    ///
     /// **SGX_ERROR_NETWORK_FAILURE**
-    /// 
+    ///
     /// Network connecting or proxy setting issue was encountered.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// Not enough memory is available to complete this operation.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_EPC**
-    /// 
+    ///
     /// There is not enough EPC memory to load one of the Architecture Enclaves needed to complete this operation.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
-    /// 
+    ///
     /// Indicates an unexpected error occurs.
     ///
     pub fn increment(&self) -> SgxResult<u32> {
@@ -685,24 +708,22 @@
 
     ///
     /// returns the value of a monotonic counter.
-    /// 
-    /// This API is only available in simulation mode.
     ///
     /// # Description
     ///
     /// Call read to read the value of a monotonic counter.
     ///
-    /// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave 
+    /// The caller should call rsgx_create_pse_session to establish a session with the platform service enclave
     /// before calling this API.
     ///
-    /// read fails if the calling enclave does not match the owner policy and the attributes specified in the 
+    /// read fails if the calling enclave does not match the owner policy and the attributes specified in the
     /// call that created the monotonic counter.
     ///
     /// # Requirements
     ///
     /// Header: sgx_tae_service.edl
     ///
-    /// Library: libsgx_tservice_sim.a (simulation)
+    /// Library: libsgx_tservice.a
     ///
     /// # Return value
     ///
@@ -719,7 +740,7 @@
     /// The Monotonic Counter does not exist or has been invalidated.
     ///
     /// **SGX_ERROR_AE_SESSION_INVALID**
-    /// 
+    ///
     /// Session is not created or has been closed by architectural enclave service.
     ///
     /// **SGX_ERROR_SERVICE_UNAVAILABLE**
@@ -729,23 +750,23 @@
     /// **SGX_ERROR_SERVICE_TIMEOUT**
     ///
     /// A request to the AE service timed out.
-    /// 
+    ///
     /// **SGX_ERROR_NETWORK_FAILURE**
-    /// 
+    ///
     /// Network connecting or proxy setting issue was encountered.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_MEMORY**
-    /// 
+    ///
     /// Not enough memory is available to complete this operation.
-    /// 
+    ///
     /// **SGX_ERROR_OUT_OF_EPC**
-    /// 
+    ///
     /// There is not enough EPC memory to load one of the Architecture Enclaves needed to complete this operation.
-    /// 
+    ///
     /// **SGX_ERROR_UNEXPECTED**
-    /// 
+    ///
     /// Indicates an unexpected error occurs.
-    /// 
+    ///
     pub fn read(&self) -> SgxResult<u32> {
 
         if self.initflag.get() == false {
@@ -768,4 +789,4 @@
     fn drop(&mut self) {
         let _ = self.destory();
     }
-}
\ No newline at end of file
+}
diff --git a/sgx_tstdc/Cargo.toml b/sgx_tstdc/Cargo.toml
index 873199f..49619b4 100644
--- a/sgx_tstdc/Cargo.toml
+++ b/sgx_tstdc/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_tstdc"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Baidu"]
 
 [features]
@@ -9,3 +9,4 @@
 
 [dependencies]
 sgx_types = { path = "../sgx_types" }
+sgx_trts = { path = "../sgx_trts" }
diff --git a/sgx_tstdc/src/cond.rs b/sgx_tstdc/src/condvar.rs
similarity index 61%
rename from sgx_tstdc/src/cond.rs
rename to sgx_tstdc/src/condvar.rs
index a6e439e..d231c6d 100644
--- a/sgx_tstdc/src/cond.rs
+++ b/sgx_tstdc/src/condvar.rs
@@ -27,51 +27,58 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 //!
-//! The Intel(R) Software Guard Extensions SDK already supports mutex and conditional 
-//! variable synchronization mechanisms by means of the following APIand data types 
-//! defined in the Types and Enumerations section. Some functions included in the 
+//! The Intel(R) Software Guard Extensions SDK already supports mutex and conditional
+//! variable synchronization mechanisms by means of the following APIand data types
+//! defined in the Types and Enumerations section. Some functions included in the
 //! trusted Thread Synchronization library may make calls outside the enclave (OCALLs).
 //! If you use any of the APIs below, you must first import the needed OCALL functions
 //! from sgx_tstdc.edl. Otherwise, you will get a linker error when the enclave is
-//! being built; see Calling Functions outside the Enclave for additional details. 
-//! The table below illustrates the primitives that the Intel(R) SGX Thread 
+//! being built; see Calling Functions outside the Enclave for additional details.
+//! The table below illustrates the primitives that the Intel(R) SGX Thread
 //! Synchronization library supports, as well as the OCALLs that each API function needs.
 //!
 use sgx_types::*;
-use super::mutex::*;
+use sgx_trts::oom;
+use super::mutex::{self, SgxThreadMutex, SgxMutexGuard};
+use super::poison::{LockResult, PoisonError};
 use core::sync::atomic::{AtomicUsize, Ordering};
 
 #[cfg(not(feature = "use_std"))]
 use alloc::boxed::Box;
 
 pub unsafe fn raw_cond(lock: &sgx_thread_cond_t) -> * mut sgx_thread_cond_t {
-    lock as *const _ as *mut _
+    lock as * const _ as * mut _
 }
 
 #[allow(dead_code)]
-fn rsgx_thread_cond_init(cond: &sgx_thread_cond_t, unused: &sgx_thread_condattr_t ) -> sys_error_t {
-    
-    unsafe { sgx_thread_cond_init(raw_cond(cond), unused as * const sgx_thread_condattr_t) }
+unsafe fn rsgx_thread_cond_init(cond: &sgx_thread_cond_t, unused: &sgx_thread_condattr_t ) -> SysError {
+
+    let ret = sgx_thread_cond_init(raw_cond(cond), unused as * const sgx_thread_condattr_t);
+    if ret == 0 { Ok(()) } else { Err(ret) }
 }
 
-fn rsgx_thread_cond_destroy(cond: &sgx_thread_cond_t) -> sys_error_t {
-    
-    unsafe { sgx_thread_cond_destroy(raw_cond(cond)) }
+unsafe fn rsgx_thread_cond_destroy(cond: &sgx_thread_cond_t) -> SysError {
+
+    let ret = sgx_thread_cond_destroy(raw_cond(cond));
+    if ret == 0 { Ok(()) } else { Err(ret) }
 }
 
-fn rsgx_thread_cond_wait(cond: &sgx_thread_cond_t, mutex: &sgx_thread_mutex_t) -> sys_error_t {
-    
-    unsafe { sgx_thread_cond_wait(raw_cond(cond), raw_mutex(mutex)) }
+unsafe fn rsgx_thread_cond_wait(cond: &sgx_thread_cond_t, mutex: &sgx_thread_mutex_t) -> SysError {
+
+    let ret = sgx_thread_cond_wait(raw_cond(cond), mutex::raw_mutex(mutex));
+    if ret == 0 { Ok(()) } else { Err(ret) }
 }
 
-fn rsgx_thread_cond_signal(cond: &sgx_thread_cond_t) -> sys_error_t {
-    
-    unsafe { sgx_thread_cond_signal(raw_cond(cond)) }
+unsafe fn rsgx_thread_cond_signal(cond: &sgx_thread_cond_t) -> SysError {
+
+    let ret = sgx_thread_cond_signal(raw_cond(cond));
+    if ret == 0 { Ok(()) } else { Err(ret) }
 }
 
-fn rsgx_thread_cond_broadcast(cond: &sgx_thread_cond_t) -> sys_error_t {
-    
-    unsafe { sgx_thread_cond_broadcast(raw_cond(cond)) }
+unsafe fn rsgx_thread_cond_broadcast(cond: &sgx_thread_cond_t) -> SysError {
+
+    let ret = sgx_thread_cond_broadcast(raw_cond(cond));
+    if ret == 0 { Ok(()) } else { Err(ret) }
 }
 
 /// The structure of sgx condition.
@@ -83,50 +90,50 @@
 unsafe impl Sync for SgxThreadCond {}
 
 impl SgxThreadCond {
-    /// 
+    ///
     /// The function initializes a trusted condition variable within the enclave.
-    /// 
+    ///
     /// # Description
-    /// 
+    ///
     /// When a thread creates a condition variable within an enclave, it simply initializes the various
-    /// fields of the object to indicate that the condition variable is available. The results of using 
+    /// fields of the object to indicate that the condition variable is available. The results of using
     /// a condition variable in a wait, signal or broadcast operation before it has been fully initialized
-    /// are undefined. To avoid race conditions in the initialization of a condition variable, it is 
+    /// are undefined. To avoid race conditions in the initialization of a condition variable, it is
     /// recommended statically initializing the condition variable with the macro SGX_THREAD_COND_INITIALIZER.
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tstdc.a
     ///
-    pub fn new() -> Self {
+    pub const fn new() -> Self {
         SgxThreadCond{cond: SGX_THREAD_COND_INITIALIZER}
     }
 
-    /// 
+    ///
     /// The function waits on a condition variable within an enclave.
     ///
     /// # Description
-    /// 
+    ///
     /// A condition variable is always used in conjunction with a mutex. To wait on a
     /// condition variable, a thread first needs to acquire the condition variable spin
     /// lock. After the spin lock is acquired, the thread updates the condition variable
-    /// waiting queue. To avoid the lost wake-up signal problem, the condition variable 
+    /// waiting queue. To avoid the lost wake-up signal problem, the condition variable
     /// spin lock is released after the mutex. This order ensures the function atomically
-    /// releases the mutex and causes the calling thread to block on the condition variable, 
-    /// with respect to other threads accessing the mutex and the condition variable. 
-    /// After releasing the condition variable spin lock, the thread makes an OCALL to 
-    /// get suspended. When the thread is awakened, it acquires the condition variable 
-    /// spin lock. The thread then searches the condition variable queue. If the thread 
-    /// is in the queue, it means that the thread was already waiting on the condition 
-    /// variable outside the enclave, and it has been awakened unexpectedly. When this 
-    /// happens, the thread releases the condition variable spin lock, makes an OCALL 
+    /// releases the mutex and causes the calling thread to block on the condition variable,
+    /// with respect to other threads accessing the mutex and the condition variable.
+    /// After releasing the condition variable spin lock, the thread makes an OCALL to
+    /// get suspended. When the thread is awakened, it acquires the condition variable
+    /// spin lock. The thread then searches the condition variable queue. If the thread
+    /// is in the queue, it means that the thread was already waiting on the condition
+    /// variable outside the enclave, and it has been awakened unexpectedly. When this
+    /// happens, the thread releases the condition variable spin lock, makes an OCALL
     /// and simply goes back to sleep. Otherwise, another thread has signaled or broadcasted
     /// the condition variable and this thread may proceed. Before returning, the thread
-    /// releases the condition variable spin lock and acquires the mutex, ensuring that 
+    /// releases the condition variable spin lock and acquires the mutex, ensuring that
     /// upon returning from the function call the thread still owns the mutex.
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tstdc.a
     ///
     /// # Parameters
@@ -138,77 +145,74 @@
     /// # Errors
     ///
     /// **EINVAL**
-    /// 
+    ///
     /// The trusted condition variable or mutex object is invalid or the mutex is not locked.
-    /// 
+    ///
     /// **EPERM**
-    /// 
+    ///
     /// The trusted mutex is locked by another thread.
-    /// 
-    pub fn wait(&self, mutex: &SgxThreadMutex) -> SysError {
-        
-        let ret = rsgx_thread_cond_wait(&self.cond, mutex.get_raw());
-        if ret == 0 { Ok(()) } else { Err(ret) }
+    ///
+    #[inline]
+    pub unsafe fn wait(&self, mutex: &SgxThreadMutex) -> SysError {
+        rsgx_thread_cond_wait(&self.cond, mutex.get_raw())
     }
 
     ///
     /// The function wakes a pending thread waiting on the condition variable.
     ///
     /// # Description
-    /// 
+    ///
     /// To signal a condition variable, a thread starts acquiring the condition variable
     /// spin-lock. Then it inspects the status of the condition variable queue. If the
     /// queue is empty it means that there are not any threads waiting on the condition
-    /// variable. When that happens, the thread releases the condition variable and returns. 
-    /// However, if the queue is not empty, the thread removes the first thread waiting 
+    /// variable. When that happens, the thread releases the condition variable and returns.
+    /// However, if the queue is not empty, the thread removes the first thread waiting
     /// in the queue. The thread then makes an OCALL to wake up the thread that is suspended
     /// outside the enclave, but first the thread releases the condition variable spin-lock.
     /// Upon returning from the OCALL, the thread continues normal execution.
     ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tstdc.a
     ///
-    /// # Errors 
+    /// # Errors
     ///
     /// **EINVAL**
     ///
     /// The trusted condition variable is invalid.
     ///
-    pub fn signal(&self) -> SysError {
-        
-        let ret = rsgx_thread_cond_signal(&self.cond);
-        if ret == 0 { Ok(()) } else { Err(ret) }
+    #[inline]
+    pub unsafe fn signal(&self) -> SysError {
+        rsgx_thread_cond_signal(&self.cond)
     }
 
-    /// 
+    ///
     /// The function wakes all pending threads waiting on the condition variable.
     ///
     /// # Description
-    /// 
+    ///
     /// Broadcast and signal operations on a condition variable are analogous. The
     /// only difference is that during a broadcast operation, the thread removes all
     /// the threads waiting on the condition variable queue and wakes up all the
     /// threads suspended outside the enclave in a single OCALL.
     ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tstdc.a
     ///
     /// # Errors
-    /// 
+    ///
     /// **EINVAL**
-    /// 
+    ///
     /// The trusted condition variable is invalid.
-    /// 
+    ///
     /// **ENOMEM**
-    /// 
+    ///
     /// Internal memory allocation failed.
-    /// 
-    pub fn broadcast(&self) -> SysError {
-
-        let ret = rsgx_thread_cond_broadcast(&self.cond);
-        if ret == 0 { Ok(()) } else { Err(ret) }
+    ///
+    #[inline]
+    pub unsafe fn broadcast(&self) -> SysError {
+        rsgx_thread_cond_broadcast(&self.cond)
     }
 
     ///
@@ -216,45 +220,61 @@
     ///
     /// # Description
     ///
-    /// The procedure first confirms that there are no threads waiting on the condition 
+    /// The procedure first confirms that there are no threads waiting on the condition
     /// variable before it is destroyed. The destroy operation acquires the spin lock at
-    /// the beginning of the operation to prevent other threads from signaling to or 
+    /// the beginning of the operation to prevent other threads from signaling to or
     /// waiting on the condition variable.
     ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tstdc.a
     ///
     /// # Errors
-    /// 
+    ///
     /// **EINVAL**
-    /// 
+    ///
     /// The trusted condition variable is invalid.
-    /// 
+    ///
     /// **EBUSY**
-    /// 
+    ///
     /// The condition variable has pending threads waiting on it.
-    /// 
-    pub fn destory(&self) -> SysError {
-        
-        let ret = rsgx_thread_cond_destroy(&self.cond);
-        if ret == 0 { Ok(()) } else { Err(ret) }
+    ///
+    #[inline]
+    pub unsafe fn destroy(&self) -> SysError {
+        rsgx_thread_cond_destroy(&self.cond)
     }
 
     /// Get the pointer of sgx_thread_cond_t in SgxThreadCond.
-    pub fn get_raw(&self) -> &sgx_thread_cond_t {
+    #[allow(dead_code)]
+    #[inline]
+    pub unsafe fn get_raw(&self) -> &sgx_thread_cond_t {
         &self.cond
     }
 }
 
-/// The structure wrapped of SgxThreadCond.
+/// A Condition Variable
+///
+/// Condition variables represent the ability to block a thread such that it
+/// consumes no CPU time while waiting for an event to occur. Condition
+/// variables are typically associated with a boolean predicate (a condition)
+/// and a mutex. The predicate is always verified inside of the mutex before
+/// determining that a thread must block.
+///
+/// Functions in this module will block the current **thread** of execution and
+/// are bindings to system-provided condition variables where possible. Note
+/// that this module places one additional restriction over the system condition
+/// variables: each condvar can be used with precisely one mutex at runtime. Any
+/// attempt to use multiple mutexes on the same condition variable will result
+/// in a runtime panic. If this is not desired, then the unsafe primitives in
+/// `sys` do not have this restriction but may result in undefined behavior.
+///
 pub struct SgxCond {
     inner: Box<SgxThreadCond>,
     mutex: AtomicUsize,
 }
 
 impl SgxCond {
-    /// 
+    ///
     /// Creates a new condition variable which is ready to be waited on and notified.
     ///
     pub fn new() -> Self {
@@ -264,78 +284,90 @@
         }
     }
 
-    /// 
-    /// The function waits on a condition variable within an enclave.
-    /// 
     /// Blocks the current thread until this condition variable receives a
     /// notification.
     ///
     /// This function will atomically unlock the mutex specified (represented by
     /// `guard`) and block the current thread. This means that any calls
-    /// to [`broadcast`] which happen logically after the
+    /// to [`signal`] or [`broadcast`] which happen logically after the
     /// mutex is unlocked are candidates to wake this thread up. When this
     /// function call returns, the lock specified will have been re-acquired.
     ///
-    /// # Parameters
-    /// 
-    /// **guard**
-    ///
-    /// The SgxMutexGuard warpped of sgx_thread_mutex_t. The trusted mutex object that will be atomically unlocked.
-    ///
-    /// # Return value
-    ///
-    /// Indicates wait success. Return the guard.
+    /// Note that this function is susceptible to spurious wakeups. Condition
+    /// variables normally have a boolean predicate associated with them, and
+    /// the predicate must always be checked each time this function returns to
+    /// protect against spurious wakeups.
     ///
     /// # Errors
-    /// 
-    /// **EINVAL**
     ///
-    /// The trusted condition variable is invalid.
+    /// This function will return an error if the mutex being waited on is
+    /// poisoned when this thread re-acquires the lock. For more information,
+    /// see information about [poisoning] on the [`SgxMutex`] type.
     ///
-    pub fn wait<'a, T>(&self, guard: SgxMutexGuard<'a, T>) -> SysResult<SgxMutexGuard<'a, T>> {
+    /// # Panics
+    ///
+    /// This function will [`panic!`] if it is used with more than one mutex
+    /// over time. Each condition variable is dynamically bound to exactly one
+    /// mutex to ensure defined behavior across platforms. If this functionality
+    /// is not desired, then unsafe primitives in `sys` are provided.
+    pub fn wait<'a, T>(&self, guard: SgxMutexGuard<'a, T>) -> LockResult<SgxMutexGuard<'a, T>> {
 
-        let lock = guard_lock(&guard);
-
-        let error = self.verify(lock);
-        if error.is_err() {
-            return Err(error.unwrap_err());
+        let poisoned = unsafe {
+            let lock = mutex::guard_lock(&guard);
+            self.verify(lock);
+            let _ = self.inner.wait(lock);
+            mutex::guard_poison(&guard).get()
+        };
+        if poisoned {
+            Err(PoisonError::new(guard))
+        } else {
+            Ok(guard)
         }
-
-        self.inner.wait(lock).map(|_| guard)
     }
 
+    /// Wakes up one blocked thread on this condvar.
     ///
-    /// The function wakes a pending thread waiting on the condition variable.
+    /// If there is a blocked thread on this condition variable, then it will
+    /// be woken up from its call to [`wait`]. Calls to `signal` are not buffered
+    /// in any way.
     ///
-    pub fn signal(&self) -> SysError {
-       self.inner.signal()
+    /// To wake up all threads, see [`broadcast`].
+    pub fn signal(&self) {
+        unsafe { let _ = self.inner.signal(); }
     }
 
-    ///
-    /// Wakes up all blocked threads on this SgxCond.
+    /// Wakes up all blocked threads on this condvar.
     ///
     /// This method will ensure that any current waiters on the condition
     /// variable are awoken. Calls to `broadcast()` are not buffered in any
     /// way.
     ///
-    pub fn broadcast(&self) -> SysError {   
-       self.inner.broadcast()
+    /// To wake up only one thread, see [`signal`].
+    pub fn broadcast(&self) {
+
+        unsafe {
+            let ret = self.inner.broadcast();
+            match ret {
+                Err(r) if r == ENOMEM => oom::rsgx_oom(),
+                _ => {},
+            }
+        }
     }
 
-    fn verify(&self, mutex: &SgxThreadMutex) -> SysError {
-        
+    fn verify(&self, mutex: &SgxThreadMutex) {
+
         let addr = mutex as *const _ as usize;
         match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) {
-            0 => Ok(()),
-            n if n == addr => Ok(()),
-            _ => Err(EINVAL),
+            0 => {},
+            n if n == addr => {},
+            _ => panic!("attempted to use a condition variable with two mutexes."),
         }
-    } 
+    }
 }
 
 impl Drop for SgxCond {
     fn drop(&mut self) {
-        let _ = self.inner.destory();
+        unsafe { let _ = self.inner.destroy(); }
     }
 }
 
diff --git a/sgx_tstdc/src/cpuid.rs b/sgx_tstdc/src/cpuid.rs
new file mode 100644
index 0000000..6893830
--- /dev/null
+++ b/sgx_tstdc/src/cpuid.rs
@@ -0,0 +1,153 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use sgx_types::*;
+
+///
+/// The rsgx_cpuid function performs the equivalent of a cpuid() function call or
+/// intrinisic which executes the CPUID instruction to query the host processor for
+/// the information about supported features.
+///
+/// **Note**
+///
+/// This function performs an OCALL to execute the CPUID instruction.
+///
+/// # Description
+///
+/// This function provides the equivalent of the cpuid() function or intrinsic. The
+/// function executes the CPUID instruction for the given leaf (input). The CPUID
+/// instruction provides processor feature and type information that is returned in
+/// cpuinfo, an array of 4 integers to specify the values of EAX, EBX, ECX and EDX
+/// registers. rsgx_cpuid performs an OCALL by invoking oc_cpuidex to get the
+/// info from untrusted side because the CPUID instruction is an illegal instruction
+/// in the enclave domain.
+///
+/// **Note**
+///
+/// As the CPUID instruction is executed by an OCALL, the results should not
+/// be trusted. Code should verify the results and perform a threat evaluation
+/// to determine the impact on trusted code if the results were
+/// spoofed.
+///
+/// The implementation of this function performs an OCALL and therefore,
+/// this function will not have the same serializing or fencing behavior of
+/// executing a CPUID instruction in an untrusted domain code flow.
+///
+/// # Parameters
+///
+/// **leaf**
+///
+/// The leaf specified for retrieved CPU info.
+///
+/// # Requirements
+///
+/// Library: libsgx_tstdc.a
+///
+/// # Return value
+///
+/// The information returned in an array of four integers.
+///
+/// # Errors
+///
+/// **SGX_ERROR_INVALID_PARAMETER**
+///
+/// Indicates the parameter is invalid.
+///
+pub fn rsgx_cpuid(leaf: i32) -> SgxResult<sgx_cpuinfo_t> {
+
+    let cpuinfo = [0_i32; 4];
+    let ret = unsafe { sgx_cpuid(cpuinfo, leaf) };
+    match ret {
+        sgx_status_t::SGX_SUCCESS => Ok(cpuinfo),
+        _ => Err(ret),
+    }
+}
+
+///
+/// The rsgx_cpuidex function performs the equivalent of a cpuid_ex() function call or
+/// intrinisic which executes the CPUID instruction to query the host processor for
+/// the information about supported features.
+///
+/// **Note**
+///
+/// This function performs an OCALL to execute the CPUID instruction.
+///
+/// # Description
+///
+/// This function provides the equivalent of the cpuid_ex() function or intrinsic. The
+/// function executes the CPUID instruction for the given leaf (input). The CPUID
+/// instruction provides processor feature and type information that is returned in
+/// cpuinfo, an array of 4 integers to specify the values of EAX, EBX, ECX and EDX
+/// registers. rsgx_cpuidex performs an OCALL by invoking oc_cpuidex to get the
+/// info from untrusted side because the CPUID instruction is an illegal instruction
+/// in the enclave domain.
+///
+/// **Note**
+///
+/// As the CPUID instruction is executed by an OCALL, the results should not
+/// be trusted. Code should verify the results and perform a threat evaluation
+/// to determine the impact on trusted code if the results were
+/// spoofed.
+///
+/// The implementation of this function performs an OCALL and therefore,
+/// this function will not have the same serializing or fencing behavior of
+/// executing a CPUID instruction in an untrusted domain code flow.
+///
+/// # Parameters
+///
+/// **leaf**
+///
+/// The leaf specified for retrieved CPU info.
+///
+/// **subleaf**
+///
+/// The sub-leaf specified for retrieved CPU info.
+///
+/// # Requirements
+///
+/// Library: libsgx_tstdc.a
+///
+/// # Return value
+///
+/// The information returned in an array of four integers.
+///
+/// # Errors
+///
+/// **SGX_ERROR_INVALID_PARAMETER**
+///
+/// Indicates the parameter is invalid.
+///
+pub fn rsgx_cpuidex(leaf: i32, subleaf: i32) -> SgxResult<sgx_cpuinfo_t> {
+
+    let cpuinfo = [0_i32; 4];
+    let ret = unsafe { sgx_cpuidex(cpuinfo, leaf, subleaf) };
+    match ret {
+        sgx_status_t::SGX_SUCCESS => Ok(cpuinfo),
+        _ => Err(ret),
+    }
+}
diff --git a/sgx_tstdc/src/lib.rs b/sgx_tstdc/src/lib.rs
index a72eed2..c7ccc8e 100644
--- a/sgx_tstdc/src/lib.rs
+++ b/sgx_tstdc/src/lib.rs
@@ -28,9 +28,12 @@
 
 //!
 //! The library is named sgx_tstdc, provides the following functions:
-//! 
+//!
 //! * Mutex
 //! * Condition
+//! * Rwlock
+//! * Once call
+//! * thread
 //! * Query CPUID inside Enclave
 //! * Spin lock
 //!
@@ -38,9 +41,14 @@
 #![crate_type = "rlib"]
 
 #![cfg_attr(not(feature = "use_std"), no_std)]
-#![cfg_attr(not(feature = "use_std"), feature(alloc, optin_builtin_traits))]
+#![feature(optin_builtin_traits)]
+#![feature(const_fn)]
+#![feature(dropck_eyepatch)]
+#![feature(generic_param_attrs)]
+#![cfg_attr(not(feature = "use_std"), feature(alloc))]
 
 #![allow(non_camel_case_types)]
+#![allow(deprecated)]
 
 #[cfg(feature = "use_std")]
 extern crate std as core;
@@ -49,225 +57,35 @@
 extern crate alloc;
 
 extern crate sgx_types;
-use sgx_types::*;
 
-pub mod mutex;
-pub use self::mutex::*;
+#[macro_use]
+extern crate sgx_trts;
 
-pub mod cond;
-pub use self::cond::*;
+mod cpuid;
+pub use cpuid::*;
 
-///
-/// The rsgx_cpuid function performs the equivalent of a cpuid() function call or
-/// intrinisic which executes the CPUID instruction to query the host processor for
-/// the information about supported features.
-///
-/// **Note**
-///
-/// This function performs an OCALL to execute the CPUID instruction.
-///
-/// # Description
-///
-/// This function provides the equivalent of the cpuid() function or intrinsic. The
-/// function executes the CPUID instruction for the given leaf (input). The CPUID
-/// instruction provides processor feature and type information that is returned in
-/// cpuinfo, an array of 4 integers to specify the values of EAX, EBX, ECX and EDX
-/// registers. rsgx_cpuid performs an OCALL by invoking oc_cpuidex to get the
-/// info from untrusted side because the CPUID instruction is an illegal instruction
-/// in the enclave domain.
-///
-/// **Note**
-///
-/// As the CPUID instruction is executed by an OCALL, the results should not
-/// be trusted. Code should verify the results and perform a threat evaluation
-/// to determine the impact on trusted code if the results were
-/// spoofed.
-///
-/// The implementation of this function performs an OCALL and therefore,
-/// this function will not have the same serializing or fencing behavior of
-/// executing a CPUID instruction in an untrusted domain code flow.
-///
-/// # Parameters
-///
-/// **leaf**
-///
-/// The leaf specified for retrieved CPU info.
-///
-/// # Requirements
-///
-/// Library: libsgx_tstdc.a
-///
-/// # Return value
-///
-/// The information returned in an array of four integers.
-///
-/// # Errors
-///
-/// **SGX_ERROR_INVALID_PARAMETER**
-///
-/// Indicates the parameter is invalid.
-///
-pub fn rsgx_cpuid(leaf: i32) -> SgxResult<sgx_cpuinfo_t> {
-    
-    let cpuinfo = [0_i32; 4];
-    let ret = unsafe { sgx_cpuid(cpuinfo, leaf) };
-    match ret {
-        sgx_status_t::SGX_SUCCESS => Ok(cpuinfo),
-        _ => Err(ret),
-    }
-}
+mod mutex;
+pub use self::mutex::{SgxMutex, SgxMutexGuard};
 
-///
-/// The rsgx_cpuidex function performs the equivalent of a cpuid_ex() function call or
-/// intrinisic which executes the CPUID instruction to query the host processor for
-/// the information about supported features.
-///
-/// **Note**
-///
-/// This function performs an OCALL to execute the CPUID instruction.
-///
-/// # Description
-///
-/// This function provides the equivalent of the cpuid_ex() function or intrinsic. The
-/// function executes the CPUID instruction for the given leaf (input). The CPUID
-/// instruction provides processor feature and type information that is returned in
-/// cpuinfo, an array of 4 integers to specify the values of EAX, EBX, ECX and EDX
-/// registers. rsgx_cpuidex performs an OCALL by invoking oc_cpuidex to get the
-/// info from untrusted side because the CPUID instruction is an illegal instruction
-/// in the enclave domain.
-///
-/// **Note**
-///
-/// As the CPUID instruction is executed by an OCALL, the results should not
-/// be trusted. Code should verify the results and perform a threat evaluation
-/// to determine the impact on trusted code if the results were
-/// spoofed.
-///
-/// The implementation of this function performs an OCALL and therefore,
-/// this function will not have the same serializing or fencing behavior of
-/// executing a CPUID instruction in an untrusted domain code flow.
-///
-/// # Parameters
-///
-/// **leaf**
-///
-/// The leaf specified for retrieved CPU info.
-///
-/// **subleaf**
-///
-/// The sub-leaf specified for retrieved CPU info.
-///
-/// # Requirements
-///
-/// Library: libsgx_tstdc.a
-///
-/// # Return value
-///
-/// The information returned in an array of four integers.
-///
-/// # Errors
-///
-/// **SGX_ERROR_INVALID_PARAMETER**
-///
-/// Indicates the parameter is invalid.
-///
-pub fn rsgx_cpuidex(leaf: i32, subleaf: i32) -> SgxResult<sgx_cpuinfo_t> {
+mod condvar;
+pub use self::condvar::{SgxCond};
 
-    let cpuinfo = [0_i32; 4];
-    let ret = unsafe { sgx_cpuidex(cpuinfo, leaf, subleaf) };
-    match ret {
-        sgx_status_t::SGX_SUCCESS => Ok(cpuinfo),
-        _ => Err(ret),
-    }
-}
+mod spinlock;
+pub use self::spinlock::{SgxSpinlock, SgxSpinlockGuard};
 
-/// 
-/// The rsgx_spin_lock function acquires a spin lock within the enclave.
-///
-/// # Description
-///
-/// rsgx_spin_lock modifies the value of the spin lock by using compiler atomic
-/// operations. If the lock is not available to be acquired, the thread will always
-/// wait on the lock until it can be acquired successfully.
-///
-/// # Parameters
-///
-/// **lock**
-///
-/// The trusted spin lock object to be acquired.
-///
-/// # Requirements
-///
-/// Library: libsgx_tstdc.a
-///
-pub fn rsgx_spin_lock(lock: &mut sgx_spinlock_t) {
+#[allow(unused_must_use)]
+mod rwlock;
+pub use self::rwlock::{SgxRwLock, SgxRwLockReadGuard, SgxRwLockWriteGuard};
 
-    unsafe { sgx_spin_lock(lock as * mut sgx_spinlock_t); }
-}
+pub mod thread;
+pub use self::thread::{SgxThread, rsgx_thread_self, rsgx_thread_equal};
 
-/// 
-/// The rsgx_spin_unlock function releases a spin lock within the enclave.
-///
-/// # Description
-///
-/// rsgx_spin_unlock resets the value of the spin lock, regardless of its current
-/// state. This function simply assigns a value of zero to the lock, which indicates
-/// the lock is released.
-///
-/// # Parameters
-///
-/// **lock**
-///
-/// The trusted spin lock object to be released.
-///
-/// # Requirements
-///
-/// Library: libsgx_tstdc.a
-///
-pub fn rsgx_spin_unlock(lock: &mut sgx_spinlock_t) {
+pub mod thread_info;
+pub mod once;
 
-    unsafe { sgx_spin_unlock(lock as * mut sgx_spinlock_t); }
-}
+mod poison;
+pub use poison::{PoisonError, TryLockError, TryLockResult, LockResult};
 
-///
-/// The rsgx_thread_self function returns the unique thread identification.
-///
-/// # Description
-///
-/// The function is a simple wrap of get_thread_data() provided in the tRTS,
-/// which provides a trusted thread unique identifier.
-///
-/// # Requirements
-///
-/// Library: libsgx_tstdc.a
-///
-/// # Return value
-///
-/// The return value cannot be NULL and is always valid as long as it is invoked by a thread inside the enclave.
-///
-pub fn rsgx_thread_self() -> sgx_thread_t {
-    
-    unsafe { sgx_thread_self() }
-}
 
-///
-/// The rsgx_thread_equal function compares two thread identifiers.
-///
-/// # Description
-///
-/// The function compares two thread identifiers provided by sgx_thread_
-/// self to determine if the IDs refer to the same trusted thread.
-///
-/// # Requirements
-///
-/// Library: libsgx_tstdc.a
-///
-/// # Return value
-///
-/// **true**
-///
-/// The two thread IDs are equal.
-///
-pub fn rsgx_thread_equal(a: sgx_thread_t, b: sgx_thread_t) -> bool {
-    a == b
-}
+
+
diff --git a/sgx_tstdc/src/mutex.rs b/sgx_tstdc/src/mutex.rs
index 7a1b4f4..2ee55ad 100644
--- a/sgx_tstdc/src/mutex.rs
+++ b/sgx_tstdc/src/mutex.rs
@@ -27,55 +27,62 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 //!
-//! The Intel(R) Software Guard Extensions SDK already supports mutex and conditional 
-//! variable synchronization mechanisms by means of the following APIand data types 
-//! defined in the Types and Enumerations section. Some functions included in the 
+//! The Intel(R) Software Guard Extensions SDK already supports mutex and conditional
+//! variable synchronization mechanisms by means of the following APIand data types
+//! defined in the Types and Enumerations section. Some functions included in the
 //! trusted Thread Synchronization library may make calls outside the enclave (OCALLs).
 //! If you use any of the APIs below, you must first import the needed OCALL functions
 //! from sgx_tstdc.edl. Otherwise, you will get a linker error when the enclave is
-//! being built; see Calling Functions outside the Enclave for additional details. 
-//! The table below illustrates the primitives that the Intel(R) SGX Thread 
+//! being built; see Calling Functions outside the Enclave for additional details.
+//! The table below illustrates the primitives that the Intel(R) SGX Thread
 //! Synchronization library supports, as well as the OCALLs that each API function needs.
 //!
 use sgx_types::*;
+#[cfg(not(feature = "use_std"))]
+use sgx_trts::panic::{UnwindSafe, RefUnwindSafe};
+use super::poison::{self, TryLockError, TryLockResult, LockResult};
 use core::cell::UnsafeCell;
 use core::mem;
 use core::ptr;
 use core::ops::{Deref, DerefMut};
-#[cfg(not(feature = "use_std"))]
 use core::marker;
 #[cfg(not(feature = "use_std"))]
 use alloc::boxed::Box;
 
 
 pub unsafe fn raw_mutex(lock: &sgx_thread_mutex_t) -> * mut sgx_thread_mutex_t {
-    lock as *const _ as *mut _
+    lock as * const _ as * mut _
 }
 
 #[allow(dead_code)]
-fn rsgx_thread_mutex_init(mutex: &sgx_thread_mutex_t, unused: &sgx_thread_mutexattr_t) -> sys_error_t {
+unsafe fn rsgx_thread_mutex_init(mutex: &sgx_thread_mutex_t, unused: &sgx_thread_mutexattr_t) -> SysError {
 
-    unsafe { sgx_thread_mutex_init(raw_mutex(mutex), unused as * const sgx_thread_mutexattr_t) }
+    let ret = sgx_thread_mutex_init(raw_mutex(mutex), unused as * const sgx_thread_mutexattr_t);
+    if ret == 0 { Ok(()) } else { Err(ret) }
 }
 
-fn rsgx_thread_mutex_destroy(mutex: &sgx_thread_mutex_t) -> sys_error_t {
-    
-    unsafe { sgx_thread_mutex_destroy(raw_mutex(mutex)) }
+unsafe fn rsgx_thread_mutex_destroy(mutex: &sgx_thread_mutex_t) -> SysError {
+
+    let ret = sgx_thread_mutex_destroy(raw_mutex(mutex));
+    if ret == 0 { Ok(()) } else { Err(ret) }
 }
 
-fn rsgx_thread_mutex_lock(mutex: &sgx_thread_mutex_t) -> sys_error_t {
-    
-    unsafe { sgx_thread_mutex_lock(raw_mutex(mutex)) }
+unsafe fn rsgx_thread_mutex_lock(mutex: &sgx_thread_mutex_t) -> SysError {
+
+    let ret = sgx_thread_mutex_lock(raw_mutex(mutex));
+    if ret == 0 { Ok(()) } else { Err(ret) }
 }
 
-fn rsgx_thread_mutex_trylock(mutex: &sgx_thread_mutex_t) -> sys_error_t {
-    
-    unsafe { sgx_thread_mutex_trylock(raw_mutex(mutex)) }
+unsafe fn rsgx_thread_mutex_trylock(mutex: &sgx_thread_mutex_t) -> SysError {
+
+    let ret = sgx_thread_mutex_trylock(raw_mutex(mutex));
+    if ret == 0 { Ok(()) } else { Err(ret) }
 }
 
-fn rsgx_thread_mutex_unlock(mutex: &sgx_thread_mutex_t) -> sys_error_t {
-    
-    unsafe { sgx_thread_mutex_unlock(raw_mutex(mutex)) }
+unsafe fn rsgx_thread_mutex_unlock(mutex: &sgx_thread_mutex_t) -> SysError {
+
+    let ret = sgx_thread_mutex_unlock(raw_mutex(mutex));
+    if ret == 0 { Ok(()) } else { Err(ret) }
 }
 
 /// The structure of sgx mutex.
@@ -87,12 +94,12 @@
 unsafe impl Sync for SgxThreadMutex {}
 
 impl SgxThreadMutex {
-    
+
     ///
     /// The function initializes a trusted mutex object within the enclave.
     ///
     /// # Description
-    /// 
+    ///
     /// When a thread creates a mutex within an enclave, sgx_thread_mutex_
     /// init simply initializes the various fields of the mutex object to indicate that
     /// the mutex is available. rsgx_thread_mutex_init creates a non-recursive
@@ -102,24 +109,24 @@
     /// trusted mutex, it is recommended statically initializing the mutex with the
     /// macro SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_NON_RECURSIVE_MUTEX_INITIALIZER ,
     /// of, or SGX_THREAD_RECURSIVE_MUTEX_INITIALIZER instead.
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tstdc.a
     ///
     /// # Return value
     ///
     /// The trusted mutex object to be initialized.
     ///
-    pub fn new() -> Self {
+    pub const fn new() -> Self {
         SgxThreadMutex{lock: SGX_THREAD_NONRECURSIVE_MUTEX_INITIALIZER}
     }
-    
+
     ///
     /// The function locks a trusted mutex object within an enclave.
     ///
     /// # Description
-    /// 
+    ///
     /// To acquire a mutex, a thread first needs to acquire the corresponding spin
     /// lock. After the spin lock is acquired, the thread checks whether the mutex is
     /// available. If the queue is empty or the thread is at the head of the queue the
@@ -139,28 +146,27 @@
     /// A thread should not exit an enclave returning from a root ECALL after acquiring
     /// the ownership of a mutex. Do not split the critical section protected by a
     /// mutex across root ECALLs.
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tstdc.a
     ///
     /// # Errors
     ///
     /// **EINVAL**
-    /// 
+    ///
     /// The trusted mutex object is invalid.
-    /// 
-    pub fn lock(&self) -> SysError {
-
-        let ret = rsgx_thread_mutex_lock(&self.lock);
-        if ret == 0 { Ok(()) } else { Err(ret) }
+    ///
+    #[inline]
+    pub unsafe fn lock(&self) -> SysError {
+        rsgx_thread_mutex_lock(&self.lock)
     }
-    
+
     ///
     /// The function tries to lock a trusted mutex object within an enclave.
     ///
     /// # Description
-    /// 
+    ///
     /// A thread may check the status of the mutex, which implies acquiring the spin
     /// lock and verifying that the mutex is available and that the queue is empty or
     /// the thread is at the head of the queue. When this happens, the thread
@@ -173,68 +179,66 @@
     /// A thread should not exit an enclave returning from a root ECALL after acquiring
     /// the ownership of a mutex. Do not split the critical section protected by a
     /// mutex across root ECALLs.
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tstdc.a
     ///
     /// # Errors
     ///
     /// **EINVAL**
-    /// 
+    ///
     /// The trusted mutex object is invalid.
-    /// 
+    ///
     /// **EBUSY**
-    /// 
+    ///
     /// The mutex is locked by another thread or has pending threads to acquire the mutex
     ///
-    pub fn trylock(&self) -> SysError {
-
-        let ret = rsgx_thread_mutex_trylock(&self.lock);
-        if ret == 0 { Ok(()) } else { Err(ret) }
+    #[inline]
+    pub unsafe fn try_lock(&self) -> SysError {
+        rsgx_thread_mutex_trylock(&self.lock)
     }
 
     ///
     /// The function unlocks a trusted mutex object within an enclave.
     ///
     /// # Description
-    /// 
+    ///
     /// Before a thread releases a mutex, it has to verify it is the owner of the mutex. If
     /// that is the case, the thread decreases the refcount by 1 and then may either
     /// continue normal execution or wakeup the first thread in the queue. Note that
     /// to ensure the state of the mutex remains consistent, the thread that is
     /// awakened by the thread releasing the mutex will then try to acquire the
     /// mutex almost as in the initial call to the rsgx_thread_mutex_lock routine.
-    /// 
+    ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tstdc.a
     ///
     /// # Errors
     ///
     /// **EINVAL**
-    /// 
+    ///
     /// The trusted mutex object is invalid or it is not locked by any thread.
-    /// 
+    ///
     /// **EPERM**
-    /// 
+    ///
     /// The mutex is locked by another thread.
     ///
-    pub fn unlock(&self) -> SysError {
-
-        let ret = rsgx_thread_mutex_unlock(&self.lock);
-        if ret == 0 { Ok(()) } else { Err(ret) }
+    #[inline]
+    pub unsafe fn unlock(&self) -> SysError {
+        rsgx_thread_mutex_unlock(&self.lock)
     }
 
     ///
     /// The function destroys a trusted mutex object within an enclave.
     ///
     /// # Description
-    /// 
+    ///
     /// rsgx_thread_mutex_destroy resets the mutex, which brings it to its initial
     /// status. In this process, certain fields are checked to prevent releasing a mutex
     /// that is still owned by a thread or on which threads are still waiting.
-    /// 
+    ///
     /// **Note**
     ///
     /// Locking or unlocking a mutex after it has been destroyed results in undefined
@@ -242,39 +246,72 @@
     /// used again.
     ///
     /// # Requirements
-    /// 
+    ///
     /// Library: libsgx_tstdc.a
     ///
     /// # Errors
     ///
     /// **EINVAL**
-    /// 
+    ///
     /// The trusted mutex object is invalid.
-    /// 
+    ///
     /// **EBUSY**
-    /// 
+    ///
     /// The mutex is locked by another thread or has pending threads to acquire the mutex.
     ///
-    pub fn destory(&self) -> SysError {
-
-        let ret = rsgx_thread_mutex_destroy(&self.lock);
-        if ret == 0 { Ok(()) } else { Err(ret) }
+    #[inline]
+    pub unsafe fn destroy(&self) -> SysError {
+        rsgx_thread_mutex_destroy(&self.lock)
     }
 
     /// Get the pointer of sgx_thread_mutex_t in SgxThreadMutex.
-    pub fn get_raw(&self) -> &sgx_thread_mutex_t {
+    #[inline]
+    pub unsafe fn get_raw(&self) -> &sgx_thread_mutex_t {
         &self.lock
     }
 }
 
-/// The structure wrapped of SgxThreadMutex.
+/// A mutual exclusion primitive useful for protecting shared data
+///
+/// This mutex will block threads waiting for the lock to become available. The
+/// mutex can also be statically initialized or created via a `new`
+/// constructor. Each mutex has a type parameter which represents the data that
+/// it is protecting. The data can only be accessed through the RAII guards
+/// returned from `lock` and `try_lock`, which guarantees that the data is only
+/// ever accessed when the mutex is locked.
+///
+/// # Poisoning
+///
+/// The mutexes in this module implement a strategy called "poisoning" where a
+/// mutex is considered poisoned whenever a thread panics while holding the
+/// mutex. Once a mutex is poisoned, all other threads are unable to access the
+/// data by default as it is likely tainted (some invariant is not being
+/// upheld).
+///
+/// For a mutex, this means that the `lock` and `try_lock` methods return a
+/// `Result` which indicates whether a mutex has been poisoned or not. Most
+/// usage of a mutex will simply `unwrap()` these results, propagating panics
+/// among threads to ensure that a possibly invalid invariant is not witnessed.
+///
+/// A poisoned mutex, however, does not prevent all access to the underlying
+/// data. The `PoisonError` type has an `into_inner` method which will return
+/// the guard that would have otherwise been returned on a successful lock. This
+/// allows access to the data, despite the lock being poisoned.
+///
 pub struct SgxMutex<T: ?Sized> {
     inner: Box<SgxThreadMutex>,
+    poison: poison::Flag,
     data: UnsafeCell<T>
 }
 
-unsafe impl<T: ?Sized + Send> Send for SgxMutex<T> { }
-unsafe impl<T: ?Sized + Send> Sync for SgxMutex<T> { }
+// these are the only places where `T: Send` matters; all other
+// functionality works fine on a single thread.
+unsafe impl<T: ?Sized + Send> Send for SgxMutex<T> {}
+unsafe impl<T: ?Sized + Send> Sync for SgxMutex<T> {}
+#[cfg(not(feature = "use_std"))]
+impl<T: ?Sized> UnwindSafe for SgxMutex<T> {}
+#[cfg(not(feature = "use_std"))]
+impl<T: ?Sized> RefUnwindSafe for SgxMutex<T> {}
 
 impl<T> SgxMutex<T> {
     ///
@@ -283,6 +320,7 @@
     pub fn new(t: T) -> SgxMutex<T> {
         SgxMutex{
             inner: Box::new(SgxThreadMutex::new()),
+            poison: poison::Flag::new(),
             data: UnsafeCell::new(t),
         }
     }
@@ -293,83 +331,147 @@
     ///
     /// The function locks a trusted mutex object within an enclave.
     ///
-    /// An RAII guard is returned to allow scoped unlock of the lock. When
+    /// Acquires a mutex, blocking the current thread until it is able to do so.
+    ///
+    /// This function will block the local thread until it is available to acquire
+    /// the mutex. Upon returning, the thread is the only thread with the lock
+    /// held. An RAII guard is returned to allow scoped unlock of the lock. When
     /// the guard goes out of scope, the mutex will be unlocked.
     ///
-    pub fn lock(&self) -> SysResult<SgxMutexGuard<T>> {
-        self.inner.lock().map(|_| SgxMutexGuard::new(self))
+    /// The exact behavior on locking a mutex in the thread which already holds
+    /// the lock is left unspecified. However, this function will not return on
+    /// the second call (it might panic or deadlock, for example).
+    ///
+    /// # Errors
+    ///
+    /// If another user of this mutex panicked while holding the mutex, then
+    /// this call will return an error once the mutex is acquired.
+    ///
+    /// # Panics
+    ///
+    /// This function might panic when called if the lock is already held by
+    /// the current thread.
+    pub fn lock(&self) -> LockResult<SgxMutexGuard<T>> {
+        unsafe {
+            let _ = self.inner.lock();
+            SgxMutexGuard::new(self)
+        }
     }
 
     ///
     /// The function tries to lock a trusted mutex object within an enclave.
     ///
+    /// Attempts to acquire this lock.
+    ///
     /// If the lock could not be acquired at this time, then `Err` is returned.
     /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
     /// guard is dropped.
     ///
     /// This function does not block.
     ///
-    pub fn try_lock(&self) -> SysResult<SgxMutexGuard<T>> {
-        self.inner.trylock().map(|_| SgxMutexGuard::new(self))
+    /// # Errors
+    ///
+    /// If another user of this mutex panicked while holding the mutex, then
+    /// this call will return failure if the mutex would otherwise be
+    /// acquired.
+    pub fn try_lock(&self) -> TryLockResult<SgxMutexGuard<T>> {
+        unsafe {
+            match self.inner.try_lock() {
+                Ok(_) => Ok(SgxMutexGuard::new(self)?),
+                Err(_) => Err(TryLockError::WouldBlock),
+            }
+        }
+    }
+
+    /// Determines whether the mutex is poisoned.
+    ///
+    /// If another thread is active, the mutex can still become poisoned at any
+    /// time. You should not trust a `false` value for program correctness
+    /// without additional synchronization.
+    #[inline]
+    pub fn is_poisoned(&self) -> bool {
+        self.poison.get()
     }
 
     /// Consumes this mutex, returning the underlying data.
-    pub fn into_inner(self) -> SysResult<T> where T: Sized {
+    ///
+    /// # Errors
+    ///
+    /// If another user of this mutex panicked while holding the mutex, then
+    /// this call will return an error instead.
+    pub fn into_inner(self) -> LockResult<T> where T: Sized {
 
         unsafe {
-            let (inner, data) = {
-                let SgxMutex {ref inner, ref data } = self;
-                (ptr::read(inner), ptr::read(data))
+            let (inner, poison, data) = {
+                let SgxMutex {ref inner, ref poison, ref data } = self;
+                (ptr::read(inner), ptr::read(poison), ptr::read(data))
             };
             mem::forget(self);
-            let result = inner.destory();
+            let _ = inner.destroy();
             drop(inner);
-            result.map(|_| data.into_inner())
+
+            poison::map_result(poison.borrow(), |_| data.into_inner())
         }
     }
 
     /// Returns a mutable reference to the underlying data.
-    pub fn get_mut(&mut self) -> SysResult<&mut T> {
-      
+    ///
+    /// Since this call borrows the `Mutex` mutably, no actual locking needs to
+    /// take place---the mutable borrow statically guarantees no locks exist.
+    ///
+    /// # Errors
+    ///
+    /// If another user of this mutex panicked while holding the mutex, then
+    /// this call will return an error instead.
+    pub fn get_mut(&mut self) -> LockResult<&mut T> {
+
         let data = unsafe { &mut *self.data.get() };
-        Ok(data)
+        poison::map_result(self.poison.borrow(), |_| data)
     }
 }
 
-impl<T: ?Sized> Drop for SgxMutex<T> {
+unsafe impl<#[may_dangle] T: ?Sized> Drop for SgxMutex<T> {
     fn drop(&mut self) {
-       let _ = self.inner.destory();
+        // IMPORTANT: This code must be kept in sync with `Mutex::into_inner`.
+        unsafe {
+            let _ = self.inner.destroy();
+        }
     }
 }
 
 impl<T: ?Sized + Default> Default for SgxMutex<T> {
+    /// Creates a `SgxMutex<T>`, with the `Default` value for T.
     fn default() -> SgxMutex<T> {
         SgxMutex::new(Default::default())
     }
 }
 
-///
+
 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
 /// dropped (falls out of scope), the lock will be unlocked.
 ///
 /// The data protected by the mutex can be accessed through this guard via its
-/// Deref and DerefMut implementations.
+/// [`Deref`] and [`DerefMut`] implementations.
 ///
-/// This structure is created by the lock and try_lock methods on Mutex.
-///
+/// This structure is created by the [`lock`] and [`try_lock`] methods on
+/// [`SgxMutex`].
 pub struct SgxMutexGuard<'a, T: ?Sized + 'a> {
     lock: &'a SgxMutex<T>,
+    poison: poison::Guard,
 }
 
-#[cfg(not(feature = "use_std"))]
-impl<'a, T: ?Sized> !marker::Send for SgxMutexGuard<'a, T> {}
+impl<'a, T: ?Sized> !marker::Send for SgxMutexGuard<'a, T> { }
+unsafe impl<'a, T: ?Sized + Sync> Sync for SgxMutexGuard<'a, T> { }
 
 impl<'mutex, T: ?Sized> SgxMutexGuard<'mutex, T> {
 
-    fn new(lock: &'mutex SgxMutex<T>) -> SgxMutexGuard<'mutex, T> {
-        SgxMutexGuard {
-            lock: lock,
-        }
+    unsafe fn new(lock: &'mutex SgxMutex<T>) -> LockResult<SgxMutexGuard<'mutex, T>> {
+        poison::map_result(lock.poison.borrow(), |guard| {
+            SgxMutexGuard {
+                lock: lock,
+                poison: guard,
+            }
+        })
     }
 }
 
@@ -390,10 +492,17 @@
 impl<'a, T: ?Sized> Drop for SgxMutexGuard<'a, T> {
     #[inline]
     fn drop(&mut self) {
-       let _ = self.lock.inner.unlock();
+        unsafe {
+            self.lock.poison.done(&self.poison);
+            let _ = self.lock.inner.unlock();
+        }
     }
 }
 
 pub fn guard_lock<'a, T: ?Sized>(guard: &SgxMutexGuard<'a, T>) -> &'a SgxThreadMutex {
     &guard.lock.inner
 }
+
+pub fn guard_poison<'a, T: ?Sized>(guard: &SgxMutexGuard<'a, T>) -> &'a poison::Flag {
+    &guard.lock.poison
+}
diff --git a/sgx_tstdc/src/once.rs b/sgx_tstdc/src/once.rs
new file mode 100644
index 0000000..e636601
--- /dev/null
+++ b/sgx_tstdc/src/once.rs
@@ -0,0 +1,335 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//! A "once initialization" primitive
+//!
+//! This primitive is meant to be used to run one-time initialization. An
+//! example use case would be for initializing an FFI library.
+
+// A "once" is a relatively simple primitive, and it's also typically provided
+// by the OS as well (see `pthread_once` or `InitOnceExecuteOnce`). The OS
+// primitives, however, tend to have surprising restrictions, such as the Unix
+// one doesn't allow an argument to be passed to the function.
+//
+// As a result, we end up implementing it ourselves in the standard library.
+// This also gives us the opportunity to optimize the implementation a bit which
+// should help the fast path on call sites. Consequently, let's explain how this
+// primitive works now!
+//
+// So to recap, the guarantees of a Once are that it will call the
+// initialization closure at most once, and it will never return until the one
+// that's running has finished running. This means that we need some form of
+// blocking here while the custom callback is running at the very least.
+// Additionally, we add on the restriction of **poisoning**. Whenever an
+// initialization closure panics, the Once enters a "poisoned" state which means
+// that all future calls will immediately panic as well.
+//
+// So to implement this, one might first reach for a `StaticMutex`, but those
+// unfortunately need to be deallocated (e.g. call `destroy()`) to free memory
+// on all OSes (some of the BSDs allocate memory for mutexes). It also gets a
+// lot harder with poisoning to figure out when the mutex needs to be
+// deallocated because it's not after the closure finishes, but after the first
+// successful closure finishes.
+//
+// All in all, this is instead implemented with atomics and lock-free
+// operations! Whee! Each `Once` has one word of atomic state, and this state is
+// CAS'd on to determine what to do. There are four possible state of a `Once`:
+//
+// * Incomplete - no initialization has run yet, and no thread is currently
+//                using the Once.
+// * Poisoned - some thread has previously attempted to initialize the Once, but
+//              it panicked, so the Once is now poisoned. There are no other
+//              threads currently accessing this Once.
+// * Running - some thread is currently attempting to run initialization. It may
+//             succeed, so all future threads need to wait for it to finish.
+//             Note that this state is accompanied with a payload, described
+//             below.
+// * Complete - initialization has completed and all future calls should finish
+//              immediately.
+//
+// With 4 states we need 2 bits to encode this, and we use the remaining bits
+// in the word we have allocated as a queue of threads waiting for the thread
+// responsible for entering the RUNNING state. This queue is just a linked list
+// of Waiter nodes which is monotonically increasing in size. Each node is
+// allocated on the stack, and whenever the running closure finishes it will
+// consume the entire queue and notify all waiters they should try again.
+//
+// You'll find a few more details in the implementation, but that's the gist of
+// it!
+
+use core::marker::PhantomData;
+use core::ptr;
+use core::sync::atomic::{AtomicUsize, AtomicBool, Ordering};
+use super::thread::{self, SgxThread};
+
+/// A synchronization primitive which can be used to run a one-time global
+/// initialization. Useful for one-time initialization for FFI or related
+/// functionality. This type can only be constructed with the [`ONCE_INIT`]
+/// value.
+pub struct Once {
+    // This `state` word is actually an encoded version of just a pointer to a
+    // `Waiter`, so we add the `PhantomData` appropriately.
+    state: AtomicUsize,
+    marker: PhantomData<* mut Waiter>,
+}
+
+// The `PhantomData` of a raw pointer removes these two auto traits, but we
+// enforce both below in the implementation so this should be safe to add.
+unsafe impl Sync for Once {}
+unsafe impl Send for Once {}
+
+/// State yielded to the [`call_once_force`] method which can be used to query
+/// whether the [`Once`] was previously poisoned or not.
+#[derive(Debug)]
+pub struct OnceState {
+    poisoned: bool,
+}
+
+/// Initialization value for static [`Once`] values.
+pub const ONCE_INIT: Once = Once::new();
+
+// Four states that a Once can be in, encoded into the lower bits of `state` in
+// the Once structure.
+const INCOMPLETE: usize = 0x0;
+const POISONED: usize = 0x1;
+const RUNNING: usize = 0x2;
+const COMPLETE: usize = 0x3;
+
+// Mask to learn about the state. All other bits are the queue of waiters if
+// this is in the RUNNING state.
+const STATE_MASK: usize = 0x3;
+
+// Representation of a node in the linked list of waiters in the RUNNING state.
+struct Waiter {
+    thread: Option<SgxThread>,
+    signaled: AtomicBool,
+    next: * mut Waiter,
+}
+
+// Helper struct used to clean up after a closure call with a `Drop`
+// implementation to also run on panic.
+struct Finish {
+    panicked: bool,
+    me: &'static Once,
+}
+
+impl Once {
+    /// Creates a new `Once` value.
+    pub const fn new() -> Once {
+        Once {
+            state: AtomicUsize::new(INCOMPLETE),
+            marker: PhantomData,
+        }
+    }
+
+    /// Performs an initialization routine once and only once. The given closure
+    /// will be executed if this is the first time `call_once` has been called,
+    /// and otherwise the routine will *not* be invoked.
+    ///
+    /// This method will block the calling thread if another initialization
+    /// routine is currently running.
+    ///
+    /// When this function returns, it is guaranteed that some initialization
+    /// has run and completed (it may not be the closure specified). It is also
+    /// guaranteed that any memory writes performed by the executed closure can
+    /// be reliably observed by other threads at this point (there is a
+    /// happens-before relation between the closure and code executing after the
+    /// return).
+    ///
+    /// # Panics
+    ///
+    /// The closure `f` will only be executed once if this is called
+    /// concurrently amongst many threads. If that closure panics, however, then
+    /// it will *poison* this `Once` instance, causing all future invocations of
+    /// `call_once` to also panic.
+    pub fn call_once<F>(&'static self, f: F) where F: FnOnce() {
+
+        if self.state.load(Ordering::SeqCst) == COMPLETE {
+            return
+        }
+
+        let mut f = Some(f);
+        self.call_inner(false, &mut |_| f.take().unwrap()());
+    }
+
+    /// Performs the same function as [`call_once`] except ignores poisoning.
+    ///
+    /// If this `Once` has been poisoned (some initialization panicked) then
+    /// this function will continue to attempt to call initialization functions
+    /// until one of them doesn't panic.
+    ///
+    /// The closure `f` is yielded a [`OnceState`] structure which can be used to query the
+    /// state of this `Once` (whether initialization has previously panicked or
+    /// not).
+    ///
+    pub fn call_once_force<F>(&'static self, f: F) where F: FnOnce(&OnceState) {
+
+        if self.state.load(Ordering::SeqCst) == COMPLETE {
+            return
+        }
+
+        let mut f = Some(f);
+        self.call_inner(true, &mut |p| {
+            f.take().unwrap()(&OnceState { poisoned: p })
+        });
+    }
+
+    // This is a non-generic function to reduce the monomorphization cost of
+    // using `call_once` (this isn't exactly a trivial or small implementation).
+    //
+    // Additionally, this is tagged with `#[cold]` as it should indeed be cold
+    // and it helps let LLVM know that calls to this function should be off the
+    // fast path. Essentially, this should help generate more straight line code
+    // in LLVM.
+    //
+    // Finally, this takes an `FnMut` instead of a `FnOnce` because there's
+    // currently no way to take an `FnOnce` and call it via virtual dispatch
+    // without some allocation overhead.
+    #[cold]
+    fn call_inner(&'static self,
+                  ignore_poisoning: bool,
+                  mut init: &mut FnMut(bool)) {
+        let mut state = self.state.load(Ordering::SeqCst);
+
+        'outer: loop {
+            match state {
+                // If we're complete, then there's nothing to do, we just
+                // jettison out as we shouldn't run the closure.
+                COMPLETE => return,
+
+                // If we're poisoned and we're not in a mode to ignore
+                // poisoning, then we panic here to propagate the poison.
+                POISONED if !ignore_poisoning => {
+                    panic!("Once instance has previously been poisoned");
+                }
+
+                // Otherwise if we see a poisoned or otherwise incomplete state
+                // we will attempt to move ourselves into the RUNNING state. If
+                // we succeed, then the queue of waiters starts at null (all 0
+                // bits).
+                POISONED |
+                INCOMPLETE => {
+                    let old = self.state.compare_and_swap(state, RUNNING,
+                                                          Ordering::SeqCst);
+                    if old != state {
+                        state = old;
+                        continue
+                    }
+
+                    // Run the initialization routine, letting it know if we're
+                    // poisoned or not. The `Finish` struct is then dropped, and
+                    // the `Drop` implementation here is responsible for waking
+                    // up other waiters both in the normal return and panicking
+                    // case.
+                    let mut complete = Finish {
+                        panicked: true,
+                        me: self,
+                    };
+                    init(state == POISONED);
+                    complete.panicked = false;
+                    return
+                }
+
+                // All other values we find should correspond to the RUNNING
+                // state with an encoded waiter list in the more significant
+                // bits. We attempt to enqueue ourselves by moving us to the
+                // head of the list and bail out if we ever see a state that's
+                // not RUNNING.
+                _ => {
+                    assert!(state & STATE_MASK == RUNNING);
+                    let mut node = Waiter {
+                        thread: Some(thread::current()),
+                        signaled: AtomicBool::new(false),
+                        next: ptr::null_mut(),
+                    };
+                    let me = &mut node as *mut Waiter as usize;
+                    assert!(me & STATE_MASK == 0);
+
+                    while state & STATE_MASK == RUNNING {
+                        node.next = (state & !STATE_MASK) as *mut Waiter;
+                        let old = self.state.compare_and_swap(state,
+                                                              me | RUNNING,
+                                                              Ordering::SeqCst);
+                        if old != state {
+                            state = old;
+                            continue
+                        }
+
+                        // Once we've enqueued ourselves, wait in a loop.
+                        // Afterwards reload the state and continue with what we
+                        // were doing from before.
+                        while !node.signaled.load(Ordering::SeqCst) {
+                            thread::park();
+                        }
+                        state = self.state.load(Ordering::SeqCst);
+                        continue 'outer
+                    }
+                }
+            }
+        }
+    }
+}
+
+impl Drop for Finish {
+    fn drop(&mut self) {
+        // Swap out our state with however we finished. We should only ever see
+        // an old state which was RUNNING.
+        let queue = if self.panicked {
+            self.me.state.swap(POISONED, Ordering::SeqCst)
+        } else {
+            self.me.state.swap(COMPLETE, Ordering::SeqCst)
+        };
+        assert_eq!(queue & STATE_MASK, RUNNING);
+
+        // Decode the RUNNING to a list of waiters, then walk that entire list
+        // and wake them up. Note that it is crucial that after we store `true`
+        // in the node it can be free'd! As a result we load the `thread` to
+        // signal ahead of time and then unpark it after the store.
+        unsafe {
+            let mut queue = (queue & !STATE_MASK) as *mut Waiter;
+            while !queue.is_null() {
+                let next = (*queue).next;
+                let thread = (*queue).thread.take().unwrap();
+                (*queue).signaled.store(true, Ordering::SeqCst);
+                thread.unpark();
+                queue = next;
+            }
+        }
+    }
+}
+
+impl OnceState {
+    /// Returns whether the associated [`Once`] has been poisoned.
+    ///
+    /// Once an initalization routine for a [`Once`] has panicked it will forever
+    /// indicate to future forced initialization routines that it is poisoned.
+    ///
+    pub fn poisoned(&self) -> bool {
+        self.poisoned
+    }
+}
diff --git a/sgx_tstdc/src/poison.rs b/sgx_tstdc/src/poison.rs
new file mode 100644
index 0000000..c5c727d
--- /dev/null
+++ b/sgx_tstdc/src/poison.rs
@@ -0,0 +1,181 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use super::thread;
+use core::fmt;
+use core::convert;
+use core::sync::atomic::{AtomicBool, Ordering};
+
+pub struct Flag { failed: AtomicBool }
+
+// Note that the Ordering uses to access the `failed` field of `Flag` below is
+// always `Relaxed`, and that's because this isn't actually protecting any data,
+// it's just a flag whether we've panicked or not.
+//
+// The actual location that this matters is when a mutex is **locked** which is
+// where we have external synchronization ensuring that we see memory
+// reads/writes to this flag.
+//
+// As a result, if it matters, we should see the correct value for `failed` in
+// all cases.
+impl Flag {
+    pub const fn new() -> Flag {
+        Flag { failed: AtomicBool::new(false) }
+    }
+
+    #[inline]
+    pub fn borrow(&self) -> LockResult<Guard> {
+        let ret = Guard { panicking: thread::panicking() };
+        if self.get() {
+            Err(PoisonError::new(ret))
+        } else {
+            Ok(ret)
+        }
+    }
+
+    #[inline]
+    pub fn done(&self, guard: &Guard) {
+        if !guard.panicking && thread::panicking() {
+            self.failed.store(true, Ordering::Relaxed);
+        }
+    }
+
+    #[inline]
+    pub fn get(&self) -> bool {
+        self.failed.load(Ordering::Relaxed)
+    }
+}
+
+pub struct Guard {
+    panicking: bool,
+}
+
+/// A type of error which can be returned whenever a lock is acquired.
+///
+/// Both [`SgxMutex`]es and [`SgxRwLock`]s are poisoned whenever a thread fails while the lock
+/// is held. The precise semantics for when a lock is poisoned is documented on
+/// each lock, but once a lock is poisoned then all future acquisitions will
+/// return this error.
+pub struct PoisonError<T> {
+    guard: T,
+}
+
+/// An enumeration of possible errors which can occur while calling the
+/// [`try_lock`] method.
+pub enum TryLockError<T> {
+    /// The lock could not be acquired because another thread failed while holding
+    /// the lock.
+    Poisoned(PoisonError<T>),
+    /// The lock could not be acquired at this time because the operation would
+    /// otherwise block.
+    WouldBlock,
+}
+
+/// A type alias for the result of a lock method which can be poisoned.
+///
+/// The [`Ok`] variant of this result indicates that the primitive was not
+/// poisoned, and the `Guard` is contained within. The [`Err`] variant indicates
+/// that the primitive was poisoned. Note that the [`Err`] variant *also* carries
+/// the associated guard, and it can be acquired through the [`into_inner`]
+/// method.
+pub type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;
+
+/// A type alias for the result of a nonblocking locking method.
+///
+/// For more information, see [`LockResult`]. A `TryLockResult` doesn't
+/// necessarily hold the associated guard in the [`Err`] type as the lock may not
+/// have been acquired for other reasons.
+pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>;
+
+impl<T> fmt::Debug for PoisonError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "PoisonError { inner: .. }".fmt(f)
+    }
+}
+
+impl<T> fmt::Display for PoisonError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "poisoned lock: another task failed inside".fmt(f)
+    }
+}
+
+impl<T> PoisonError<T> {
+
+    /// Creates a `PoisonError`.
+    ///
+    /// This is generally created by methods like [`SgxMutex::lock`] or [`SgxRwLock::read`].
+    ///
+    pub fn new(guard: T) -> PoisonError<T> {
+        PoisonError { guard: guard }
+    }
+
+    /// Consumes this error indicating that a lock is poisoned, returning the
+    /// underlying guard to allow access regardless.
+    pub fn into_inner(self) -> T { self.guard }
+
+    /// Reaches into this error indicating that a lock is poisoned, returning a
+    /// reference to the underlying guard to allow access regardless.
+    pub fn get_ref(&self) -> &T { &self.guard }
+
+    /// Reaches into this error indicating that a lock is poisoned, returning a
+    /// mutable reference to the underlying guard to allow access regardless.
+    pub fn get_mut(&mut self) -> &mut T { &mut self.guard }
+}
+
+impl<T> convert::From<PoisonError<T>> for TryLockError<T> {
+    fn from(err: PoisonError<T>) -> TryLockError<T> {
+        TryLockError::Poisoned(err)
+    }
+}
+
+impl<T> fmt::Debug for TryLockError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f),
+            TryLockError::WouldBlock => "WouldBlock".fmt(f)
+        }
+    }
+}
+
+impl<T> fmt::Display for TryLockError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            TryLockError::Poisoned(..) => "poisoned lock: another task failed inside",
+            TryLockError::WouldBlock => "try_lock failed because the operation would block"
+        }.fmt(f)
+    }
+}
+
+pub fn map_result<T, U, F>(result: LockResult<T>, f: F)
+                           -> LockResult<U>
+                           where F: FnOnce(T) -> U {
+    match result {
+        Ok(t) => Ok(f(t)),
+        Err(PoisonError { guard }) => Err(PoisonError::new(f(guard)))
+    }
+}
diff --git a/sgx_tstdc/src/rwlock.rs b/sgx_tstdc/src/rwlock.rs
new file mode 100644
index 0000000..fa3fd6b
--- /dev/null
+++ b/sgx_tstdc/src/rwlock.rs
@@ -0,0 +1,661 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use sgx_types::*;
+use sgx_trts::panic::{UnwindSafe, RefUnwindSafe};
+use super::thread;
+use super::mutex::SgxThreadMutex;
+use super::condvar::SgxThreadCond;
+use super::spinlock::SgxThreadSpinlock;
+use super::poison::{self, TryLockError, TryLockResult, LockResult};
+use core::cell::UnsafeCell;
+use core::mem;
+use core::ptr;
+use core::ops::{Deref, DerefMut};
+use core::marker;
+#[cfg(not(feature = "use_std"))]
+use alloc::boxed::Box;
+
+struct RwLockInfo {
+    readers_num: u32,
+    writers_num: u32,
+    busy: u32,
+    writer_thread: sgx_thread_t,
+    cond: SgxThreadCond,
+    mutex: SgxThreadMutex,
+    spinlock: SgxThreadSpinlock,
+}
+
+impl RwLockInfo {
+
+    const fn new() -> Self {
+        RwLockInfo{
+            readers_num: 0,
+            writers_num: 0,
+            busy: 0,
+            writer_thread: SGX_THREAD_T_NULL,
+            cond: SgxThreadCond::new(),
+            mutex: SgxThreadMutex::new(),
+            spinlock: SgxThreadSpinlock::new(),
+        }
+    }
+
+    #[allow(dead_code)]
+    unsafe fn ref_busy(&mut self) -> SysError {
+
+        let ret: SysError;
+        self.spinlock.lock();
+        {
+            if self.busy == u32::max_value() {
+                ret = Err(EAGAIN);
+            } else {
+                self.busy += 1;
+                ret = Ok(());
+            }
+        }
+        self.spinlock.unlock();
+        ret
+    }
+
+    unsafe fn deref_busy(&mut self) -> SysError {
+
+        let ret: SysError;
+        self.spinlock.lock();
+        {
+            if self.busy == 0 {
+                ret = Err(EAGAIN);
+            } else {
+                self.busy -= 1;
+                ret = Ok(());
+            }
+        }
+        self.spinlock.unlock();
+        ret
+    }
+}
+
+/// An OS-based reader-writer lock.
+///
+/// This structure is entirely unsafe and serves as the lowest layer of a
+/// cross-platform binding of system rwlocks. It is recommended to use the
+/// safer types at the top level of this crate instead of this type.
+pub struct SgxThreadRwLock {
+    lock: UnsafeCell<RwLockInfo>,
+}
+
+unsafe impl Send for SgxThreadRwLock {}
+unsafe impl Sync for SgxThreadRwLock {}
+
+impl SgxThreadRwLock {
+
+    /// Creates a new reader-writer lock for use.
+    pub const fn new() -> Self {
+        SgxThreadRwLock { lock: UnsafeCell::new(RwLockInfo::new()) }
+    }
+    /// Acquires shared access to the underlying lock, blocking the current
+    /// thread to do so.
+    pub unsafe fn read(&self) -> SysError {
+
+        let rwlockinfo: &mut RwLockInfo = &mut *self.lock.get();
+
+        try!(rwlockinfo.ref_busy());
+
+        rwlockinfo.mutex.lock();
+        {
+            if rwlockinfo.writer_thread == thread::rsgx_thread_self() {
+
+                rwlockinfo.mutex.unlock();
+                rwlockinfo.deref_busy();
+                return Err(EDEADLK);
+            }
+
+            if rwlockinfo.readers_num == u32::max_value() {
+
+                rwlockinfo.mutex.unlock();
+                rwlockinfo.deref_busy();
+                return Err(EAGAIN);
+            }
+
+            while rwlockinfo.writers_num > 0 {
+                rwlockinfo.cond.wait(&rwlockinfo.mutex);
+            }
+
+            rwlockinfo.readers_num += 1;
+        }
+        rwlockinfo.mutex.unlock();
+
+        rwlockinfo.deref_busy();
+
+        Ok(())
+    }
+
+    /// Attempts to acquire shared access to this lock, returning whether it
+    /// succeeded or not.
+    ///
+    /// This function does not block the current thread.
+    pub unsafe fn try_read(&self) -> SysError {
+
+        let rwlockinfo: &mut RwLockInfo = &mut *self.lock.get();
+
+        try!(rwlockinfo.ref_busy());
+
+        rwlockinfo.mutex.lock();
+        {
+            let mut ret = Ok(());
+            if rwlockinfo.writer_thread == thread::rsgx_thread_self() {
+                ret = Err(EDEADLK);
+            }
+            else if rwlockinfo.readers_num == u32::max_value() {
+                ret = Err(EAGAIN);
+            }
+            else if rwlockinfo.writers_num > 0 {
+                ret = Err(EBUSY);
+            }
+
+            match ret {
+                Ok(_) => {},
+                Err(e) => {
+                    rwlockinfo.mutex.unlock();
+                    rwlockinfo.deref_busy();
+                    return Err(e);
+                }
+            }
+
+            rwlockinfo.readers_num += 1;
+        }
+        rwlockinfo.mutex.unlock();
+
+        rwlockinfo.deref_busy();
+
+        Ok(())
+    }
+
+    /// Acquires write access to the underlying lock, blocking the current thread
+    /// to do so.
+    pub unsafe fn write(&self) -> SysError {
+
+        let rwlockinfo: &mut RwLockInfo = &mut *self.lock.get();
+
+        try!(rwlockinfo.ref_busy());
+
+        rwlockinfo.mutex.lock();
+        {
+            if rwlockinfo.writer_thread == thread::rsgx_thread_self() {
+
+                rwlockinfo.mutex.unlock();
+                rwlockinfo.deref_busy();
+                return Err(EDEADLK);
+            }
+
+            if rwlockinfo.writers_num == u32::max_value() {
+
+                rwlockinfo.mutex.unlock();
+                rwlockinfo.deref_busy();
+                return Err(EAGAIN);
+            }
+
+            rwlockinfo.writers_num += 1;
+
+            while rwlockinfo.readers_num > 0 {
+                rwlockinfo.cond.wait(&rwlockinfo.mutex);
+            }
+
+            while rwlockinfo.writer_thread != SGX_THREAD_T_NULL {
+                rwlockinfo.cond.wait(&rwlockinfo.mutex);
+            }
+
+            rwlockinfo.writer_thread = thread::rsgx_thread_self();
+        }
+        rwlockinfo.mutex.unlock();
+
+        rwlockinfo.deref_busy();
+
+        Ok(())
+    }
+
+    /// Attempts to acquire exclusive access to this lock, returning whether it
+    /// succeeded or not.
+    ///
+    /// This function does not block the current thread.
+    pub unsafe fn try_write(&self) -> SysError {
+
+        let rwlockinfo: &mut RwLockInfo = &mut *self.lock.get();
+
+        try!(rwlockinfo.ref_busy());
+
+        rwlockinfo.mutex.lock();
+        {
+            let mut ret = Ok(());
+            if rwlockinfo.writer_thread == thread::rsgx_thread_self() {
+                ret = Err(EDEADLK);
+            }
+            else if rwlockinfo.writers_num == u32::max_value() {
+                ret = Err(EAGAIN);
+            }
+            else if rwlockinfo.readers_num > 0 || rwlockinfo.writer_thread != SGX_THREAD_T_NULL {
+                ret = Err(EBUSY);
+            }
+
+            match ret {
+                Ok(_) => {},
+                Err(e) => {
+                    rwlockinfo.mutex.unlock();
+                    rwlockinfo.deref_busy();
+                    return Err(e);
+                }
+            }
+
+            rwlockinfo.writers_num += 1;
+
+            rwlockinfo.writer_thread = thread::rsgx_thread_self();
+        }
+        rwlockinfo.mutex.unlock();
+
+        rwlockinfo.deref_busy();
+
+        Ok(())
+    }
+
+    /// Unlocks previously acquired shared access to this lock.
+    pub unsafe fn read_unlock(&self) -> SysError {
+        self.raw_unlock()
+    }
+
+    /// Unlocks previously acquired exclusive access to this lock.
+    pub unsafe fn write_unlock(&self) -> SysError {
+        self.raw_unlock()
+    }
+
+    unsafe fn raw_unlock(&self) -> SysError {
+
+        let rwlockinfo: &mut RwLockInfo = &mut *self.lock.get();
+
+        rwlockinfo.mutex.lock();
+        {
+            if rwlockinfo.readers_num > 0 {
+                rwlockinfo.readers_num -= 1;
+
+                if rwlockinfo.readers_num == 0 && rwlockinfo.writers_num > 0 {
+                    rwlockinfo.cond.broadcast();
+                }
+            } else {
+                if rwlockinfo.writer_thread != thread::rsgx_thread_self() {
+                    rwlockinfo.mutex.unlock();
+                    return Err(EPERM);
+                }
+
+                rwlockinfo.writers_num -= 1;
+                rwlockinfo.writer_thread = SGX_THREAD_T_NULL;
+
+                if rwlockinfo.busy > 0 {
+                    rwlockinfo.cond.broadcast();
+                }
+            }
+        }
+        rwlockinfo.mutex.unlock();
+
+        Ok(())
+    }
+    /// Destroys OS-related resources with this RWLock.
+    pub unsafe fn destroy(&self) -> SysError {
+
+        let rwlockinfo: &mut RwLockInfo = &mut *self.lock.get();
+
+        rwlockinfo.mutex.lock();
+        {
+            if rwlockinfo.readers_num > 0 ||
+               rwlockinfo.writers_num > 0 ||
+               rwlockinfo.busy > 0 {
+
+                rwlockinfo.spinlock.unlock();
+                return Err(EBUSY);
+            }
+
+            rwlockinfo.cond.destroy();
+            rwlockinfo.mutex.destroy();
+        }
+        rwlockinfo.spinlock.unlock();
+
+        Ok(())
+    }
+}
+
+/// A reader-writer lock
+///
+/// This type of lock allows a number of readers or at most one writer at any
+/// point in time. The write portion of this lock typically allows modification
+/// of the underlying data (exclusive access) and the read portion of this lock
+/// typically allows for read-only access (shared access).
+///
+/// The priority policy of the lock is dependent on the underlying operating
+/// system's implementation, and this type does not guarantee that any
+/// particular policy will be used.
+///
+/// The type parameter `T` represents the data that this lock protects. It is
+/// required that `T` satisfies `Send` to be shared across threads and `Sync` to
+/// allow concurrent access through readers. The RAII guards returned from the
+/// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
+/// to allow access to the contained of the lock.
+///
+/// # Poisoning
+///
+/// An `RwLock`, like `Mutex`, will become poisoned on a panic. Note, however,
+/// that an `RwLock` may only be poisoned if a panic occurs while it is locked
+/// exclusively (write mode). If a panic occurs in any reader, then the lock
+/// will not be poisoned.
+///
+pub struct SgxRwLock<T: ?Sized> {
+    inner: Box<SgxThreadRwLock>,
+    poison: poison::Flag,
+    data: UnsafeCell<T>,
+}
+
+unsafe impl<T: ?Sized + Send> Send for SgxRwLock<T> {}
+unsafe impl<T: ?Sized + Send> Sync for SgxRwLock<T> {}
+#[cfg(not(feature = "use_std"))]
+impl<T: ?Sized> UnwindSafe for SgxRwLock<T> {}
+#[cfg(not(feature = "use_std"))]
+impl<T: ?Sized> RefUnwindSafe for SgxRwLock<T> {}
+
+impl<T> SgxRwLock<T> {
+
+    /// Creates a new instance of an `RwLock<T>` which is unlocked.
+    pub fn new(t: T) -> SgxRwLock<T> {
+        SgxRwLock {
+            inner: Box::new(SgxThreadRwLock::new()),
+            poison: poison::Flag::new(),
+            data: UnsafeCell::new(t),
+        }
+    }
+}
+
+impl<T: ?Sized> SgxRwLock<T> {
+
+    /// Locks this rwlock with shared read access, blocking the current thread
+    /// until it can be acquired.
+    ///
+    /// The calling thread will be blocked until there are no more writers which
+    /// hold the lock. There may be other readers currently inside the lock when
+    /// this method returns. This method does not provide any guarantees with
+    /// respect to the ordering of whether contentious readers or writers will
+    /// acquire the lock first.
+    ///
+    /// Returns an RAII guard which will release this thread's shared access
+    /// once it is dropped.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the RwLock is poisoned. An RwLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock.
+    /// The failure will occur immediately after the lock has been acquired.
+    ///
+    /// # Panics
+    ///
+    /// This function might panic when called if the lock is already held by the current thread.
+    pub fn read(&self) -> LockResult<SgxRwLockReadGuard<T>> {
+        unsafe {
+            let ret = self.inner.read();
+            match ret {
+                Err(EAGAIN) => panic!("rwlock maximum reader count exceeded"),
+                Err(EDEADLK) => panic!("rwlock read lock would result in deadlock"),
+                _ => SgxRwLockReadGuard::new(self),
+            }
+        }
+    }
+
+    /// Attempts to acquire this rwlock with shared read access.
+    ///
+    /// If the access could not be granted at this time, then `Err` is returned.
+    /// Otherwise, an RAII guard is returned which will release the shared access
+    /// when it is dropped.
+    ///
+    /// This function does not block.
+    ///
+    /// This function does not provide any guarantees with respect to the ordering
+    /// of whether contentious readers or writers will acquire the lock first.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the RwLock is poisoned. An RwLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock. An
+    /// error will only be returned if the lock would have otherwise been
+    /// acquired.
+    pub fn try_read(&self) -> TryLockResult<SgxRwLockReadGuard<T>> {
+        unsafe {
+            let ret = self.inner.try_read();
+            match ret {
+                Ok(_) => Ok(SgxRwLockReadGuard::new(self)?),
+                Err(_) => Err(TryLockError::WouldBlock),
+            }
+        }
+    }
+
+    /// Locks this rwlock with exclusive write access, blocking the current
+    /// thread until it can be acquired.
+    ///
+    /// This function will not return while other writers or other readers
+    /// currently have access to the lock.
+    ///
+    /// Returns an RAII guard which will drop the write access of this rwlock
+    /// when dropped.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the RwLock is poisoned. An RwLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock.
+    /// An error will be returned when the lock is acquired.
+    ///
+    /// # Panics
+    ///
+    /// This function might panic when called if the lock is already held by the current thread.
+    pub fn write(&self) -> LockResult<SgxRwLockWriteGuard<T>> {
+        unsafe {
+            let ret = self.inner.write();
+            match ret {
+                Err(EAGAIN) => panic!("rwlock maximum writer count exceeded"),
+                Err(EDEADLK) => panic!("rwlock write lock would result in deadlock"),
+                _ => SgxRwLockWriteGuard::new(self),
+            }
+        }
+    }
+
+    /// Attempts to lock this rwlock with exclusive write access.
+    ///
+    /// If the lock could not be acquired at this time, then `Err` is returned.
+    /// Otherwise, an RAII guard is returned which will release the lock when
+    /// it is dropped.
+    ///
+    /// This function does not block.
+    ///
+    /// This function does not provide any guarantees with respect to the ordering
+    /// of whether contentious readers or writers will acquire the lock first.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the RwLock is poisoned. An RwLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock. An
+    /// error will only be returned if the lock would have otherwise been
+    /// acquired.
+    pub fn try_write(&self) -> TryLockResult<SgxRwLockWriteGuard<T>> {
+        unsafe {
+            let ret = self.inner.try_write();
+            match ret {
+                Ok(_) => Ok(SgxRwLockWriteGuard::new(self)?),
+                Err(_) => Err(TryLockError::WouldBlock),
+            }
+        }
+    }
+
+    /// Determines whether the lock is poisoned.
+    ///
+    /// If another thread is active, the lock can still become poisoned at any
+    /// time.  You should not trust a `false` value for program correctness
+    /// without additional synchronization.
+    #[inline]
+    pub fn is_poisoned(&self) -> bool {
+        self.poison.get()
+    }
+
+    /// Consumes this `RwLock`, returning the underlying data.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the RwLock is poisoned. An RwLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock. An
+    /// error will only be returned if the lock would have otherwise been
+    /// acquired.
+    pub fn into_inner(self) -> LockResult<T> where T: Sized {
+
+        unsafe {
+            let (inner, poison, data) = {
+                let SgxRwLock { ref inner, ref poison, ref data } = self;
+                (ptr::read(inner), ptr::read(poison), ptr::read(data))
+            };
+
+            mem::forget(self);
+            let _ = inner.destroy();
+            drop(inner);
+
+            poison::map_result(poison.borrow(), |_| data.into_inner())
+        }
+    }
+
+    /// Returns a mutable reference to the underlying data.
+    ///
+    /// Since this call borrows the `RwLock` mutably, no actual locking needs to
+    /// take place---the mutable borrow statically guarantees no locks exist.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the RwLock is poisoned. An RwLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock. An
+    /// error will only be returned if the lock would have otherwise been
+    /// acquired.
+    pub fn get_mut(&mut self) -> LockResult<&mut T> {
+
+        let data = unsafe { &mut *self.data.get() };
+        poison::map_result(self.poison.borrow(), |_| data)
+    }
+}
+
+unsafe impl<#[may_dangle] T: ?Sized> Drop for SgxRwLock<T> {
+    fn drop(&mut self) {
+        // IMPORTANT: This code needs to be kept in sync with `SgxRwLock::into_inner`.
+        unsafe {
+            let _ = self.inner.destroy();
+        }
+    }
+}
+
+impl<T: Default> Default for SgxRwLock<T> {
+    /// Creates a new `RwLock<T>`, with the `Default` value for T.
+    fn default() -> SgxRwLock<T> {
+        SgxRwLock::new(Default::default())
+    }
+}
+
+/// RAII structure used to release the shared read access of a lock when
+/// dropped.
+///
+/// This structure is created by the [`read`] and [`try_read`] methods on
+/// [`RwLock`].
+pub struct SgxRwLockReadGuard<'a, T: ?Sized + 'a> {
+    lock: &'a SgxRwLock<T>,
+}
+
+impl<'a, T: ?Sized> !marker::Send for SgxRwLockReadGuard<'a, T> {}
+
+/// RAII structure used to release the exclusive write access of a lock when
+/// dropped.
+///
+/// This structure is created by the [`write`] and [`try_write`] methods
+/// on [`RwLock`].
+pub struct SgxRwLockWriteGuard<'a, T: ?Sized + 'a> {
+    lock: &'a SgxRwLock<T>,
+    poison: poison::Guard,
+}
+
+impl<'a, T: ?Sized> !marker::Send for SgxRwLockWriteGuard<'a, T> {}
+
+impl<'rwlock, T: ?Sized> SgxRwLockReadGuard<'rwlock, T> {
+    unsafe fn new(lock: &'rwlock SgxRwLock<T>)
+                  -> LockResult<SgxRwLockReadGuard<'rwlock, T>> {
+        poison::map_result(lock.poison.borrow(), |_| {
+            SgxRwLockReadGuard {
+                lock: lock,
+            }
+        })
+    }
+}
+
+impl<'rwlock, T: ?Sized> SgxRwLockWriteGuard<'rwlock, T> {
+    unsafe fn new(lock: &'rwlock SgxRwLock<T>)
+                  -> LockResult<SgxRwLockWriteGuard<'rwlock, T>> {
+        poison::map_result(lock.poison.borrow(), |guard| {
+            SgxRwLockWriteGuard {
+                lock: lock,
+                poison: guard,
+            }
+        })
+    }
+}
+
+impl<'rwlock, T: ?Sized> Deref for SgxRwLockReadGuard<'rwlock, T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe { &*self.lock.data.get() }
+    }
+}
+
+impl<'rwlock, T: ?Sized> Deref for SgxRwLockWriteGuard<'rwlock, T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe { &*self.lock.data.get() }
+    }
+}
+
+impl<'rwlock, T: ?Sized> DerefMut for SgxRwLockWriteGuard<'rwlock, T> {
+    fn deref_mut(&mut self) -> &mut T {
+        unsafe { &mut *self.lock.data.get() }
+    }
+}
+
+impl<'a, T: ?Sized> Drop for SgxRwLockReadGuard<'a, T> {
+    fn drop(&mut self) {
+        unsafe { self.lock.inner.read_unlock(); }
+    }
+}
+
+impl<'a, T: ?Sized> Drop for SgxRwLockWriteGuard<'a, T> {
+    fn drop(&mut self) {
+        self.lock.poison.done(&self.poison);
+        unsafe { self.lock.inner.write_unlock(); }
+    }
+}
diff --git a/sgx_tstdc/src/spinlock.rs b/sgx_tstdc/src/spinlock.rs
new file mode 100644
index 0000000..5b9c138
--- /dev/null
+++ b/sgx_tstdc/src/spinlock.rs
@@ -0,0 +1,153 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use sgx_types::*;
+use core::marker;
+
+unsafe fn raw_lock(lock: &sgx_spinlock_t) -> * mut sgx_spinlock_t {
+    lock as * const _ as * mut _
+}
+
+///
+/// The rsgx_spin_lock function acquires a spin lock within the enclave.
+///
+/// # Description
+///
+/// rsgx_spin_lock modifies the value of the spin lock by using compiler atomic
+/// operations. If the lock is not available to be acquired, the thread will always
+/// wait on the lock until it can be acquired successfully.
+///
+/// # Parameters
+///
+/// **lock**
+///
+/// The trusted spin lock object to be acquired.
+///
+/// # Requirements
+///
+/// Library: libsgx_tstdc.a
+///
+unsafe fn rsgx_spin_lock(lock: &sgx_spinlock_t) {
+
+    sgx_spin_lock(raw_lock(lock));
+}
+
+///
+/// The rsgx_spin_unlock function releases a spin lock within the enclave.
+///
+/// # Description
+///
+/// rsgx_spin_unlock resets the value of the spin lock, regardless of its current
+/// state. This function simply assigns a value of zero to the lock, which indicates
+/// the lock is released.
+///
+/// # Parameters
+///
+/// **lock**
+///
+/// The trusted spin lock object to be released.
+///
+/// # Requirements
+///
+/// Library: libsgx_tstdc.a
+///
+unsafe fn rsgx_spin_unlock(lock: &sgx_spinlock_t) {
+
+    sgx_spin_unlock(raw_lock(lock));
+}
+
+pub struct SgxThreadSpinlock {
+    lock: sgx_spinlock_t,
+}
+
+unsafe impl Send for SgxThreadSpinlock {}
+unsafe impl Sync for SgxThreadSpinlock {}
+
+impl SgxThreadSpinlock {
+
+    pub const fn new() -> Self {
+        SgxThreadSpinlock{lock: SGX_SPINLOCK_INITIALIZER}
+    }
+
+    pub unsafe fn lock(&self) {
+        rsgx_spin_lock(&self.lock);
+    }
+
+    pub unsafe fn unlock(&self) {
+        rsgx_spin_unlock(&self.lock);
+    }
+}
+
+
+pub struct SgxSpinlock {
+    inner: SgxThreadSpinlock,
+}
+
+unsafe impl Send for SgxSpinlock {}
+unsafe impl Sync for SgxSpinlock {}
+
+impl SgxSpinlock {
+
+    pub fn new() -> Self {
+        SgxSpinlock{inner: SgxThreadSpinlock::new()}
+    }
+
+    pub fn lock(&self) -> SgxSpinlockGuard {
+        unsafe {
+            self.inner.lock();
+            SgxSpinlockGuard::new(self)
+        }
+
+    }
+}
+
+impl Default for SgxSpinlock {
+    fn default() -> SgxSpinlock {
+        SgxSpinlock::new()
+    }
+}
+
+pub struct SgxSpinlockGuard<'a> {
+    lock: &'a SgxSpinlock,
+}
+
+impl<'a> !marker::Send for SgxSpinlockGuard<'a> {}
+
+impl<'spinlock> SgxSpinlockGuard<'spinlock> {
+    unsafe fn new(lock: &'spinlock SgxSpinlock) -> Self {
+        SgxSpinlockGuard{lock: lock}
+    }
+}
+
+impl<'a> Drop for SgxSpinlockGuard<'a> {
+    fn drop(&mut self) {
+        unsafe {
+            self.lock.inner.unlock();
+        }
+    }
+}
diff --git a/sgx_tstdc/src/thread.rs b/sgx_tstdc/src/thread.rs
new file mode 100644
index 0000000..8aa5dab
--- /dev/null
+++ b/sgx_tstdc/src/thread.rs
@@ -0,0 +1,224 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//! Native threads.
+
+use sgx_types::*;
+use super::thread_info::*;
+use super::mutex::*;
+use super::condvar::*;
+#[cfg(not(feature = "use_std"))]
+use sgx_trts::panicking;
+#[cfg(not(feature = "use_std"))]
+use alloc::arc::Arc;
+#[cfg(feature = "use_std")]
+use core::sync::Arc;
+
+///
+/// The rsgx_thread_self function returns the unique thread identification.
+///
+/// # Description
+///
+/// The function is a simple wrap of get_thread_data() provided in the tRTS,
+/// which provides a trusted thread unique identifier.
+///
+/// # Requirements
+///
+/// Library: libsgx_tstdc.a
+///
+/// # Return value
+///
+/// The return value cannot be NULL and is always valid as long as it is invoked by a thread inside the enclave.
+///
+pub fn rsgx_thread_self() -> sgx_thread_t {
+
+    unsafe { sgx_thread_self() }
+}
+
+///
+/// The rsgx_thread_equal function compares two thread identifiers.
+///
+/// # Description
+///
+/// The function compares two thread identifiers provided by sgx_thread_
+/// self to determine if the IDs refer to the same trusted thread.
+///
+/// # Requirements
+///
+/// Library: libsgx_tstdc.a
+///
+/// # Return value
+///
+/// **true**
+///
+/// The two thread IDs are equal.
+///
+pub fn rsgx_thread_equal(a: sgx_thread_t, b: sgx_thread_t) -> bool {
+    a == b
+}
+
+/// Gets a handle to the thread that invokes it.
+pub fn current() -> SgxThread {
+    current_thread().expect("use of thread::current() need TCS policy is Bound")
+}
+
+/// Determines whether the current thread is unwinding because of panic.
+///
+/// A common use of this feature is to poison shared resources when writing
+/// unsafe code, by checking `panicking` when the `drop` is called.
+///
+/// This is usually not needed when writing safe code, as [`SgxMutex`es][SgxMutex]
+/// already poison themselves when a thread panics while holding the lock.
+///
+/// This can also be used in multithreaded applications, in order to send a
+/// message to other threads warning that a thread has panicked (e.g. for
+/// monitoring purposes).
+#[cfg(not(feature = "use_std"))]
+pub fn panicking() -> bool {
+    panicking::panicking()
+}
+
+#[cfg(feature = "use_std")]
+pub fn panicking() -> bool {
+    false
+}
+
+// Blocks unless or until the current thread's token is made available.
+///
+/// A call to `park` does not guarantee that the thread will remain parked
+/// forever, and callers should be prepared for this possibility.
+///
+/// # park and unpark
+///
+/// Every thread is equipped with some basic low-level blocking support, via the
+/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`]
+/// method. [`park`] blocks the current thread, which can then be resumed from
+/// another thread by calling the [`unpark`] method on the blocked thread's
+/// handle.
+///
+/// Conceptually, each [`Thread`] handle has an associated token, which is
+/// initially not present:
+///
+/// * The [`thread::park`][`park`] function blocks the current thread unless or
+///   until the token is available for its thread handle, at which point it
+///   atomically consumes the token. It may also return *spuriously*, without
+///   consuming the token.
+///
+/// * The [`unpark`] method on a [`Thread`] atomically makes the token available
+///   if it wasn't already.
+///
+/// In other words, each [`Thread`] acts a bit like a spinlock that can be
+/// locked and unlocked using `park` and `unpark`.
+///
+/// The API is typically used by acquiring a handle to the current thread,
+/// placing that handle in a shared data structure so that other threads can
+/// find it, and then `park`ing. When some desired condition is met, another
+/// thread calls [`unpark`] on the handle.
+///
+/// The motivation for this design is twofold:
+///
+/// * It avoids the need to allocate mutexes and condvars when building new
+///   synchronization primitives; the threads already provide basic
+///   blocking/signaling.
+///
+/// * It can be implemented very efficiently on many platforms.
+///
+pub fn park() {
+
+    let thread = current();
+    let mut guard = thread.inner.lock.lock().unwrap();
+    while !*guard {
+        guard = thread.inner.cvar.wait(guard).unwrap();
+    }
+    *guard = false;
+}
+
+/// A unique identifier for a running thread.
+///
+/// A `ThreadId` is an opaque object that has a unique value for each thread
+/// that creates one. `ThreadId`s are not guaranteed to correspond to a thread's
+/// system-designated identifier.
+#[derive(Eq, PartialEq, Copy, Clone)]
+pub struct SgxThreadId {
+    id: sgx_thread_t,
+}
+
+impl SgxThreadId {
+
+    // Generate a new unique thread ID.
+    pub fn new() -> Self {
+        SgxThreadId {
+            id: rsgx_thread_self(),
+        }
+    }
+}
+
+/// The internal representation of a `Thread` handle
+struct Inner {
+    id: SgxThreadId,
+    lock: SgxMutex<bool>,
+    cvar: SgxCond,
+}
+
+/// A handle to a thread.
+///
+#[derive(Clone)]
+pub struct SgxThread {
+    inner: Arc<Inner>,
+}
+
+impl SgxThread {
+
+    /// Used only internally to construct a thread object without spawning
+    pub fn new() -> Self {
+        SgxThread {
+            inner: Arc::new(Inner {
+                id: SgxThreadId::new(),
+                lock: SgxMutex::new(false),
+                cvar: SgxCond::new(),
+            })
+        }
+    }
+
+    /// Gets the thread's unique identifier.
+    pub fn id(&self) -> SgxThreadId {
+        self.inner.id
+    }
+
+    /// Atomically makes the handle's token available if it is not already.
+    ///
+    /// Every thread is equipped with some basic low-level blocking support, via
+    /// the [`park`][park] function and the `unpark()` method.
+    pub fn unpark(&self) {
+        let mut guard = self.inner.lock.lock().unwrap();
+        if !*guard {
+            *guard = true;
+            let _ = self.inner.cvar.signal();
+        }
+    }
+}
diff --git a/sgx_tstdc/src/thread_info.rs b/sgx_tstdc/src/thread_info.rs
new file mode 100644
index 0000000..f6e4299
--- /dev/null
+++ b/sgx_tstdc/src/thread_info.rs
@@ -0,0 +1,59 @@
+// Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//  * Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+//  * Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//  * Neither the name of Baidu, Inc., nor the names of its
+//    contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use super::thread::SgxThread;
+use sgx_trts::LocalKeyState;
+use core::cell::RefCell;
+
+struct SgxThreadInfo {
+    thread: SgxThread,
+}
+
+thread_local! { static THREAD_INFO: RefCell<Option<SgxThreadInfo>> = RefCell::new(None) }
+
+impl SgxThreadInfo {
+
+    fn with<R, F>(f: F) -> Option<R> where F: FnOnce(&mut SgxThreadInfo) -> R {
+        if THREAD_INFO.state() == LocalKeyState::Error {
+            return None
+        }
+
+        THREAD_INFO.with(move |c| {
+            if c.borrow().is_none() {
+                *c.borrow_mut() = Some(SgxThreadInfo {
+                    thread: SgxThread::new(),
+                })
+            }
+            Some(f(c.borrow_mut().as_mut().unwrap()))
+        })
+    }
+}
+
+pub fn current_thread() -> Option<SgxThread> {
+    SgxThreadInfo::with(|info| info.thread.clone())
+}
diff --git a/sgx_types/Cargo.toml b/sgx_types/Cargo.toml
index 8c12968..d4abdc4 100644
--- a/sgx_types/Cargo.toml
+++ b/sgx_types/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sgx_types"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Baidu"]
 
 [features]
diff --git a/sgx_types/src/error.rs b/sgx_types/src/error.rs
index fb0e04c..81b2a51 100644
--- a/sgx_types/src/error.rs
+++ b/sgx_types/src/error.rs
@@ -85,6 +85,18 @@
         SGX_ERROR_MC_USED_UP                = 0x0000400e,   /* Monotonic counters are used out */
         SGX_ERROR_MC_OVER_QUOTA             = 0x0000400f,   /* Monotonic counters exceeds quota limitation */
         SGX_ERROR_KDF_MISMATCH              = 0x00004011,   /* Key derivation function doesn't match during key exchange */
+        SGX_ERROR_UNRECOGNIZED_PLATFORM     = 0x00004012,   /* EPID Provisioning failed due to platform not recognized by backend server*/
+
+        /* SGX errors are only used in the file API when there is no appropriate EXXX (EINVAL, EIO etc.) error code */
+        SGX_ERROR_FILE_BAD_STATUS               = 0x00007001,	/* The file is in bad status, run sgx_clearerr to try and fix it */
+        SGX_ERROR_FILE_NO_KEY_ID                = 0x00007002,	/* The Key ID field is all zeros, can't re-generate the encryption key */
+        SGX_ERROR_FILE_NAME_MISMATCH            = 0x00007003,	/* The current file name is different then the original file name (not allowed, substitution attack) */
+        SGX_ERROR_FILE_NOT_SGX_FILE             = 0x00007004,   /* The file is not an SGX file */
+        SGX_ERROR_FILE_CANT_OPEN_RECOVERY_FILE  = 0x00007005,	/* A recovery file can't be opened, so flush operation can't continue (only used when no EXXX is returned)  */
+        SGX_ERROR_FILE_CANT_WRITE_RECOVERY_FILE = 0x00007006,   /* A recovery file can't be written, so flush operation can't continue (only used when no EXXX is returned)  */
+        SGX_ERROR_FILE_RECOVERY_NEEDED          = 0x00007007,	/* When openeing the file, recovery is needed, but the recovery process failed */
+        SGX_ERROR_FILE_FLUSH_FAILED             = 0x00007008,	/* fflush operation (to disk) failed (only used when no EXXX is returned) */
+        SGX_ERROR_FILE_CLOSE_FAILED             = 0x00007009,	/* fclose operation (to disk) failed (only used when no EXXX is returned) */
     }
 }
 
diff --git a/sgx_types/src/function.rs b/sgx_types/src/function.rs
index f07476a..0c92757 100644
--- a/sgx_types/src/function.rs
+++ b/sgx_types/src/function.rs
@@ -48,14 +48,14 @@
     //
     pub fn sgx_thread_mutex_init(mutex: * mut sgx_thread_mutex_t, unused: * const sgx_thread_mutexattr_t) -> ::int32_t;
     pub fn sgx_thread_mutex_destroy(mutex: * mut sgx_thread_mutex_t) -> ::int32_t;
-    
+
     pub fn sgx_thread_mutex_lock(mutex: * mut sgx_thread_mutex_t) -> ::int32_t;
     pub fn sgx_thread_mutex_trylock(mutex: * mut sgx_thread_mutex_t) -> ::int32_t;
     pub fn sgx_thread_mutex_unlock(mutex: * mut sgx_thread_mutex_t) -> ::int32_t;
-    
+
     pub fn sgx_thread_cond_init(cond: * mut sgx_thread_cond_t, unused: * const sgx_thread_condattr_t) -> ::int32_t;
     pub fn sgx_thread_cond_destroy(cond: * mut sgx_thread_cond_t) -> ::int32_t;
-    
+
     pub fn sgx_thread_cond_wait(cond: * mut sgx_thread_cond_t, mutex: * mut sgx_thread_mutex_t) -> ::int32_t;
     pub fn sgx_thread_cond_signal(cond: * mut sgx_thread_cond_t) -> ::int32_t;
     pub fn sgx_thread_cond_broadcast(cond: * mut sgx_thread_cond_t) -> ::int32_t;
@@ -73,13 +73,13 @@
     //
     pub fn sgx_dh_init_session(role: sgx_dh_session_role_t, session: * mut sgx_dh_session_t) -> sgx_status_t;
 
-    pub fn sgx_dh_responder_gen_msg1(msg1: * mut sgx_dh_msg1_t, 
+    pub fn sgx_dh_responder_gen_msg1(msg1: * mut sgx_dh_msg1_t,
                                      dh_session: * mut sgx_dh_session_t) -> sgx_status_t;
 
-    pub fn sgx_dh_initiator_proc_msg1(msg1: * const sgx_dh_msg1_t, 
-                                      msg2: * mut sgx_dh_msg2_t, 
+    pub fn sgx_dh_initiator_proc_msg1(msg1: * const sgx_dh_msg1_t,
+                                      msg2: * mut sgx_dh_msg2_t,
                                       dh_session: * mut sgx_dh_session_t) -> sgx_status_t;
-    
+
     pub fn sgx_dh_responder_proc_msg2(msg2: * const sgx_dh_msg2_t,
                                       msg3: * mut sgx_dh_msg3_t,
                                       dh_session: * mut sgx_dh_session_t,
@@ -97,6 +97,8 @@
     pub fn sgx_create_pse_session() -> sgx_status_t;
     pub fn sgx_close_pse_session() -> sgx_status_t;
     pub fn sgx_get_ps_sec_prop(security_property: * mut sgx_ps_sec_prop_desc_t) -> sgx_status_t;
+    /* intel sgx sdk 1.8 */
+    pub fn sgx_get_ps_sec_prop_ex(security_property: * mut sgx_ps_sec_prop_desc_ex_t) -> sgx_status_t;
     pub fn sgx_get_trusted_time(current_time: * mut sgx_time_t, time_source_nonce: * mut sgx_time_source_nonce_t) -> sgx_status_t;
 
     pub fn sgx_create_monotonic_counter_ex(owner_policy: ::uint16_t,
@@ -109,7 +111,7 @@
     pub fn sgx_increment_monotonic_counter(counter_uuid: * const sgx_mc_uuid_t, counter_value: * mut ::uint32_t) -> sgx_status_t;
     pub fn sgx_read_monotonic_counter(counter_uuid: * const sgx_mc_uuid_t, counter_value: * mut ::uint32_t) -> sgx_status_t;
 
-    
+
     //
     // sgx_tseal.h
     //
@@ -153,16 +155,16 @@
                              sealed_data_size: ::uint32_t,
                              p_sealed_data: * mut sgx_sealed_data_t) -> sgx_status_t;
 
-    pub fn sgx_unmac_aadata(p_sealed_data: * const sgx_sealed_data_t, 
-                            p_additional_MACtext: * mut ::uint8_t, 
+    pub fn sgx_unmac_aadata(p_sealed_data: * const sgx_sealed_data_t,
+                            p_additional_MACtext: * mut ::uint8_t,
                             p_additional_MACtext_length: * mut ::uint32_t) -> sgx_status_t;
 
 
     //
     // sgx_utils.h
     //
-    pub fn sgx_create_report(target_info : * const sgx_target_info_t, 
-                             report_data: * const sgx_report_data_t, 
+    pub fn sgx_create_report(target_info : * const sgx_target_info_t,
+                             report_data: * const sgx_report_data_t,
                              report: * mut sgx_report_t) -> sgx_status_t;
 
     pub fn sgx_verify_report(report: * const sgx_report_t) -> sgx_status_t;
@@ -181,7 +183,7 @@
     pub fn sgx_sha256_update(p_src: * const ::uint8_t, src_len: ::uint32_t, sha_handle: sgx_sha_state_handle_t) -> sgx_status_t;
     pub fn sgx_sha256_get_hash(sha_handle: sgx_sha_state_handle_t, p_hash: * mut sgx_sha256_hash_t) -> sgx_status_t;
     pub fn sgx_sha256_close(sha_handle: sgx_sha_state_handle_t) -> sgx_status_t;
-    
+
     pub fn sgx_rijndael128GCM_encrypt(p_key: * const sgx_aes_gcm_128bit_key_t,
                                       p_src: * const ::uint8_t,
                                       src_len: ::uint32_t,
@@ -207,7 +209,7 @@
     pub fn sgx_cmac128_update(p_src: * const ::uint8_t, src_len: ::uint32_t, cmac_handle: sgx_cmac_state_handle_t) -> sgx_status_t;
     pub fn sgx_cmac128_final(cmac_handle: sgx_cmac_state_handle_t, p_hash: * mut sgx_cmac_128bit_tag_t) -> sgx_status_t;
     pub fn sgx_cmac128_close(cmac_handle: sgx_cmac_state_handle_t) -> sgx_status_t;
-    
+
     pub fn sgx_aes_ctr_encrypt(p_key: * const sgx_aes_ctr_128bit_key_t,
                                p_src: * const ::uint8_t,
                                src_len: ::uint32_t,
@@ -232,6 +234,11 @@
                                            p_public_ga: * mut sgx_ec256_public_t,
                                            p_shared_key: * mut sgx_ec256_dh_shared_t,
                                            ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t;
+    /* intel sgx sdk 1.8 */
+    pub fn sgx_ecc256_compute_shared_dhkey512(p_private_b: * mut sgx_ec256_private_t,
+                                              p_public_ga: * mut sgx_ec256_public_t,
+                                              p_shared_key: * mut sgx_ec256_dh_shared512_t,
+                                              ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t;
 
     pub fn sgx_ecdsa_sign(p_data: * const ::uint8_t,
                           data_size: ::uint32_t,
@@ -239,11 +246,11 @@
                           p_signature: * mut sgx_ec256_signature_t,
                           ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t;
 
-    pub fn sgx_ecdsa_verify(p_data: * const ::uint8_t, 
-                            data_size: :: uint32_t, 
-                            p_public: * const sgx_ec256_public_t, 
+    pub fn sgx_ecdsa_verify(p_data: * const ::uint8_t,
+                            data_size: :: uint32_t,
+                            p_public: * const sgx_ec256_public_t,
                             p_signature: * mut sgx_ec256_signature_t,
-                            p_result: * mut ::uint8_t, 
+                            p_result: * mut ::uint8_t,
                             ecc_handle: sgx_ecc_state_handle_t) -> sgx_status_t;
 }
 
@@ -284,9 +291,9 @@
     //
     // sgx_trts_exception.h
     //
-    pub fn sgx_register_exception_handler(is_first_handler: ::uint32_t, 
+    pub fn sgx_register_exception_handler(is_first_handler: ::uint32_t,
                                           exception_handler: sgx_exception_handler_t) -> * const ::c_void;
-                                          
+
     pub fn sgx_unregister_exception_handler(handler: * const ::c_void) -> ::uint32_t;
 
     //
@@ -294,7 +301,7 @@
     //
     pub fn sgx_ocalloc(size: ::size_t) -> * mut ::c_void;
     pub fn sgx_sgx_ocfree();
- 
+
     //
     // trts_pic.S
     //
@@ -330,9 +337,9 @@
     pub fn sgx_get_whitelist_size(p_whitelist_size: * mut ::uint32_t) -> sgx_status_t;
     pub fn sgx_get_whitelist(p_whitelist: * mut ::uint8_t, whitelist_size: ::uint32_t) -> sgx_status_t;
     pub fn sgx_get_extended_epid_group_id(p_extended_epid_group_id: * mut ::uint32_t) -> sgx_status_t;
-    
-    pub fn sgx_report_attestation_status(p_platform_info: * const sgx_platform_info_t, 
-                                         attestation_status: i32, 
+
+    pub fn sgx_report_attestation_status(p_platform_info: * const sgx_platform_info_t,
+                                         attestation_status: i32,
                                          p_update_info: * mut sgx_update_info_bit_t) -> sgx_status_t;
 }
 
@@ -374,4 +381,4 @@
                               misc_attr: * mut sgx_misc_attribute_t) -> sgx_status_t;
 
     pub fn sgx_destroy_enclave(enclave_id: sgx_enclave_id_t);
-}
\ No newline at end of file
+}
diff --git a/sgx_types/src/lib.rs b/sgx_types/src/lib.rs
index 1067737..e6d0366 100644
--- a/sgx_types/src/lib.rs
+++ b/sgx_types/src/lib.rs
@@ -30,12 +30,11 @@
 #![crate_type = "rlib"]
 
 #![cfg_attr(not(feature = "use_std"), no_std)]
-#![cfg_attr(not(feature = "use_std"), feature(lang_items, const_fn))]
 
 #![allow(non_camel_case_types)]
 #![allow(non_snake_case)]
 #![allow(improper_ctypes)]
-#![allow(unused_variables)]
+#![allow(unused_macros)]
 
 #[cfg(feature = "use_std")]
 extern crate std as core;
@@ -81,14 +80,13 @@
 pub type ssize_t = isize;
 
 
-pub mod types;
+mod types;
 pub use self::types::*;
 
-pub mod error;
+mod error;
 pub use self::error::*;
 
-pub mod function;
+mod function;
 pub use self::function::*;
 
-pub mod oom;
-pub use self::oom::*;
\ No newline at end of file
+pub mod marker;
diff --git a/sgx_types/src/macros.rs b/sgx_types/src/macros.rs
index 51e1fb3..b8bd63e 100644
--- a/sgx_types/src/macros.rs
+++ b/sgx_types/src/macros.rs
@@ -32,6 +32,7 @@
 pub use core::ptr;
 pub use core::mem::transmute;
 
+#[macro_export]
 macro_rules! cfg_if {
     ($(
         if #[cfg($($meta:meta),*)] { $($it:item)* }
@@ -46,6 +47,7 @@
     }
 }
 
+#[macro_export]
 macro_rules! __cfg_if_items {
     (($($not:meta,)*) ; ) => {};
     (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
@@ -54,6 +56,7 @@
     }
 }
 
+#[macro_export]
 macro_rules! __cfg_if_apply {
     ($m:meta, $($it:item)*) => {
         $(#[$m] $it)*
@@ -64,7 +67,6 @@
     ($i:item) => ($i)
 }
 
-
 macro_rules! impl_copy_clone{
     ($($(#[$attr:meta])* pub struct $i:ident { $($field:tt)* })*) => ($(
         __item! {
@@ -79,7 +81,6 @@
     )*)
 }
 
-#[macro_export]
 macro_rules! impl_struct {
     ($($(#[$attr:meta])* pub struct $i:ident { $(pub $name:ident: $field:ty,)* })*) => ($(
         __item! {
@@ -96,61 +97,69 @@
                 $i{$($name: Default::default(),)*}
             }
         }
+        unsafe impl ContiguousMemory for $i {}
     )*)
 }
 
 macro_rules! impl_struct_default {
-	($($t:ty, $size:expr;)*) => {$(
-		impl Default for $t {
-			fn default() -> $t {
-				unsafe{::macros::transmute([0u8; $size])}
-			}
-		}
-	)*}
+    ($($t:ty, $size:expr;)*) => {$(
+        impl Default for $t {
+            fn default() -> $t {
+                unsafe{::macros::transmute([0u8; $size])}
+            }
+        }
+    )*}
 }
 
 macro_rules! impl_struct_clone {
-	($($t:ty;)*) => {$(
-		impl Clone for $t {
-			fn clone(&self) -> $t {
-				unsafe{::macros::ptr::read(self)}
-			}
-		}
-	)*}
+    ($($t:ty;)*) => {$(
+        impl Clone for $t {
+            fn clone(&self) -> $t {
+                unsafe{::macros::ptr::read(self)}
+            }
+        }
+    )*}
+}
+
+macro_rules! impl_struct_ContiguousMemory {
+
+    ($($t:ty;)*) => {$(
+        unsafe impl ContiguousMemory for $t {}
+    )*}
 }
 
 #[macro_export]
 macro_rules! impl_enum {
-	(
+    (
         #[repr($repr:ident)]
         #[derive($($derive:meta),*)]
-		pub enum $name:ident {
+        pub enum $name:ident {
             $key:ident = $val:expr,
-			$($keys:ident = $vals:expr,)*
-		}
-	) => (
+            $($keys:ident = $vals:expr,)*
+        }
+    ) => (
         #[repr(C)]
         #[repr($repr)]
-		#[derive($($derive),*)]	
-		pub enum $name {
+        #[derive($($derive),*)]
+        pub enum $name {
             $key = $val,
-			$($keys = $vals,)*
-		}
+            $($keys = $vals,)*
+        }
 
         impl Default for $name {
-			fn default() -> $name {
-				 $name::$key
-			}
-		}
+            fn default() -> $name {
+                 $name::$key
+            }
+        }
 
-		impl $name {
-			pub fn from_repr(v: $repr) -> Option<Self> {
-				match v {
+        impl $name {
+            pub fn from_repr(v: $repr) -> Option<Self> {
+                match v {
                     $val => Some($name::$key),
-					$($vals => Some($name::$keys),)*
-					_ => None,
-				}
-			}
+                    $($vals => Some($name::$keys),)*
+                    _ => None,
+                }
+            }
 
             pub fn from_key(self) -> $repr {
                 match self {
@@ -158,6 +167,7 @@
                     $($name::$keys => $vals,)*
                 }
             }
-		}
-	)
+        }
+    )
 }
+
diff --git a/sgx_types/src/marker.rs b/sgx_types/src/marker.rs
new file mode 100644
index 0000000..06c84ab
--- /dev/null
+++ b/sgx_types/src/marker.rs
@@ -0,0 +1,78 @@
+
+macro_rules! impl_marker_for {
+    ($traitname:ident, $($ty:ty)*) => {
+        $(
+            impl $traitname for $ty { }
+        )*
+    }
+}
+
+macro_rules! impl_marker_for_array {
+    ($traitname:ident, $($N:expr)+) => {
+        $(
+            impl<T: $traitname> $traitname for [T; $N] { }
+        )+
+    }
+}
+
+macro_rules! impl_unsafe_marker_for {
+    ($traitname:ident, $($ty:ty)*) => {
+        $(
+            unsafe impl $traitname for $ty { }
+        )*
+    }
+}
+
+macro_rules! impl_unsafe_marker_for_array {
+    ($traitname:ident, $($N:expr)+) => {
+        $(
+            unsafe impl<T: $traitname> $traitname for [T; $N] { }
+        )+
+    }
+}
+
+/// Trait implemented for types that can be compared for equality using their bytewise representation
+/// A type can implement BytewiseEquality if all of its components implement BytewiseEquality.
+pub trait BytewiseEquality { }
+
+
+impl_marker_for!(BytewiseEquality,
+                 u8 i8 u16 i16 u32 i32 u64 i64 usize isize char bool);
+
+impl<T: BytewiseEquality> BytewiseEquality for [T] { }
+
+impl_marker_for_array! {BytewiseEquality,
+     0  1  2  3  4  5  6  7  8  9
+    10 11 12 13 14 15 16 17 18 19
+    20 21 22 23 24 25 26 27 28 29
+    30 31 32 33 34 35 36 37 38 39
+    40 41 42 43 44 45 46 47 48 49
+    50 51 52 53 54 55 56 57 58 59
+    60 61 62 63 64
+}
+
+
+pub unsafe trait ContiguousMemory { }
+
+impl_unsafe_marker_for!(ContiguousMemory,
+                 u8 i8 u16 i16 u32 i32 u64 i64 usize isize char bool);
+
+unsafe impl<T: ContiguousMemory> ContiguousMemory for [T] { }
+
+
+impl_unsafe_marker_for_array! {ContiguousMemory,
+     0  1  2  3  4  5  6  7  8  9
+    10 11 12 13 14 15 16 17 18 19
+    20 21 22 23 24 25 26 27 28 29
+    30 31 32 33 34 35 36 37 38 39
+    40 41 42 43 44 45 46 47 48 49
+    50 51 52 53 54 55 56 57 58 59
+    60 61 62 63 64
+}
+
+/*
+impl<T: ?Sized> !ContiguousMemory for * const T {}
+impl<T: ?Sized> !ContiguousMemory for * mut T {}
+impl<'a, T: 'a + ?Sized> !ContiguousMemory for &'a T {}
+impl<'a, T: 'a + ?Sized> !ContiguousMemory for &'a mut T {}
+*/
diff --git a/sgx_types/src/types.rs b/sgx_types/src/types.rs
index 97696c6..5db8145 100644
--- a/sgx_types/src/types.rs
+++ b/sgx_types/src/types.rs
@@ -27,6 +27,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 use error::*;
+use super::marker::ContiguousMemory;
 
 //
 // sgx_attributes.h
@@ -35,17 +36,17 @@
 
 pub type sgx_misc_select_t = ::uint32_t;
 
-// Enclave Flags Bit Masks 
-pub const SGX_FLAGS_INITTED: ::uint64_t         = 0x0000000000000001;    //If set, then the enclave is initialized 
+// Enclave Flags Bit Masks
+pub const SGX_FLAGS_INITTED: ::uint64_t         = 0x0000000000000001;    //If set, then the enclave is initialized
 pub const SGX_FLAGS_DEBUG: ::uint64_t           = 0x0000000000000002;    //If set, then the enclave is debug
 pub const SGX_FLAGS_MODE64BIT: ::uint64_t       = 0x0000000000000004;    //If set, then the enclave is 64 bit
 pub const SGX_FLAGS_PROVISION_KEY: ::uint64_t   = 0x0000000000000010;    //If set, then the enclave has access to provision key
-pub const SGX_FLAGS_LICENSE_KEY: ::uint64_t     = 0x0000000000000020;    //If set, then the enclave has access to License key
-pub const SGX_FLAGS_RESERVED: ::uint64_t        = (!(SGX_FLAGS_INITTED 
-                                                | SGX_FLAGS_DEBUG 
-                                                | SGX_FLAGS_MODE64BIT 
-                                                | SGX_FLAGS_PROVISION_KEY 
-                                                | SGX_FLAGS_LICENSE_KEY));
+pub const SGX_FLAGS_EINITTOKEN_KEY: ::uint64_t  = 0x0000000000000020;    //If set, then the enclave has access to EINITTOKEN key
+pub const SGX_FLAGS_RESERVED: ::uint64_t        = (!(SGX_FLAGS_INITTED
+                                                | SGX_FLAGS_DEBUG
+                                                | SGX_FLAGS_MODE64BIT
+                                                | SGX_FLAGS_PROVISION_KEY
+                                                | SGX_FLAGS_EINITTOKEN_KEY));
 
 // XSAVE Feature Request Mask
 pub const SGX_XFRM_LEGACY: ::uint64_t           = 0x0000000000000003;  //Legacy XFRM
@@ -59,12 +60,12 @@
     pub struct sgx_attributes_t {
         pub flags: ::uint64_t,
         pub xfrm: ::uint64_t,
-    }  
+    }
 
     pub struct sgx_misc_attribute_t {
         pub secs_attr: sgx_attributes_t,
         pub misc_select: sgx_misc_select_t,
-    } 
+    }
 }
 
 //
@@ -78,9 +79,9 @@
 
     #[repr(packed)]
     pub struct sgx_dh_msg1_t {
-        pub g_a: sgx_ec256_public_t, 
+        pub g_a: sgx_ec256_public_t,
         pub target: sgx_target_info_t,
-    } 
+    }
 }
 
 impl_copy_clone! {
@@ -114,7 +115,7 @@
         pub mr_enclave: sgx_measurement_t,
         pub reserved_2: [::uint8_t; 32],
         pub mr_signer: sgx_measurement_t,
-        pub reserved_3: [::uint8_t; 96], 
+        pub reserved_3: [::uint8_t; 96],
         pub isv_prod_id: ::sgx_prod_id_t,
         pub isv_svn: ::sgx_isv_svn_t,
     }
@@ -133,6 +134,13 @@
     sgx_dh_session_t, 200;
 }
 
+impl_struct_ContiguousMemory! {
+    sgx_dh_msg2_t;
+    sgx_dh_msg3_body_t;
+    sgx_dh_msg3_t;
+    sgx_dh_session_enclave_identity_t;
+    sgx_dh_session_t;
+}
 
 impl_enum! {
 
@@ -225,6 +233,10 @@
     sgx_key_request_t, 512;
 }
 
+impl_struct_ContiguousMemory! {
+    sgx_key_request_t;
+}
+
 //
 // sgx_key_exchange.h
 //
@@ -277,6 +289,10 @@
     sgx_ra_msg3_t, 336;
 }
 
+impl_struct_ContiguousMemory! {
+    sgx_ra_msg3_t;
+}
+
 //
 // sgx_quote.h
 //
@@ -347,6 +363,11 @@
     sgx_platform_info_t, 101;
 }
 
+impl_struct_ContiguousMemory! {
+    sgx_quote_t;
+    sgx_platform_info_t;
+}
+
 //
 // sgx_report.h
 //
@@ -367,7 +388,7 @@
 pub type sgx_mac_t = [::uint8_t; SGX_MAC_SIZE];
 
 impl_copy_clone! {
-    
+
     pub struct sgx_report_data_t {
         pub d: [::uint8_t; SGX_REPORT_DATA_SIZE],
     }
@@ -377,6 +398,10 @@
     sgx_report_data_t, 64;
 }
 
+impl_struct_ContiguousMemory! {
+    sgx_report_data_t;
+}
+
 pub type sgx_prod_id_t = ::uint16_t;
 
 pub const SGX_TARGET_INFO_RESERVED1_BYTES: ::size_t = 4;
@@ -420,6 +445,12 @@
     sgx_report_t, 432;
 }
 
+impl_struct_ContiguousMemory! {
+    sgx_target_info_t;
+    sgx_report_body_t;
+    sgx_report_t;
+}
+
 //
 // sgx_spinlock.h
 //
@@ -455,10 +486,23 @@
     pub struct sgx_ps_sec_prop_desc_t {
         pub sgx_ps_sec_prop_desc: [::uint8_t; 256],
     }
+
+    pub struct sgx_ps_sec_prop_desc_ex_t {
+        pub ps_sec_prop_desc: sgx_ps_sec_prop_desc_t,
+        pub pse_mrsigner: sgx_measurement_t,
+        pub pse_prod_id: sgx_prod_id_t,
+        pub pse_isv_svn: sgx_isv_svn_t,
+    }
 }
 
 impl_struct_default! {
     sgx_ps_sec_prop_desc_t, 256;
+    sgx_ps_sec_prop_desc_ex_t, 292;
+}
+
+impl_struct_ContiguousMemory! {
+    sgx_ps_sec_prop_desc_t;
+    sgx_ps_sec_prop_desc_ex_t;
 }
 
 pub const SGX_MC_POLICY_SIGNER: ::uint16_t   = 0x01;
@@ -485,6 +529,11 @@
         pub s: [::uint8_t; SGX_ECP256_KEY_SIZE],
     }
 
+    pub struct sgx_ec256_dh_shared512_t {
+        pub x: [::uint8_t; SGX_ECP256_KEY_SIZE],
+        pub y: [::uint8_t; SGX_ECP256_KEY_SIZE],
+    }
+
     pub struct sgx_ec256_private_t {
         pub r: [::uint8_t; SGX_ECP256_KEY_SIZE],
     }
@@ -557,11 +606,11 @@
     }
 }
 
-pub const THREAD_SELF_ADDR:         ::size_t = 0;
-pub const THREAD_LAST_SP_ADDR:      ::size_t = (SE_WORDSIZE * 1);
-pub const THREAD_STACK_BASE_ADDR:   ::size_t = (SE_WORDSIZE * 2);
-pub const THREAD_STACK_LIMIT_ADDR:  ::size_t = (SE_WORDSIZE * 3);
-pub const THREAD_STACK_SSA_GPR:     ::size_t = (SE_WORDSIZE * 4);
+//pub const THREAD_SELF_ADDR:         ::size_t = 0;
+//pub const THREAD_LAST_SP_ADDR:      ::size_t = (SE_WORDSIZE * 1);
+//pub const THREAD_STACK_BASE_ADDR:   ::size_t = (SE_WORDSIZE * 2);
+//pub const THREAD_STACK_LIMIT_ADDR:  ::size_t = (SE_WORDSIZE * 3);
+//pub const THREAD_STACK_SSA_GPR:     ::size_t = (SE_WORDSIZE * 4);
 
 pub struct sgx_thread_queue_t {
     pub m_first: sgx_thread_t,
@@ -649,7 +698,7 @@
 pub const EXCEPTION_CONTINUE_EXECUTION: ::uint32_t   = 0xFFFFFFFF;
 
 impl_enum! {
-    
+
     #[repr(u32)]
     #[derive(Copy, Clone, PartialEq, Eq)]
     pub enum sgx_exception_vector_t {
@@ -665,7 +714,7 @@
 }
 
 impl_enum!{
-    
+
     #[repr(u32)]
     #[derive(Copy, Clone, PartialEq, Eq)]
     pub enum sgx_exception_type_t {
@@ -828,4 +877,4 @@
 //    } else {
 //        pub const SGX_DEBUG_FLAG: ::int32_t   = 0;
 //    }
-//}
\ No newline at end of file
+//}