Release Mbed Crypto 0.1.0a
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ 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.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2230ed9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,20 @@
+.PHONY: all lib programs tests clean test
+
+all: programs tests
+
+lib:
+ $(MAKE) -C library
+
+programs: lib
+ $(MAKE) -C programs
+
+tests: lib
+ $(MAKE) -C tests
+
+clean:
+ $(MAKE) -C library clean
+ $(MAKE) -C programs clean
+ $(MAKE) -C tests clean
+
+test: lib tests
+ $(MAKE) -C tests test
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..b05e046
--- /dev/null
+++ b/README.md
@@ -0,0 +1,66 @@
+# Mbed Crypto library
+
+The Mbed cryptography library is a reference implementation of the cryptography interface of the Arm Platform Security (PSA) architecture. This is a preview release of Mbed Crypto, provided for evaluation purposes only.
+
+Mbed Crypto is distributed under the Apache License, version 2.0. See the [LICENSE](LICENSE) file for the full text of the license.
+
+## PSA cryptography API
+
+Arm's Platform Security Architecture (PSA) is a holistic set of threat models, security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level.
+
+The PSA Cryptography API provides access to a set of cryptographic primitives. It has a dual purpose: it can be used in a PSA-compliant platform to build services such as secure boot, secure storage and secure communication; and it can also be used independently of other PSA components on any platform.
+
+The design goals of the PSA Cryptography API include:
+
+* The API distinguishes caller memory from internal memory, which allows the library to be implemented in an isolated space for additional security. Library calls can be implemented as direct function calls if isolation is not desired, and as remote procedure calls if isolation is desired.
+* The structure of internal data is hidden to the application, which allows substituting alternative implementations at build time or run time, for example in order to take advantage of hardware accelerators.
+* All access to keys is done via handles, which allows support for external cryptoprocessors that is transparent to applications.
+* The interface to algorithms is generic, favoring algorithm agility.
+* The interface is designed to be easy to use, and hard to accidentally misuse.
+
+## Mbed Crypto implementation
+
+Mbed Crypto is a reference implementation of the PSA Cryptography API. It is written in portable C.
+
+## Documentation
+
+The Mbed Crypto library is a reference implementation of the PSA Cryptography API. Therefore, the library's API documentation is the PSA Cryptography API specification. The PSA Cryptography API specification consists of the following documents:
+
+* The [PSA Cryptography API overview](docs/PSA_Crypto_API_Overview.pdf).
+* The [PSA Cryptography API detailed function reference](docs/PSA_Crypto_API_Reference.pdf), which you can also browse in [HTML format](docs/html/modules.html).
+
+## Compiling
+
+You need the following tools to build the library with the provided makefiles:
+
+* GNU Make.
+* A C toolchain (compiler, linker, archiver).
+* Python 2 or Python 3 (either will work) to generate the test code.
+* Perl to run the tests.
+
+If you have a C compiler such as GCC or Clang, just run `make` in the toplevel directory to build the library, a set of unit tests and some sample programs.
+
+To select a different compiler, set the `CC` variable to name or path of the compiler and linker (default: `cc`) and set `AR` to a compatible archiver (default: `ar`). For example:
+```
+make CC=arm-linux-gnueabi-gcc AR=arm-linux-gnueabi-ar
+```
+The provided makefiles pass options to the compiler that assume a GCC-like command line syntax. To use a different compiler, you may need to pass different values for `CFLAGS`, `WARNINGS_CFLAGS` and `LDFLAGS`.
+
+To run the unit tests on the host machine, run `make test` from the toplevel directory. If you are cross-compiling, copy the test executable from the `tests` directory to the target machine.
+
+## Example programs
+
+The `programs/` subdirectory contains some sample programs that use the library. Please note that the goal of these sample programs is to demonstrate specific features of the library and the code may need to be adapted to build a real-world application.
+
+## Upcoming features
+
+Future releases of this library will include:
+
+* A driver programming interface, to use hardware accelerators instead of the default software implementation for chosen algorithms.
+* Support for external keys, stored and manipulated exclusively in a separate cryptoprocessor.
+* A configuration mechanism to compile only the algorithms you need for your application.
+* A wider set of cryptographic algorithms.
+
+## Feedback welcome
+
+Arm welcomes feedback on the design of the API. If you think something could be improved, please open an issue on our Github repository. Alternatively, if you prefer to provide your feedback privately, please email us at [`mbed-crypto@arm.com`](mailto:mbed-crypto@arm.com). All feedback received in email will be treated confidentially.
diff --git a/VERSION.txt b/VERSION.txt
new file mode 100644
index 0000000..8d456e7
--- /dev/null
+++ b/VERSION.txt
@@ -0,0 +1 @@
+mbedcrypto-0.1.0a
diff --git a/docs/PSA_Crypto_API_Overview.pdf b/docs/PSA_Crypto_API_Overview.pdf
new file mode 100644
index 0000000..4d69158
--- /dev/null
+++ b/docs/PSA_Crypto_API_Overview.pdf
Binary files differ
diff --git a/docs/PSA_Crypto_API_Reference.pdf b/docs/PSA_Crypto_API_Reference.pdf
new file mode 100644
index 0000000..6645a84
--- /dev/null
+++ b/docs/PSA_Crypto_API_Reference.pdf
Binary files differ
diff --git a/docs/html/annotated.html b/docs/html/annotated.html
new file mode 100644
index 0000000..530ebf0
--- /dev/null
+++ b/docs/html/annotated.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Class List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">Class List</div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here are the classes, structs, unions and interfaces with brief descriptions:</div><div class="directory">
+<table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><span class="icona"><span class="icon">C</span></span><a class="el" href="structpsa__generate__key__extra__rsa.html" target="_self">psa_generate_key_extra_rsa</a></td><td class="desc"></td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/bc_s.png b/docs/html/bc_s.png
new file mode 100644
index 0000000..224b29a
--- /dev/null
+++ b/docs/html/bc_s.png
Binary files differ
diff --git a/docs/html/bdwn.png b/docs/html/bdwn.png
new file mode 100644
index 0000000..940a0b9
--- /dev/null
+++ b/docs/html/bdwn.png
Binary files differ
diff --git a/docs/html/classes.html b/docs/html/classes.html
new file mode 100644
index 0000000..8afddf4
--- /dev/null
+++ b/docs/html/classes.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Class Index</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">Class Index</div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="qindex"><a class="qindex" href="#letter_p">p</a></div>
+<table class="classindex">
+<tr><td rowspan="2" valign="bottom"><a name="letter_p"></a><table border="0" cellspacing="0" cellpadding="0"><tr><td><div class="ah">  p  </div></td></tr></table>
+</td><td></td></tr>
+<tr><td></td></tr>
+<tr><td valign="top"><a class="el" href="structpsa__generate__key__extra__rsa.html">psa_generate_key_extra_rsa</a>   </td><td></td></tr>
+<tr><td></td><td></td></tr>
+</table>
+<div class="qindex"><a class="qindex" href="#letter_p">p</a></div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/closed.png b/docs/html/closed.png
new file mode 100644
index 0000000..98cc2c9
--- /dev/null
+++ b/docs/html/closed.png
Binary files differ
diff --git a/docs/html/crypto_8h.html b/docs/html/crypto_8h.html
new file mode 100644
index 0000000..ba11eb6
--- /dev/null
+++ b/docs/html/crypto_8h.html
@@ -0,0 +1,761 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: psa/crypto.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_7dae9cfde651cd3cb034485ce5e391b9.html">psa</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#nested-classes">Classes</a> |
+<a href="#define-members">Macros</a> |
+<a href="#typedef-members">Typedefs</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">crypto.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Platform Security Architecture cryptography module.
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include "crypto_platform.h"</code><br />
+<code>#include <stddef.h></code><br />
+<code>#include "<a class="el" href="crypto__sizes_8h_source.html">crypto_sizes.h</a>"</code><br />
+<code>#include "crypto_struct.h"</code><br />
+<code>#include "crypto_extra.h"</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for crypto.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="crypto_8h__incl.png" border="0" usemap="#psa_2crypto_8h" alt=""/></div>
+<map name="psa_2crypto_8h" id="psa_2crypto_8h">
+<area shape="rect" id="node8" href="crypto__sizes_8h.html" title="PSA cryptography module: Mbed TLS buffer size macros. " alt="" coords="796,95,903,121"/>
+</map>
+</div>
+</div>
+<p><a href="crypto_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="nested-classes"></a>
+Classes</h2></td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct  </td><td class="memItemRight" valign="bottom"><a class="el" href="structpsa__generate__key__extra__rsa.html">psa_generate_key_extra_rsa</a></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ga4cc859e2c66ca381c7418db3527a65e1"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)0)</td></tr>
+<tr class="separator:ga4cc859e2c66ca381c7418db3527a65e1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga24d5fdcdd759f846f79d9e581c63a83f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga24d5fdcdd759f846f79d9e581c63a83f">PSA_ERROR_UNKNOWN_ERROR</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)1)</td></tr>
+<tr class="separator:ga24d5fdcdd759f846f79d9e581c63a83f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1dcc6d130633ed5db8942257581b55dd"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)2)</td></tr>
+<tr class="separator:ga1dcc6d130633ed5db8942257581b55dd"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4d1b8dd8526177a15a210b7afc1accb1"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)3)</td></tr>
+<tr class="separator:ga4d1b8dd8526177a15a210b7afc1accb1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga695025f4ec11249aee7ea3d0f65e01c8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)4)</td></tr>
+<tr class="separator:ga695025f4ec11249aee7ea3d0f65e01c8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac2fee3a51249fbea45360aaa911f3e58"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#gac2fee3a51249fbea45360aaa911f3e58">PSA_ERROR_OCCUPIED_SLOT</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)5)</td></tr>
+<tr class="separator:gac2fee3a51249fbea45360aaa911f3e58"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaba00e3e6ceb2b12965a81e5ac02ae040"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)6)</td></tr>
+<tr class="separator:gaba00e3e6ceb2b12965a81e5ac02ae040"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga933d40fa2a591004f2e93aa91e11db84"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)7)</td></tr>
+<tr class="separator:ga933d40fa2a591004f2e93aa91e11db84"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga798df25a505ebf931f7bec1f80f1f85f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)8)</td></tr>
+<tr class="separator:ga798df25a505ebf931f7bec1f80f1f85f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga91b2ad8a867517a2651f1b076c5216e5"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)9)</td></tr>
+<tr class="separator:ga91b2ad8a867517a2651f1b076c5216e5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga897a45eb206a6f6b7be7ffbe36f0d766"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga897a45eb206a6f6b7be7ffbe36f0d766">PSA_ERROR_INSUFFICIENT_STORAGE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)10)</td></tr>
+<tr class="separator:ga897a45eb206a6f6b7be7ffbe36f0d766"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5cdb6948371d49e916106249020ea3f7"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)11)</td></tr>
+<tr class="separator:ga5cdb6948371d49e916106249020ea3f7"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gadd169a1af2707862b95fb9df91dfc37d"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#gadd169a1af2707862b95fb9df91dfc37d">PSA_ERROR_STORAGE_FAILURE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)12)</td></tr>
+<tr class="separator:gadd169a1af2707862b95fb9df91dfc37d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga08b10e70fa5ff0b05c631d9f8f6b2c6b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)13)</td></tr>
+<tr class="separator:ga08b10e70fa5ff0b05c631d9f8f6b2c6b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2c5dda1485cb54f2385cb9c1279a7004"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)14)</td></tr>
+<tr class="separator:ga2c5dda1485cb54f2385cb9c1279a7004"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4deb59fec02297ec5d8b42178323f675"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">PSA_ERROR_INSUFFICIENT_ENTROPY</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)15)</td></tr>
+<tr class="separator:ga4deb59fec02297ec5d8b42178323f675"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga35927f755d232c4766de600f2c49e9f2"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga35927f755d232c4766de600f2c49e9f2">PSA_ERROR_INVALID_SIGNATURE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)16)</td></tr>
+<tr class="separator:ga35927f755d232c4766de600f2c49e9f2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gabe29594edbfb152cf153975b0597ac48"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#gabe29594edbfb152cf153975b0597ac48">PSA_ERROR_INVALID_PADDING</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)17)</td></tr>
+<tr class="separator:gabe29594edbfb152cf153975b0597ac48"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf1fa61f72e9e5b4a848c991bea495767"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#gaf1fa61f72e9e5b4a848c991bea495767">PSA_ERROR_INSUFFICIENT_CAPACITY</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)18)</td></tr>
+<tr class="separator:gaf1fa61f72e9e5b4a848c991bea495767"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf2edfe992db358f8eefd4bc82d069592"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_BITS_TO_BYTES</b>(bits)   (((bits) + 7) / 8)</td></tr>
+<tr class="separator:gaf2edfe992db358f8eefd4bc82d069592"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga997f71feb68cca794f7ed676600e06db"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_BYTES_TO_BITS</b>(bytes)   ((bytes) * 8)</td></tr>
+<tr class="separator:ga997f71feb68cca794f7ed676600e06db"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafce7ab2b54ce97ea5bff73f13a9f3e5b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gafce7ab2b54ce97ea5bff73f13a9f3e5b">PSA_KEY_TYPE_NONE</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x00000000)</td></tr>
+<tr class="separator:gafce7ab2b54ce97ea5bff73f13a9f3e5b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8dbaed2fdb1ebae8aa127ad3988516f7"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7">PSA_KEY_TYPE_VENDOR_FLAG</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x80000000)</td></tr>
+<tr class="separator:ga8dbaed2fdb1ebae8aa127ad3988516f7"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6eeda1b2a1550050cf68dbcac35ad8ac"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_CATEGORY_MASK</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x7e000000)</td></tr>
+<tr class="separator:ga6eeda1b2a1550050cf68dbcac35ad8ac"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa97f92025533102616b32d571c940d80"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaa97f92025533102616b32d571c940d80">PSA_KEY_TYPE_RAW_DATA</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x02000000)</td></tr>
+<tr class="separator:gaa97f92025533102616b32d571c940d80"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8f214beb04334be08f927f227f097ef1"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_CATEGORY_SYMMETRIC</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000000)</td></tr>
+<tr class="separator:ga8f214beb04334be08f927f227f097ef1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7f4249bf41fc60daa0b4e2901cdcd02d"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_CATEGORY_ASYMMETRIC</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x06000000)</td></tr>
+<tr class="separator:ga7f4249bf41fc60daa0b4e2901cdcd02d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6b686b30cc0193f5a93616097d58934f"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_PAIR_FLAG</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x01000000)</td></tr>
+<tr class="separator:ga6b686b30cc0193f5a93616097d58934f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga92d989f4ca64abd00f463defd773a6f8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga92d989f4ca64abd00f463defd773a6f8">PSA_KEY_TYPE_HMAC</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x02000001)</td></tr>
+<tr class="separator:ga92d989f4ca64abd00f463defd773a6f8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae871b2357b8593f33bfd51abbf93ebb1"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gae871b2357b8593f33bfd51abbf93ebb1">PSA_KEY_TYPE_DERIVE</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x02000101)</td></tr>
+<tr class="separator:gae871b2357b8593f33bfd51abbf93ebb1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6ee54579dcf278c677eda4bb1a29575e"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga6ee54579dcf278c677eda4bb1a29575e">PSA_KEY_TYPE_AES</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000001)</td></tr>
+<tr class="separator:ga6ee54579dcf278c677eda4bb1a29575e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga577562bfbbc691c820d55ec308333138"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga577562bfbbc691c820d55ec308333138">PSA_KEY_TYPE_DES</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000002)</td></tr>
+<tr class="separator:ga577562bfbbc691c820d55ec308333138"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad8e5da742343fd5519f9d8a630c2ed81"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gad8e5da742343fd5519f9d8a630c2ed81">PSA_KEY_TYPE_CAMELLIA</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000003)</td></tr>
+<tr class="separator:gad8e5da742343fd5519f9d8a630c2ed81"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae4d46e83f910dcaa126000a8ed03cde9"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gae4d46e83f910dcaa126000a8ed03cde9">PSA_KEY_TYPE_ARC4</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000004)</td></tr>
+<tr class="separator:gae4d46e83f910dcaa126000a8ed03cde9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga9ba0878f56c8bcd1995ac017a74f513b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b">PSA_KEY_TYPE_RSA_PUBLIC_KEY</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x06010000)</td></tr>
+<tr class="separator:ga9ba0878f56c8bcd1995ac017a74f513b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga581f50687f5d650456925278948f2799"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga581f50687f5d650456925278948f2799">PSA_KEY_TYPE_RSA_KEYPAIR</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x07010000)</td></tr>
+<tr class="separator:ga581f50687f5d650456925278948f2799"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5e7439c2905136366c3a876e62e5ddfc"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga5e7439c2905136366c3a876e62e5ddfc">PSA_KEY_TYPE_DSA_PUBLIC_KEY</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x06020000)</td></tr>
+<tr class="separator:ga5e7439c2905136366c3a876e62e5ddfc"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga011010ee28c20388f3d89fb27088ed62"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga011010ee28c20388f3d89fb27088ed62">PSA_KEY_TYPE_DSA_KEYPAIR</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x07020000)</td></tr>
+<tr class="separator:ga011010ee28c20388f3d89fb27088ed62"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad8d37a32a305dda9fb4af1707aace47c"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x06030000)</td></tr>
+<tr class="separator:gad8d37a32a305dda9fb4af1707aace47c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6754658749714c6ac674bdf6d2d40767"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_ECC_KEYPAIR_BASE</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x07030000)</td></tr>
+<tr class="separator:ga6754658749714c6ac674bdf6d2d40767"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gadc2a3c0041ac1d0a2b6f421d8e089b25"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_ECC_CURVE_MASK</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x0000ffff)</td></tr>
+<tr class="separator:gadc2a3c0041ac1d0a2b6f421d8e089b25"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gadf3ad65d157bf5282849c954bf3f51af"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gadf3ad65d157bf5282849c954bf3f51af">PSA_KEY_TYPE_ECC_KEYPAIR</a>(curve)   (PSA_KEY_TYPE_ECC_KEYPAIR_BASE | (curve))</td></tr>
+<tr class="separator:gadf3ad65d157bf5282849c954bf3f51af"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad54c03d3b47020e571a72cd01d978cf2"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gad54c03d3b47020e571a72cd01d978cf2">PSA_KEY_TYPE_ECC_PUBLIC_KEY</a>(curve)   (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve))</td></tr>
+<tr class="separator:gad54c03d3b47020e571a72cd01d978cf2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gadbe4c086a6562aefe344bc79e51bdfd3"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gadbe4c086a6562aefe344bc79e51bdfd3">PSA_KEY_TYPE_IS_VENDOR_DEFINED</a>(type)   (((type) & <a class="el" href="group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7">PSA_KEY_TYPE_VENDOR_FLAG</a>) != 0)</td></tr>
+<tr class="separator:gadbe4c086a6562aefe344bc79e51bdfd3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab138ae2ebf2905dfbaf4154db2620939"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gab138ae2ebf2905dfbaf4154db2620939">PSA_KEY_TYPE_IS_ASYMMETRIC</a>(type)   (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)</td></tr>
+<tr class="separator:gab138ae2ebf2905dfbaf4154db2620939"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac674a0f059bc0cb72b47f0c517b4f45b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gac674a0f059bc0cb72b47f0c517b4f45b">PSA_KEY_TYPE_IS_PUBLIC_KEY</a>(type)</td></tr>
+<tr class="separator:gac674a0f059bc0cb72b47f0c517b4f45b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac14c6d6e1b2b7f4a92a7b757465cff29"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gac14c6d6e1b2b7f4a92a7b757465cff29">PSA_KEY_TYPE_IS_KEYPAIR</a>(type)</td></tr>
+<tr class="separator:gac14c6d6e1b2b7f4a92a7b757465cff29"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf09f1ca1de6a7e7cff0fe516f3f6c91d"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaf09f1ca1de6a7e7cff0fe516f3f6c91d">PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY</a>(type)   ((type) | PSA_KEY_TYPE_PAIR_FLAG)</td></tr>
+<tr class="separator:gaf09f1ca1de6a7e7cff0fe516f3f6c91d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gace08e46dd7cbf642d50d982a25d02bec"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec">PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR</a>(type)   ((type) & ~PSA_KEY_TYPE_PAIR_FLAG)</td></tr>
+<tr class="separator:gace08e46dd7cbf642d50d982a25d02bec"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga0e1d8f241228e49c9cadadfb4579ef1a"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a">PSA_KEY_TYPE_IS_RSA</a>(type)   (<a class="el" href="group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec">PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR</a>(type) == <a class="el" href="group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b">PSA_KEY_TYPE_RSA_PUBLIC_KEY</a>)</td></tr>
+<tr class="separator:ga0e1d8f241228e49c9cadadfb4579ef1a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga88e01fa06b585654689a99bcc06bbe66"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66">PSA_KEY_TYPE_IS_ECC</a>(type)</td></tr>
+<tr class="separator:ga88e01fa06b585654689a99bcc06bbe66"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7bf101b671e8cf26f4cb08fcb679db4b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_IS_ECC_KEYPAIR</b>(type)</td></tr>
+<tr class="separator:ga7bf101b671e8cf26f4cb08fcb679db4b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5af146a173b0c84d7e737e2fb6a3c0a7"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY</b>(type)</td></tr>
+<tr class="separator:ga5af146a173b0c84d7e737e2fb6a3c0a7"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga0c567210e6f80aa8f2aa87efa7a3a3f9"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga0c567210e6f80aa8f2aa87efa7a3a3f9">PSA_KEY_TYPE_GET_CURVE</a>(type)</td></tr>
+<tr class="separator:ga0c567210e6f80aa8f2aa87efa7a3a3f9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4201013d5947c375fae7311b0f98bac7"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT163K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0001)</td></tr>
+<tr class="separator:ga4201013d5947c375fae7311b0f98bac7"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaca8816b785f492a8795b5276977d1369"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT163R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0002)</td></tr>
+<tr class="separator:gaca8816b785f492a8795b5276977d1369"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4ab7a853ceb3ad0a525ecb571633a1ca"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT163R2</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0003)</td></tr>
+<tr class="separator:ga4ab7a853ceb3ad0a525ecb571633a1ca"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac9fd11da90ca67649a5f51a158afe5f3"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT193R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0004)</td></tr>
+<tr class="separator:gac9fd11da90ca67649a5f51a158afe5f3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7a77f5e385f6439dae5857a7f35756eb"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT193R2</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0005)</td></tr>
+<tr class="separator:ga7a77f5e385f6439dae5857a7f35756eb"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga36e409c36983e41db5db202b1d2095b5"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT233K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0006)</td></tr>
+<tr class="separator:ga36e409c36983e41db5db202b1d2095b5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga54997a9f8ef752c6d717171e01c31019"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT233R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0007)</td></tr>
+<tr class="separator:ga54997a9f8ef752c6d717171e01c31019"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaabccf2759188c3e98d82faa5d8dfcd8c"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT239K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0008)</td></tr>
+<tr class="separator:gaabccf2759188c3e98d82faa5d8dfcd8c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga28c765d75773b5fe083219e7c0b054f9"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT283K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0009)</td></tr>
+<tr class="separator:ga28c765d75773b5fe083219e7c0b054f9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafd8ecacea0d9e7e1a0247c047baf3372"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT283R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000a)</td></tr>
+<tr class="separator:gafd8ecacea0d9e7e1a0247c047baf3372"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2bf301617cc84a6f2b36a86cc29eaf4d"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT409K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000b)</td></tr>
+<tr class="separator:ga2bf301617cc84a6f2b36a86cc29eaf4d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae41caa1cc16d3c35769b6edcb62c8957"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT409R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000c)</td></tr>
+<tr class="separator:gae41caa1cc16d3c35769b6edcb62c8957"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2043aa519549a6194d132d81816879bc"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT571K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000d)</td></tr>
+<tr class="separator:ga2043aa519549a6194d132d81816879bc"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1607d2cb9591b56dbe1295bedc33e19e"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT571R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000e)</td></tr>
+<tr class="separator:ga1607d2cb9591b56dbe1295bedc33e19e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2ad14935d244d93ee0e4cfe9b1f218a4"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP160K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000f)</td></tr>
+<tr class="separator:ga2ad14935d244d93ee0e4cfe9b1f218a4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga35ed41203039e94eb4855cc70f28f7f0"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP160R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0010)</td></tr>
+<tr class="separator:ga35ed41203039e94eb4855cc70f28f7f0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac465f57c34914a01aea8c220a613dfe6"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP160R2</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0011)</td></tr>
+<tr class="separator:gac465f57c34914a01aea8c220a613dfe6"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga58c806d45ab350287ddc49da833bd558"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP192K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0012)</td></tr>
+<tr class="separator:ga58c806d45ab350287ddc49da833bd558"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5aa3ceff4603fa3fafd8f2286c5d3e4a"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP192R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0013)</td></tr>
+<tr class="separator:ga5aa3ceff4603fa3fafd8f2286c5d3e4a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gabfaaab2eaab0ac360e41c1aff6133cdf"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP224K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0014)</td></tr>
+<tr class="separator:gabfaaab2eaab0ac360e41c1aff6133cdf"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8d1d21b6b87ba4158235b876ae79031d"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP224R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0015)</td></tr>
+<tr class="separator:ga8d1d21b6b87ba4158235b876ae79031d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaaa61941f815aff976a1debd910b1704c"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP256K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0016)</td></tr>
+<tr class="separator:gaaa61941f815aff976a1debd910b1704c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga11224270225c2b2dbfa2ab01073a4e93"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP256R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0017)</td></tr>
+<tr class="separator:ga11224270225c2b2dbfa2ab01073a4e93"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3e870a36493143507a01a28c70790fa3"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP384R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0018)</td></tr>
+<tr class="separator:ga3e870a36493143507a01a28c70790fa3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4482ff6155006ff509071c32ce263fdf"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP521R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0019)</td></tr>
+<tr class="separator:ga4482ff6155006ff509071c32ce263fdf"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa999b69c56af0cc1cebf4596f8578191"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_BRAINPOOL_P256R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x001a)</td></tr>
+<tr class="separator:gaa999b69c56af0cc1cebf4596f8578191"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga79f95ed8050f2dc7750cbac212c6e687"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_BRAINPOOL_P384R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x001b)</td></tr>
+<tr class="separator:ga79f95ed8050f2dc7750cbac212c6e687"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa03a2dc6096f336be3d68a1f7405e86c"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_BRAINPOOL_P512R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x001c)</td></tr>
+<tr class="separator:gaa03a2dc6096f336be3d68a1f7405e86c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac94faf3b8d9884221541f51f26b11c7a"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_CURVE25519</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x001d)</td></tr>
+<tr class="separator:gac94faf3b8d9884221541f51f26b11c7a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga902b0e91eff920873b3b59c740854305"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_CURVE448</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x001e)</td></tr>
+<tr class="separator:ga902b0e91eff920873b3b59c740854305"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafef0f861db5bb6cdf025d18cf0fbdbb0"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_FFDHE_2048</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0100)</td></tr>
+<tr class="separator:gafef0f861db5bb6cdf025d18cf0fbdbb0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae69d8c862c26e5aed50e047814e8c27e"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_FFDHE_3072</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0101)</td></tr>
+<tr class="separator:gae69d8c862c26e5aed50e047814e8c27e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7d2411ef9ff0f95bd01ca6208368f8e4"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_FFDHE_4096</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0102)</td></tr>
+<tr class="separator:ga7d2411ef9ff0f95bd01ca6208368f8e4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga9380456dc83ac91a5338d3b5cf48c100"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_FFDHE_6144</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0103)</td></tr>
+<tr class="separator:ga9380456dc83ac91a5338d3b5cf48c100"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga847e2f8d9663ff63025a8cd0d1096655"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_FFDHE_8192</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0104)</td></tr>
+<tr class="separator:ga847e2f8d9663ff63025a8cd0d1096655"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gacaa366bdeb0413e63e87a667c5457b2e"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gacaa366bdeb0413e63e87a667c5457b2e">PSA_BLOCK_CIPHER_BLOCK_SIZE</a>(type)</td></tr>
+<tr class="separator:gacaa366bdeb0413e63e87a667c5457b2e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf5d76750b6cfe3e7f0c8e9eee1162318"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_VENDOR_FLAG</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x80000000)</td></tr>
+<tr class="separator:gaf5d76750b6cfe3e7f0c8e9eee1162318"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga25e918c465b4421dbfaedad6b693d110"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x7f000000)</td></tr>
+<tr class="separator:ga25e918c465b4421dbfaedad6b693d110"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafd048e1835b80e6daaff7fddce699757"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_HASH</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000000)</td></tr>
+<tr class="separator:gafd048e1835b80e6daaff7fddce699757"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5e6e0039d0b0d18afb3e13e5b9602b3a"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_MAC</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02000000)</td></tr>
+<tr class="separator:ga5e6e0039d0b0d18afb3e13e5b9602b3a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga68228a619db59eba93fd13e9129dbfe2"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_CIPHER</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000000)</td></tr>
+<tr class="separator:ga68228a619db59eba93fd13e9129dbfe2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga37fdd9cac2552f1568f38e091a826549"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_AEAD</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x06000000)</td></tr>
+<tr class="separator:ga37fdd9cac2552f1568f38e091a826549"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga68a0af1dd89b33fb1e53139f654988f6"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_SIGN</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10000000)</td></tr>
+<tr class="separator:ga68a0af1dd89b33fb1e53139f654988f6"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga72f46c8256b760b174e6db61a61cd608"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x12000000)</td></tr>
+<tr class="separator:ga72f46c8256b760b174e6db61a61cd608"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga808e397a4891c612df4a5b20eebc2fac"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_KEY_AGREEMENT</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x22000000)</td></tr>
+<tr class="separator:ga808e397a4891c612df4a5b20eebc2fac"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac185b2274dd4e5f0b97c43334c2e478f"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_KEY_DERIVATION</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x30000000)</td></tr>
+<tr class="separator:gac185b2274dd4e5f0b97c43334c2e478f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2396d8ba67096b3ebc69bc351a74c78b"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_VENDOR_DEFINED</b>(alg)   (((alg) & PSA_ALG_VENDOR_FLAG) != 0)</td></tr>
+<tr class="separator:ga2396d8ba67096b3ebc69bc351a74c78b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac9280662bb482590b4b33d1dcd32930f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH)</td></tr>
+<tr class="separator:gac9280662bb482590b4b33d1dcd32930f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaca7aee4c9dde316b3b1a150a26eab776"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaca7aee4c9dde316b3b1a150a26eab776">PSA_ALG_IS_MAC</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC)</td></tr>
+<tr class="separator:gaca7aee4c9dde316b3b1a150a26eab776"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1d1a5a402ad89a2e68f12bfb535490eb"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga1d1a5a402ad89a2e68f12bfb535490eb">PSA_ALG_IS_CIPHER</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER)</td></tr>
+<tr class="separator:ga1d1a5a402ad89a2e68f12bfb535490eb"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1d44829d60065eaa4ac9a703e7d6abc8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8">PSA_ALG_IS_AEAD</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD)</td></tr>
+<tr class="separator:ga1d44829d60065eaa4ac9a703e7d6abc8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6d490d0904e0698f6c1268a89d72ff31"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga6d490d0904e0698f6c1268a89d72ff31">PSA_ALG_IS_SIGN</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN)</td></tr>
+<tr class="separator:ga6d490d0904e0698f6c1268a89d72ff31"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga41d2ee937d54efd76bd54a97b2ebc08a"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga41d2ee937d54efd76bd54a97b2ebc08a">PSA_ALG_IS_ASYMMETRIC_ENCRYPTION</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION)</td></tr>
+<tr class="separator:ga41d2ee937d54efd76bd54a97b2ebc08a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga59753742cb06553bd22751bbef472b6f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga59753742cb06553bd22751bbef472b6f">PSA_ALG_IS_KEY_AGREEMENT</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT)</td></tr>
+<tr class="separator:ga59753742cb06553bd22751bbef472b6f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf8b90c648aa53dbd06c236695e300cd0"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaf8b90c648aa53dbd06c236695e300cd0">PSA_ALG_IS_KEY_DERIVATION</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)</td></tr>
+<tr class="separator:gaf8b90c648aa53dbd06c236695e300cd0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac41a7077aef55bb20c629c8949d43c57"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_HASH_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x000000ff)</td></tr>
+<tr class="separator:gac41a7077aef55bb20c629c8949d43c57"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab076ca67238cb4ebd81556db8f3dbac1"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_MD2</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000001)</td></tr>
+<tr class="separator:gab076ca67238cb4ebd81556db8f3dbac1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaac7ab8c28c117ef4ddf01affc8d3ceb2"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_MD4</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000002)</td></tr>
+<tr class="separator:gaac7ab8c28c117ef4ddf01affc8d3ceb2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gade591d9286d23382eb5cec099c84180d"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_MD5</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000003)</td></tr>
+<tr class="separator:gade591d9286d23382eb5cec099c84180d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6c5d3a32cda59086f07b85ef007033dd"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_RIPEMD160</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000004)</td></tr>
+<tr class="separator:ga6c5d3a32cda59086f07b85ef007033dd"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3fca4e9f9ad4a1158817d1850dee82e5"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_SHA_1</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000005)</td></tr>
+<tr class="separator:ga3fca4e9f9ad4a1158817d1850dee82e5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga25d6a3244d10a7148fe6b026d1979f7b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga25d6a3244d10a7148fe6b026d1979f7b">PSA_ALG_SHA_224</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000008)</td></tr>
+<tr class="separator:ga25d6a3244d10a7148fe6b026d1979f7b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga619471f978e13cdd0a1e37145e4bf341"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga619471f978e13cdd0a1e37145e4bf341">PSA_ALG_SHA_256</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000009)</td></tr>
+<tr class="separator:ga619471f978e13cdd0a1e37145e4bf341"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga58af64dd9a86a287e8da9ed7739eead4"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga58af64dd9a86a287e8da9ed7739eead4">PSA_ALG_SHA_384</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000a)</td></tr>
+<tr class="separator:ga58af64dd9a86a287e8da9ed7739eead4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafba3ae409f46d3dd7f37a0910660c3e9"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gafba3ae409f46d3dd7f37a0910660c3e9">PSA_ALG_SHA_512</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000b)</td></tr>
+<tr class="separator:gafba3ae409f46d3dd7f37a0910660c3e9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3fe2d7c3c80e3186ca78d16a35d5d931"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga3fe2d7c3c80e3186ca78d16a35d5d931">PSA_ALG_SHA_512_224</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000c)</td></tr>
+<tr class="separator:ga3fe2d7c3c80e3186ca78d16a35d5d931"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5910b3964c14e9613e8643a45b09c2d4"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga5910b3964c14e9613e8643a45b09c2d4">PSA_ALG_SHA_512_256</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000d)</td></tr>
+<tr class="separator:ga5910b3964c14e9613e8643a45b09c2d4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga16f5fe34ccce68c2fada1224c054a999"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga16f5fe34ccce68c2fada1224c054a999">PSA_ALG_SHA3_224</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000010)</td></tr>
+<tr class="separator:ga16f5fe34ccce68c2fada1224c054a999"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaace70d9515489bbe3c5e7ac1b7d9155b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaace70d9515489bbe3c5e7ac1b7d9155b">PSA_ALG_SHA3_256</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000011)</td></tr>
+<tr class="separator:gaace70d9515489bbe3c5e7ac1b7d9155b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab0f079257ea75e2acfe2fc3b38c78cd8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gab0f079257ea75e2acfe2fc3b38c78cd8">PSA_ALG_SHA3_384</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000012)</td></tr>
+<tr class="separator:gab0f079257ea75e2acfe2fc3b38c78cd8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga37e5dbe936dddb155e76f2997de27188"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga37e5dbe936dddb155e76f2997de27188">PSA_ALG_SHA3_512</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000013)</td></tr>
+<tr class="separator:ga37e5dbe936dddb155e76f2997de27188"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gabba3fcfee55533b0e25350e78a942e07"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_MAC_SUBCATEGORY_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00c00000)</td></tr>
+<tr class="separator:gabba3fcfee55533b0e25350e78a942e07"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga0675192b82720fb8c9037a95bdeb6c88"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_HMAC_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02800000)</td></tr>
+<tr class="separator:ga0675192b82720fb8c9037a95bdeb6c88"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga70f397425684b3efcde1e0e34c28261f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga70f397425684b3efcde1e0e34c28261f">PSA_ALG_HMAC</a>(hash_alg)   (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga70f397425684b3efcde1e0e34c28261f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6ac4f9564237dfd8d28e988da41bc931"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_HMAC_HASH</b>(hmac_alg)   (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga6ac4f9564237dfd8d28e988da41bc931"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4a050c3c3cbc6eb96418f18847601c8a"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga4a050c3c3cbc6eb96418f18847601c8a">PSA_ALG_IS_HMAC</a>(alg)</td></tr>
+<tr class="separator:ga4a050c3c3cbc6eb96418f18847601c8a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaee0c29980b08305f6d0e7b3fbb588ade"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CIPHER_MAC_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02c00000)</td></tr>
+<tr class="separator:gaee0c29980b08305f6d0e7b3fbb588ade"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga20bdc755de7b90f6621ccb1e6bb5d9e1"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CBC_MAC</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02c00001)</td></tr>
+<tr class="separator:ga20bdc755de7b90f6621ccb1e6bb5d9e1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga146328a1e0023a02464e232d6ecefdc2"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CMAC</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02c00002)</td></tr>
+<tr class="separator:ga146328a1e0023a02464e232d6ecefdc2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga69a012ce150219a2d97c3ab5582f0004"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_GMAC</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02c00003)</td></tr>
+<tr class="separator:ga69a012ce150219a2d97c3ab5582f0004"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8986360ff97dbd91f220edf9202e375d"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga8986360ff97dbd91f220edf9202e375d">PSA_ALG_IS_CIPHER_MAC</a>(alg)</td></tr>
+<tr class="separator:ga8986360ff97dbd91f220edf9202e375d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5e09871380b1dd62be19732b4736313b"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CIPHER_SUBCATEGORY_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00c00000)</td></tr>
+<tr class="separator:ga5e09871380b1dd62be19732b4736313b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8441c6d5dfe158d2d8a7540a9a0ebb39"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_BLOCK_CIPHER_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000000)</td></tr>
+<tr class="separator:ga8441c6d5dfe158d2d8a7540a9a0ebb39"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6bd5e2da108ecb82ac6fd3eb746424ef"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_BLOCK_CIPHER_MODE_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x000000ff)</td></tr>
+<tr class="separator:ga6bd5e2da108ecb82ac6fd3eb746424ef"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga61c792645f8e5aa42fc8b3392fe53231"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_BLOCK_CIPHER_PADDING_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x003f0000)</td></tr>
+<tr class="separator:ga61c792645f8e5aa42fc8b3392fe53231"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga0992d26a02a2a7dc316cd5abc5254966"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga0992d26a02a2a7dc316cd5abc5254966">PSA_ALG_BLOCK_CIPHER_PAD_NONE</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00000000)</td></tr>
+<tr class="separator:ga0992d26a02a2a7dc316cd5abc5254966"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga40066e494138ef20dfc8de22825b4057"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_BLOCK_CIPHER_PAD_PKCS7</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00010000)</td></tr>
+<tr class="separator:ga40066e494138ef20dfc8de22825b4057"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga02e787d79c0cd666efcd090569d5b31c"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga02e787d79c0cd666efcd090569d5b31c">PSA_ALG_IS_BLOCK_CIPHER</a>(alg)</td></tr>
+<tr class="separator:ga02e787d79c0cd666efcd090569d5b31c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga931f31d4f05c3dab9fd5d7fdcd3715f2"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga931f31d4f05c3dab9fd5d7fdcd3715f2">PSA_ALG_CBC_BASE</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000001)</td></tr>
+<tr class="separator:ga931f31d4f05c3dab9fd5d7fdcd3715f2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa04cf3217f724b219f2a054b98c554fe"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CFB_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000002)</td></tr>
+<tr class="separator:gaa04cf3217f724b219f2a054b98c554fe"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7a1c7906c13a78ad62463c2b68869999"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_OFB_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000003)</td></tr>
+<tr class="separator:ga7a1c7906c13a78ad62463c2b68869999"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga914d820b488366067023ba6ed363ee83"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_XTS_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000004)</td></tr>
+<tr class="separator:ga914d820b488366067023ba6ed363ee83"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaff1ae6bbbe3898273035c237731a6ed6"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_STREAM_CIPHER_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04800000)</td></tr>
+<tr class="separator:gaff1ae6bbbe3898273035c237731a6ed6"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad318309706a769cffdc64e4c7e06b2e9"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gad318309706a769cffdc64e4c7e06b2e9">PSA_ALG_CTR</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04800001)</td></tr>
+<tr class="separator:gad318309706a769cffdc64e4c7e06b2e9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab6a5284decb0e5e1b5b8740a41ef3c5e"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gab6a5284decb0e5e1b5b8740a41ef3c5e">PSA_ALG_ARC4</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04800002)</td></tr>
+<tr class="separator:gab6a5284decb0e5e1b5b8740a41ef3c5e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gacfec68e0c6175e02e1b2ebc97df383c0"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gacfec68e0c6175e02e1b2ebc97df383c0">PSA_ALG_IS_STREAM_CIPHER</a>(alg)</td></tr>
+<tr class="separator:gacfec68e0c6175e02e1b2ebc97df383c0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac2c0e7d21f1b2df5e76bcb4a8f84273c"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CCM</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x06000001)</td></tr>
+<tr class="separator:gac2c0e7d21f1b2df5e76bcb4a8f84273c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga0d7d02b15aaae490d38277d99f1c637c"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_GCM</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x06000002)</td></tr>
+<tr class="separator:ga0d7d02b15aaae490d38277d99f1c637c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga819b23c9899e92e9f867c7b2ae8f264c"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_RSA_PKCS1V15_SIGN_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10020000)</td></tr>
+<tr class="separator:ga819b23c9899e92e9f867c7b2ae8f264c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga702ff75385a6ae7d4247033f479439af"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga702ff75385a6ae7d4247033f479439af">PSA_ALG_RSA_PKCS1V15_SIGN</a>(hash_alg)   (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga702ff75385a6ae7d4247033f479439af"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4215e2a78dcf834e9a625927faa2a817"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga4215e2a78dcf834e9a625927faa2a817">PSA_ALG_RSA_PKCS1V15_SIGN_RAW</a>   PSA_ALG_RSA_PKCS1V15_SIGN_BASE</td></tr>
+<tr class="separator:ga4215e2a78dcf834e9a625927faa2a817"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga9d545279f23d43b1b2a744d0dd6826d0"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_RSA_PKCS1V15_SIGN</b>(alg)   (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE)</td></tr>
+<tr class="separator:ga9d545279f23d43b1b2a744d0dd6826d0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga49d39a343790971b7a74644f4faea0c0"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_RSA_PSS_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10030000)</td></tr>
+<tr class="separator:ga49d39a343790971b7a74644f4faea0c0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga62152bf4cb4bf6aace5e1be8f143564d"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga62152bf4cb4bf6aace5e1be8f143564d">PSA_ALG_RSA_PSS</a>(hash_alg)   (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga62152bf4cb4bf6aace5e1be8f143564d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafa04fae7393a76d5161558768cb82a78"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_RSA_PSS</b>(alg)   (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE)</td></tr>
+<tr class="separator:gafa04fae7393a76d5161558768cb82a78"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga863284106894476e3a8524805410b55b"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DSA_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10040000)</td></tr>
+<tr class="separator:ga863284106894476e3a8524805410b55b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga9a68efdddff5ae95f104a1416b12742e"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga9a68efdddff5ae95f104a1416b12742e">PSA_ALG_DSA</a>(hash_alg)   (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga9a68efdddff5ae95f104a1416b12742e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad3800dafc62d6a17bcae4bce98402e68"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DETERMINISTIC_DSA_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10050000)</td></tr>
+<tr class="separator:gad3800dafc62d6a17bcae4bce98402e68"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1d2a96f788cce4f8fc156d13342e70de"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DSA_DETERMINISTIC_FLAG</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00010000)</td></tr>
+<tr class="separator:ga1d2a96f788cce4f8fc156d13342e70de"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab8eb98fb6d2e094e47f3b44dfe128f94"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DETERMINISTIC_DSA</b>(hash_alg)   (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:gab8eb98fb6d2e094e47f3b44dfe128f94"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gacfc3cd50ef0c4bf694cf936079bcbaee"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_DSA</b>(alg)</td></tr>
+<tr class="separator:gacfc3cd50ef0c4bf694cf936079bcbaee"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae01ae792228c16eac05102f8e900efd1"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DSA_IS_DETERMINISTIC</b>(alg)   (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)</td></tr>
+<tr class="separator:gae01ae792228c16eac05102f8e900efd1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga11f7d6fe7a4441143ed398420b7d1980"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_DETERMINISTIC_DSA</b>(alg)   (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg))</td></tr>
+<tr class="separator:ga11f7d6fe7a4441143ed398420b7d1980"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga474c0582c4726d0c0274e470f4199cf9"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_RANDOMIZED_DSA</b>(alg)   (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg))</td></tr>
+<tr class="separator:ga474c0582c4726d0c0274e470f4199cf9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafd9800fdbe6ea881e0ac0ce03d145928"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_ECDSA_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10060000)</td></tr>
+<tr class="separator:gafd9800fdbe6ea881e0ac0ce03d145928"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7e3ce9f514a227d5ba5d8318870452e3"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga7e3ce9f514a227d5ba5d8318870452e3">PSA_ALG_ECDSA</a>(hash_alg)   (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga7e3ce9f514a227d5ba5d8318870452e3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga51d6b6044a62e33cae0cf64bfc3b22a4"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga51d6b6044a62e33cae0cf64bfc3b22a4">PSA_ALG_ECDSA_ANY</a>   PSA_ALG_ECDSA_BASE</td></tr>
+<tr class="separator:ga51d6b6044a62e33cae0cf64bfc3b22a4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6c08b65200140aeb46ee9db9c8ed878c"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DETERMINISTIC_ECDSA_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10070000)</td></tr>
+<tr class="separator:ga6c08b65200140aeb46ee9db9c8ed878c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga11da566bcd341661c8de921e2ca5ed03"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga11da566bcd341661c8de921e2ca5ed03">PSA_ALG_DETERMINISTIC_ECDSA</a>(hash_alg)   (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga11da566bcd341661c8de921e2ca5ed03"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafb92dc138c9d2388033ff5fc1dab7b48"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_ECDSA</b>(alg)</td></tr>
+<tr class="separator:gafb92dc138c9d2388033ff5fc1dab7b48"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaced29d8e3a1740aaec01e9ef8211df4f"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_ECDSA_IS_DETERMINISTIC</b>(alg)   (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)</td></tr>
+<tr class="separator:gaced29d8e3a1740aaec01e9ef8211df4f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gacd8766fe0fb8c1e2d32644e0d092c43a"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_DETERMINISTIC_ECDSA</b>(alg)   (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))</td></tr>
+<tr class="separator:gacd8766fe0fb8c1e2d32644e0d092c43a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae7b0fafebd139f6f815285b7cad622ea"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_RANDOMIZED_ECDSA</b>(alg)   (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))</td></tr>
+<tr class="separator:gae7b0fafebd139f6f815285b7cad622ea"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga24cf6d7bcd2b9aeeeff86f07b6c674e3"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga24cf6d7bcd2b9aeeeff86f07b6c674e3">PSA_ALG_SIGN_GET_HASH</a>(alg)</td></tr>
+<tr class="separator:ga24cf6d7bcd2b9aeeeff86f07b6c674e3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4c540d3abe43fb9abcb94f2bc51acef9"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga4c540d3abe43fb9abcb94f2bc51acef9">PSA_ALG_RSA_PKCS1V15_CRYPT</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x12020000)</td></tr>
+<tr class="separator:ga4c540d3abe43fb9abcb94f2bc51acef9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga67ba62fbd154f5d3098866ae68ba66eb"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_RSA_OAEP_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x12030000)</td></tr>
+<tr class="separator:ga67ba62fbd154f5d3098866ae68ba66eb"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa1235dc3fdd9839c6c1b1a9857344c76"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaa1235dc3fdd9839c6c1b1a9857344c76">PSA_ALG_RSA_OAEP</a>(hash_alg)   (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:gaa1235dc3fdd9839c6c1b1a9857344c76"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga9a85c05fd5c39ca63bbc47fb0755da39"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_RSA_OAEP</b>(alg)   (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE)</td></tr>
+<tr class="separator:ga9a85c05fd5c39ca63bbc47fb0755da39"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae6b0b87aabe82a1b3113824f022c52e8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_RSA_OAEP_GET_HASH</b>(alg)</td></tr>
+<tr class="separator:gae6b0b87aabe82a1b3113824f022c52e8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga85fe668f95a1e65b573dc5acb798be6f"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_HKDF_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x30000100)</td></tr>
+<tr class="separator:ga85fe668f95a1e65b573dc5acb798be6f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga32a888fb360e6e25cab8a343772c4a82"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga32a888fb360e6e25cab8a343772c4a82">PSA_ALG_HKDF</a>(hash_alg)   (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga32a888fb360e6e25cab8a343772c4a82"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1979d0a76fcee6164cf2e65960f38db2"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga1979d0a76fcee6164cf2e65960f38db2">PSA_ALG_IS_HKDF</a>(alg)   (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE)</td></tr>
+<tr class="separator:ga1979d0a76fcee6164cf2e65960f38db2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga643df48b529b176995927b697ff07a4c"><td class="memItemLeft" align="right" valign="top">
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_HKDF_GET_HASH</b>(hkdf_alg)   (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga643df48b529b176995927b697ff07a4c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7dddccdd1303176e87a4d20c87b589ed"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga7dddccdd1303176e87a4d20c87b589ed">PSA_KEY_USAGE_EXPORT</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000001)</td></tr>
+<tr class="separator:ga7dddccdd1303176e87a4d20c87b589ed"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga75153b296d045d529d97203a6a995dad"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga75153b296d045d529d97203a6a995dad">PSA_KEY_USAGE_ENCRYPT</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000100)</td></tr>
+<tr class="separator:ga75153b296d045d529d97203a6a995dad"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac3f2d2e5983db1edde9f142ca9bf8e6a"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gac3f2d2e5983db1edde9f142ca9bf8e6a">PSA_KEY_USAGE_DECRYPT</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000200)</td></tr>
+<tr class="separator:gac3f2d2e5983db1edde9f142ca9bf8e6a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga99b9f456cf59efc4b5579465407aef5a"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga99b9f456cf59efc4b5579465407aef5a">PSA_KEY_USAGE_SIGN</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000400)</td></tr>
+<tr class="separator:ga99b9f456cf59efc4b5579465407aef5a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga39b54ffd5958b69634607924fa53cea6"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga39b54ffd5958b69634607924fa53cea6">PSA_KEY_USAGE_VERIFY</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000800)</td></tr>
+<tr class="separator:ga39b54ffd5958b69634607924fa53cea6"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf19022acc5ef23cf12477f632b48a0b2"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gaf19022acc5ef23cf12477f632b48a0b2">PSA_KEY_USAGE_DERIVE</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00001000)</td></tr>
+<tr class="separator:gaf19022acc5ef23cf12477f632b48a0b2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8b438870ba69489b685730d346455108"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#ga8b438870ba69489b685730d346455108">PSA_KEY_LIFETIME_VOLATILE</a>   ((<a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a>)0x00000000)</td></tr>
+<tr class="separator:ga8b438870ba69489b685730d346455108"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3713a01c5fcd5f7eae46ff22ceaf6d02"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#ga3713a01c5fcd5f7eae46ff22ceaf6d02">PSA_KEY_LIFETIME_PERSISTENT</a>   ((<a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a>)0x00000001)</td></tr>
+<tr class="separator:ga3713a01c5fcd5f7eae46ff22ceaf6d02"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae6b8443238ef1900cf132550d7df557f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#gae6b8443238ef1900cf132550d7df557f">PSA_KEY_LIFETIME_WRITE_ONCE</a>   ((<a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a>)0x7fffffff)</td></tr>
+<tr class="separator:gae6b8443238ef1900cf132550d7df557f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaef340331ce3cba2b57e1fc5624bf1f99"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99">PSA_HASH_SIZE</a>(alg)</td></tr>
+<tr class="separator:gaef340331ce3cba2b57e1fc5624bf1f99"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga337ef01fe3c9f71d62ccced33e8917f4"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4">PSA_AEAD_TAG_SIZE</a>(alg)</td></tr>
+<tr class="separator:ga337ef01fe3c9f71d62ccced33e8917f4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga10c472a35f04051add6b20cc228ffc11"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__asymmetric.html#ga10c472a35f04051add6b20cc228ffc11">PSA_ECDSA_SIGNATURE_SIZE</a>(curve_bits)   (PSA_BITS_TO_BYTES(curve_bits) * 2)</td></tr>
+<tr class="memdesc:ga10c472a35f04051add6b20cc228ffc11"><td class="mdescLeft"> </td><td class="mdescRight">ECDSA signature size for a given curve bit size. <a href="group__asymmetric.html#ga10c472a35f04051add6b20cc228ffc11">More...</a><br /></td></tr>
+<tr class="separator:ga10c472a35f04051add6b20cc228ffc11"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaec0bcba60e7514b83f967b171d494ed3"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_RSA_MINIMUM_PADDING_SIZE</b>(alg)</td></tr>
+<tr class="separator:gaec0bcba60e7514b83f967b171d494ed3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4788b471385fc667876fbd8a0d3fe062"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#ga4788b471385fc667876fbd8a0d3fe062">PSA_CRYPTO_GENERATOR_INIT</a>   {0}</td></tr>
+<tr class="separator:ga4788b471385fc667876fbd8a0d3fe062"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:gac3da92a6b8a7f0c01dc348f8e0432e4c"><td class="memItemLeft" align="right" valign="top">typedef _unsigned_integral_type_ </td><td class="memItemRight" valign="bottom"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a></td></tr>
+<tr class="memdesc:gac3da92a6b8a7f0c01dc348f8e0432e4c"><td class="mdescLeft"> </td><td class="mdescRight">Key slot number. <a href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">More...</a><br /></td></tr>
+<tr class="separator:gac3da92a6b8a7f0c01dc348f8e0432e4c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga05676e70ba5c6a7565aff3c36677c1f9"><td class="memItemLeft" align="right" valign="top">typedef int32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a></td></tr>
+<tr class="memdesc:ga05676e70ba5c6a7565aff3c36677c1f9"><td class="mdescLeft"> </td><td class="mdescRight">Function return status. <a href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">More...</a><br /></td></tr>
+<tr class="separator:ga05676e70ba5c6a7565aff3c36677c1f9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga578159487dfc7096cb191b0d2befe628"><td class="memItemLeft" align="right" valign="top">
+typedef uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a></td></tr>
+<tr class="memdesc:ga578159487dfc7096cb191b0d2befe628"><td class="mdescLeft"> </td><td class="mdescRight">Encoding of a key type. <br /></td></tr>
+<tr class="separator:ga578159487dfc7096cb191b0d2befe628"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4e8977c145cce5077c4bce7fec890ad9"><td class="memItemLeft" align="right" valign="top">typedef uint16_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a></td></tr>
+<tr class="separator:ga4e8977c145cce5077c4bce7fec890ad9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac2e4d47f1300d73c2f829a6d99252d69"><td class="memItemLeft" align="right" valign="top">typedef uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a></td></tr>
+<tr class="memdesc:gac2e4d47f1300d73c2f829a6d99252d69"><td class="mdescLeft"> </td><td class="mdescRight">Encoding of a cryptographic algorithm. <a href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">More...</a><br /></td></tr>
+<tr class="separator:gac2e4d47f1300d73c2f829a6d99252d69"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7bb9de71337e0e98de843aa7f9b55f25"><td class="memItemLeft" align="right" valign="top">
+typedef uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a></td></tr>
+<tr class="memdesc:ga7bb9de71337e0e98de843aa7f9b55f25"><td class="mdescLeft"> </td><td class="mdescRight">Encoding of permitted usage on a key. <br /></td></tr>
+<tr class="separator:ga7bb9de71337e0e98de843aa7f9b55f25"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf553efd409845b6d09ff25ce2ba36607"><td class="memItemLeft" align="right" valign="top">typedef struct psa_key_policy_s </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a></td></tr>
+<tr class="separator:gaf553efd409845b6d09ff25ce2ba36607"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6821ff6dd39dc2bc370ded760ad8b0cf"><td class="memItemLeft" align="right" valign="top">typedef uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a></td></tr>
+<tr class="separator:ga6821ff6dd39dc2bc370ded760ad8b0cf"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3c4205d2ce66c4095fc5c78c25273fab"><td class="memItemLeft" align="right" valign="top">typedef struct psa_hash_operation_s </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a></td></tr>
+<tr class="separator:ga3c4205d2ce66c4095fc5c78c25273fab"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga78f0838b0c4e3db28b26355624d4bd37"><td class="memItemLeft" align="right" valign="top">typedef struct psa_mac_operation_s </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a></td></tr>
+<tr class="separator:ga78f0838b0c4e3db28b26355624d4bd37"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1399de29db657e3737bb09927aae51fa"><td class="memItemLeft" align="right" valign="top">typedef struct psa_cipher_operation_s </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a></td></tr>
+<tr class="separator:ga1399de29db657e3737bb09927aae51fa"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1f894c4fba202ef8e307d72caf489e3b"><td class="memItemLeft" align="right" valign="top">typedef struct psa_crypto_generator_s </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a></td></tr>
+<tr class="separator:ga1f894c4fba202ef8e307d72caf489e3b"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga2de150803fc2f7dc6101d5af7e921dd9"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga2de150803fc2f7dc6101d5af7e921dd9">psa_crypto_init</a> (void)</td></tr>
+<tr class="memdesc:ga2de150803fc2f7dc6101d5af7e921dd9"><td class="mdescLeft"> </td><td class="mdescRight">Library initialization. <a href="group__basic.html#ga2de150803fc2f7dc6101d5af7e921dd9">More...</a><br /></td></tr>
+<tr class="separator:ga2de150803fc2f7dc6101d5af7e921dd9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gace37363530e2525a2562f07ceec8efb5"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5">psa_import_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> type, const uint8_t *data, size_t data_length)</td></tr>
+<tr class="memdesc:gace37363530e2525a2562f07ceec8efb5"><td class="mdescLeft"> </td><td class="mdescRight">Import a key in binary format. <a href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5">More...</a><br /></td></tr>
+<tr class="separator:gace37363530e2525a2562f07ceec8efb5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2e9a60a9525ce6b3082a72df2080f0c5"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__key__management.html#ga2e9a60a9525ce6b3082a72df2080f0c5">psa_destroy_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key)</td></tr>
+<tr class="memdesc:ga2e9a60a9525ce6b3082a72df2080f0c5"><td class="mdescLeft"> </td><td class="mdescRight">Destroy a key and restore the slot to its default state. <a href="group__key__management.html#ga2e9a60a9525ce6b3082a72df2080f0c5">More...</a><br /></td></tr>
+<tr class="separator:ga2e9a60a9525ce6b3082a72df2080f0c5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf105167657ab1d484cb4a51f93413717"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__key__management.html#gaf105167657ab1d484cb4a51f93413717">psa_get_key_information</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> *type, size_t *bits)</td></tr>
+<tr class="memdesc:gaf105167657ab1d484cb4a51f93413717"><td class="mdescLeft"> </td><td class="mdescRight">Get basic metadata about a key. <a href="group__key__management.html#gaf105167657ab1d484cb4a51f93413717">More...</a><br /></td></tr>
+<tr class="separator:gaf105167657ab1d484cb4a51f93413717"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa67bc459b20028b268f3d75a05afe022"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__key__management.html#gaa67bc459b20028b268f3d75a05afe022">psa_export_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, uint8_t *data, size_t data_size, size_t *data_length)</td></tr>
+<tr class="memdesc:gaa67bc459b20028b268f3d75a05afe022"><td class="mdescLeft"> </td><td class="mdescRight">Export a key in binary format. <a href="group__key__management.html#gaa67bc459b20028b268f3d75a05afe022">More...</a><br /></td></tr>
+<tr class="separator:gaa67bc459b20028b268f3d75a05afe022"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7355b38f8eb9330db2786604f4a83a3b"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__key__management.html#ga7355b38f8eb9330db2786604f4a83a3b">psa_export_public_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, uint8_t *data, size_t data_size, size_t *data_length)</td></tr>
+<tr class="memdesc:ga7355b38f8eb9330db2786604f4a83a3b"><td class="mdescLeft"> </td><td class="mdescRight">Export a public key or the public part of a key pair in binary format. <a href="group__key__management.html#ga7355b38f8eb9330db2786604f4a83a3b">More...</a><br /></td></tr>
+<tr class="separator:ga7355b38f8eb9330db2786604f4a83a3b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad49eb85e3fcbe70f763f511ac83e762e"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gad49eb85e3fcbe70f763f511ac83e762e">psa_key_policy_init</a> (<a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy)</td></tr>
+<tr class="memdesc:gad49eb85e3fcbe70f763f511ac83e762e"><td class="mdescLeft"> </td><td class="mdescRight">Initialize a key policy structure to a default that forbids all usage of the key. <a href="group__policy.html#gad49eb85e3fcbe70f763f511ac83e762e">More...</a><br /></td></tr>
+<tr class="separator:gad49eb85e3fcbe70f763f511ac83e762e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac16792fd6d375a5f76d372090df40607"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gac16792fd6d375a5f76d372090df40607">psa_key_policy_set_usage</a> (<a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy, <a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a> usage, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="memdesc:gac16792fd6d375a5f76d372090df40607"><td class="mdescLeft"> </td><td class="mdescRight">Set the standard fields of a policy structure. <a href="group__policy.html#gac16792fd6d375a5f76d372090df40607">More...</a><br /></td></tr>
+<tr class="separator:gac16792fd6d375a5f76d372090df40607"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7746662b7503e484774d0ecb5d8ac2ab"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga7746662b7503e484774d0ecb5d8ac2ab">psa_key_policy_get_usage</a> (const <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy)</td></tr>
+<tr class="memdesc:ga7746662b7503e484774d0ecb5d8ac2ab"><td class="mdescLeft"> </td><td class="mdescRight">Retrieve the usage field of a policy structure. <a href="group__policy.html#ga7746662b7503e484774d0ecb5d8ac2ab">More...</a><br /></td></tr>
+<tr class="separator:ga7746662b7503e484774d0ecb5d8ac2ab"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaadf16b89ace53e1d2cb5bcb0aef24c86"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gaadf16b89ace53e1d2cb5bcb0aef24c86">psa_key_policy_get_algorithm</a> (const <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy)</td></tr>
+<tr class="memdesc:gaadf16b89ace53e1d2cb5bcb0aef24c86"><td class="mdescLeft"> </td><td class="mdescRight">Retrieve the algorithm field of a policy structure. <a href="group__policy.html#gaadf16b89ace53e1d2cb5bcb0aef24c86">More...</a><br /></td></tr>
+<tr class="separator:gaadf16b89ace53e1d2cb5bcb0aef24c86"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad7faa7e64aa771f7441c44ceff21af19"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gad7faa7e64aa771f7441c44ceff21af19">psa_set_key_policy</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, const <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy)</td></tr>
+<tr class="memdesc:gad7faa7e64aa771f7441c44ceff21af19"><td class="mdescLeft"> </td><td class="mdescRight">Set the usage policy on a key slot. <a href="group__policy.html#gad7faa7e64aa771f7441c44ceff21af19">More...</a><br /></td></tr>
+<tr class="separator:gad7faa7e64aa771f7441c44ceff21af19"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga613f28712124f9149bd640614376ab5a"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga613f28712124f9149bd640614376ab5a">psa_get_key_policy</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy)</td></tr>
+<tr class="memdesc:ga613f28712124f9149bd640614376ab5a"><td class="mdescLeft"> </td><td class="mdescRight">Get the usage policy for a key slot. <a href="group__policy.html#ga613f28712124f9149bd640614376ab5a">More...</a><br /></td></tr>
+<tr class="separator:ga613f28712124f9149bd640614376ab5a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf0daaa1dba14dc324ca83dfe1495a5e2"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#gaf0daaa1dba14dc324ca83dfe1495a5e2">psa_get_key_lifetime</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a> *lifetime)</td></tr>
+<tr class="memdesc:gaf0daaa1dba14dc324ca83dfe1495a5e2"><td class="mdescLeft"> </td><td class="mdescRight">Retrieve the lifetime of a key slot. <a href="group__persistence.html#gaf0daaa1dba14dc324ca83dfe1495a5e2">More...</a><br /></td></tr>
+<tr class="separator:gaf0daaa1dba14dc324ca83dfe1495a5e2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1bd1ee6d00ebd9962fc6ad72cbd22ef8"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8">psa_set_key_lifetime</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a> lifetime)</td></tr>
+<tr class="memdesc:ga1bd1ee6d00ebd9962fc6ad72cbd22ef8"><td class="mdescLeft"> </td><td class="mdescRight">Change the lifetime of a key slot. <a href="group__persistence.html#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8">More...</a><br /></td></tr>
+<tr class="separator:ga1bd1ee6d00ebd9962fc6ad72cbd22ef8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8d72896cf70fc4d514c5c6b978912515"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup</a> (<a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="separator:ga8d72896cf70fc4d514c5c6b978912515"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga65b16ef97d7f650899b7db4b7d1112ff"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">psa_hash_update</a> (<a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation, const uint8_t *input, size_t input_length)</td></tr>
+<tr class="separator:ga65b16ef97d7f650899b7db4b7d1112ff"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4795fd06a0067b0adcd92e9627b8c97e"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">psa_hash_finish</a> (<a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation, uint8_t *hash, size_t hash_size, size_t *hash_length)</td></tr>
+<tr class="separator:ga4795fd06a0067b0adcd92e9627b8c97e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7be923c5700c9c70ef77ee9b76d1a5c0"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">psa_hash_verify</a> (<a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation, const uint8_t *hash, size_t hash_length)</td></tr>
+<tr class="separator:ga7be923c5700c9c70ef77ee9b76d1a5c0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab0b4d5f9912a615559497a467b532928"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#gab0b4d5f9912a615559497a467b532928">psa_hash_abort</a> (<a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation)</td></tr>
+<tr class="separator:gab0b4d5f9912a615559497a467b532928"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga68ac2ad3253e9e27fcfbc788a4df8177"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation, <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="separator:ga68ac2ad3253e9e27fcfbc788a4df8177"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac7d1c3d075ce1604a54cbbc9933fa39d"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation, <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="separator:gac7d1c3d075ce1604a54cbbc9933fa39d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5560af371497babefe03c9da4e8a1c05"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">psa_mac_update</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation, const uint8_t *input, size_t input_length)</td></tr>
+<tr class="separator:ga5560af371497babefe03c9da4e8a1c05"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac22bc0125580c96724a09226cfbc97f2"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#gac22bc0125580c96724a09226cfbc97f2">psa_mac_sign_finish</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation, uint8_t *mac, size_t mac_size, size_t *mac_length)</td></tr>
+<tr class="separator:gac22bc0125580c96724a09226cfbc97f2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac92b2930d6728e1be4d011c05d485822"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">psa_mac_verify_finish</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation, const uint8_t *mac, size_t mac_length)</td></tr>
+<tr class="separator:gac92b2930d6728e1be4d011c05d485822"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gacd8dd54855ba1bc0a03f104f252884fd"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">psa_mac_abort</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation)</td></tr>
+<tr class="separator:gacd8dd54855ba1bc0a03f104f252884fd"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga735c9d51b820e1d4cb45f2406ebfae98"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="separator:ga735c9d51b820e1d4cb45f2406ebfae98"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8ce1efaa648d7e0dd00e878d655d2950"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="separator:ga8ce1efaa648d7e0dd00e878d655d2950"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga44857cf5e0c3d134a3c560f8ff5b50aa"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">psa_cipher_generate_iv</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, unsigned char *iv, size_t iv_size, size_t *iv_length)</td></tr>
+<tr class="separator:ga44857cf5e0c3d134a3c560f8ff5b50aa"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1359b2101f31637496ce7cc36c6e3d42"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42">psa_cipher_set_iv</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, const unsigned char *iv, size_t iv_length)</td></tr>
+<tr class="separator:ga1359b2101f31637496ce7cc36c6e3d42"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafd0caea99cf1052527e4089d37f5ab91"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, const uint8_t *input, size_t input_length, unsigned char *output, size_t output_size, size_t *output_length)</td></tr>
+<tr class="separator:gafd0caea99cf1052527e4089d37f5ab91"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1dcb58b8befe23f8a4d7a1d49c99249b"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">psa_cipher_finish</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, uint8_t *output, size_t output_size, size_t *output_length)</td></tr>
+<tr class="separator:ga1dcb58b8befe23f8a4d7a1d49c99249b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaad482cdca2098bca0620596aaa02eaa4"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">psa_cipher_abort</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation)</td></tr>
+<tr class="separator:gaad482cdca2098bca0620596aaa02eaa4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga14e4068a3d328515a4884f3037904d54"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__aead.html#ga14e4068a3d328515a4884f3037904d54">psa_aead_encrypt</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)</td></tr>
+<tr class="separator:ga14e4068a3d328515a4884f3037904d54"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5b88ad2cfbf2e98039858416fa3ebd7a"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__aead.html#ga5b88ad2cfbf2e98039858416fa3ebd7a">psa_aead_decrypt</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)</td></tr>
+<tr class="separator:ga5b88ad2cfbf2e98039858416fa3ebd7a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga48091460d1ead078d93caa3611aec976"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__asymmetric.html#ga48091460d1ead078d93caa3611aec976">psa_asymmetric_sign</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length)</td></tr>
+<tr class="memdesc:ga48091460d1ead078d93caa3611aec976"><td class="mdescLeft"> </td><td class="mdescRight">Sign a hash or short message with a private key. <a href="group__asymmetric.html#ga48091460d1ead078d93caa3611aec976">More...</a><br /></td></tr>
+<tr class="separator:ga48091460d1ead078d93caa3611aec976"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaee3e92946c1c4b3dfa90879e2f7d1321"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__asymmetric.html#gaee3e92946c1c4b3dfa90879e2f7d1321">psa_asymmetric_verify</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length)</td></tr>
+<tr class="memdesc:gaee3e92946c1c4b3dfa90879e2f7d1321"><td class="mdescLeft"> </td><td class="mdescRight">Verify the signature a hash or short message using a public key. <a href="group__asymmetric.html#gaee3e92946c1c4b3dfa90879e2f7d1321">More...</a><br /></td></tr>
+<tr class="separator:gaee3e92946c1c4b3dfa90879e2f7d1321"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3c0ba402bac217d623dba8320c2240c2"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2">psa_asymmetric_encrypt</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length)</td></tr>
+<tr class="memdesc:ga3c0ba402bac217d623dba8320c2240c2"><td class="mdescLeft"> </td><td class="mdescRight">Encrypt a short message with a public key. <a href="group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2">More...</a><br /></td></tr>
+<tr class="separator:ga3c0ba402bac217d623dba8320c2240c2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3094be979f37aa2865c283167ba907e6"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6">psa_asymmetric_decrypt</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length)</td></tr>
+<tr class="memdesc:ga3094be979f37aa2865c283167ba907e6"><td class="mdescLeft"> </td><td class="mdescRight">Decrypt a short message with a private key. <a href="group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6">More...</a><br /></td></tr>
+<tr class="separator:ga3094be979f37aa2865c283167ba907e6"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7453491e3b440193be2c5dccc2040fd2"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#ga7453491e3b440193be2c5dccc2040fd2">psa_get_generator_capacity</a> (const <a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator, size_t *capacity)</td></tr>
+<tr class="separator:ga7453491e3b440193be2c5dccc2040fd2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab5712ad29b78c2b170e64cc5bcfc1bce"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#gab5712ad29b78c2b170e64cc5bcfc1bce">psa_generator_read</a> (<a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator, uint8_t *output, size_t output_length)</td></tr>
+<tr class="separator:gab5712ad29b78c2b170e64cc5bcfc1bce"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga06c1ba3d989827d909b4b01ffe983beb"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#ga06c1ba3d989827d909b4b01ffe983beb">psa_generator_import_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> type, size_t bits, <a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator)</td></tr>
+<tr class="separator:ga06c1ba3d989827d909b4b01ffe983beb"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga563ca64537d90368899286b36d8cf7f3"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#ga563ca64537d90368899286b36d8cf7f3">psa_generator_abort</a> (<a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator)</td></tr>
+<tr class="separator:ga563ca64537d90368899286b36d8cf7f3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1b6429f443a45e5f3209043abbbe8315"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__derivation.html#ga1b6429f443a45e5f3209043abbbe8315">psa_key_derivation</a> (<a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator, <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *salt, size_t salt_length, const uint8_t *label, size_t label_length, size_t capacity)</td></tr>
+<tr class="separator:ga1b6429f443a45e5f3209043abbbe8315"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1985eae417dfbccedf50d5fff54ea8c5"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__random.html#ga1985eae417dfbccedf50d5fff54ea8c5">psa_generate_random</a> (uint8_t *output, size_t output_size)</td></tr>
+<tr class="memdesc:ga1985eae417dfbccedf50d5fff54ea8c5"><td class="mdescLeft"> </td><td class="mdescRight">Generate random bytes. <a href="group__random.html#ga1985eae417dfbccedf50d5fff54ea8c5">More...</a><br /></td></tr>
+<tr class="separator:ga1985eae417dfbccedf50d5fff54ea8c5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gada1d701903f6b4de6b4c6a1d613c1b10"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10">psa_generate_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> type, size_t bits, const void *extra, size_t extra_size)</td></tr>
+<tr class="memdesc:gada1d701903f6b4de6b4c6a1d613c1b10"><td class="mdescLeft"> </td><td class="mdescRight">Generate a key or key pair. <a href="group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10">More...</a><br /></td></tr>
+<tr class="separator:gada1d701903f6b4de6b4c6a1d613c1b10"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Platform Security Architecture cryptography module. </p>
+</div></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/crypto_8h__incl.map b/docs/html/crypto_8h__incl.map
new file mode 100644
index 0000000..d8aa9bc
--- /dev/null
+++ b/docs/html/crypto_8h__incl.map
@@ -0,0 +1,3 @@
+<map id="psa/crypto.h" name="psa/crypto.h">
+<area shape="rect" id="node8" href="$crypto__sizes_8h.html" title="PSA cryptography module: Mbed TLS buffer size macros. " alt="" coords="796,95,903,121"/>
+</map>
diff --git a/docs/html/crypto_8h__incl.md5 b/docs/html/crypto_8h__incl.md5
new file mode 100644
index 0000000..d11e262
--- /dev/null
+++ b/docs/html/crypto_8h__incl.md5
@@ -0,0 +1 @@
+d9998ce66e171c5acfcfddb2e96bbd47
\ No newline at end of file
diff --git a/docs/html/crypto_8h__incl.png b/docs/html/crypto_8h__incl.png
new file mode 100644
index 0000000..2a4a765
--- /dev/null
+++ b/docs/html/crypto_8h__incl.png
Binary files differ
diff --git a/docs/html/crypto_8h_source.html b/docs/html/crypto_8h_source.html
new file mode 100644
index 0000000..9a24d78
--- /dev/null
+++ b/docs/html/crypto_8h_source.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: psa/crypto.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_7dae9cfde651cd3cb034485ce5e391b9.html">psa</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">crypto.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="crypto_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span> </div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span> <span class="comment">/*</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span> <span class="comment"> * Copyright (C) 2018, ARM Limited, All Rights Reserved</span></div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span> <span class="comment"> * SPDX-License-Identifier: Apache-2.0</span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span> <span class="comment"> *</span></div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span> <span class="comment"> * Licensed under the Apache License, Version 2.0 (the "License"); you may</span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span> <span class="comment"> * not use this file except in compliance with the License.</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span> <span class="comment"> * You may obtain a copy of the License at</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span> <span class="comment"> *</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span> <span class="comment"> * http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span> <span class="comment"> *</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span> <span class="comment"> * Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span> <span class="comment"> * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT</span></div><div class="line"><a name="l00017"></a><span class="lineno"> 17</span> <span class="comment"> * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00018"></a><span class="lineno"> 18</span> <span class="comment"> * See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00019"></a><span class="lineno"> 19</span> <span class="comment"> * limitations under the License.</span></div><div class="line"><a name="l00020"></a><span class="lineno"> 20</span> <span class="comment"> */</span></div><div class="line"><a name="l00021"></a><span class="lineno"> 21</span> </div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span> <span class="preprocessor">#ifndef PSA_CRYPTO_H</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span> <span class="preprocessor">#define PSA_CRYPTO_H</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span> </div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span> <span class="preprocessor">#include "crypto_platform.h"</span></div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span> </div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span> <span class="preprocessor">#include <stddef.h></span></div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span> </div><div class="line"><a name="l00029"></a><span class="lineno"> 29</span> <span class="preprocessor">#ifdef __DOXYGEN_ONLY__</span></div><div class="line"><a name="l00030"></a><span class="lineno"> 30</span> <span class="comment">/* This __DOXYGEN_ONLY__ block contains mock definitions for things that</span></div><div class="line"><a name="l00031"></a><span class="lineno"> 31</span> <span class="comment"> * must be defined in the crypto_platform.h header. These mock definitions</span></div><div class="line"><a name="l00032"></a><span class="lineno"> 32</span> <span class="comment"> * are present in this file as a convenience to generate pretty-printed</span></div><div class="line"><a name="l00033"></a><span class="lineno"> 33</span> <span class="comment"> * documentation that includes those definitions. */</span></div><div class="line"><a name="l00034"></a><span class="lineno"> 34</span> </div><div class="line"><a name="l00051"></a><span class="lineno"><a class="line" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c"> 51</a></span> <span class="keyword">typedef</span> _unsigned_integral_type_ <a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a>;</div><div class="line"><a name="l00052"></a><span class="lineno"> 52</span> </div><div class="line"><a name="l00054"></a><span class="lineno"> 54</span> <span class="preprocessor">#endif </span><span class="comment">/* __DOXYGEN_ONLY__ */</span><span class="preprocessor"></span></div><div class="line"><a name="l00055"></a><span class="lineno"> 55</span> </div><div class="line"><a name="l00056"></a><span class="lineno"> 56</span> <span class="preprocessor">#ifdef __cplusplus</span></div><div class="line"><a name="l00057"></a><span class="lineno"> 57</span> <span class="keyword">extern</span> <span class="stringliteral">"C"</span> {</div><div class="line"><a name="l00058"></a><span class="lineno"> 58</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00059"></a><span class="lineno"> 59</span> </div><div class="line"><a name="l00064"></a><span class="lineno"> 64</span> <span class="preprocessor">#if defined(PSA_SUCCESS)</span></div><div class="line"><a name="l00065"></a><span class="lineno"> 65</span> <span class="comment">/* If PSA_SUCCESS is defined, assume that PSA crypto is being used</span></div><div class="line"><a name="l00066"></a><span class="lineno"> 66</span> <span class="comment"> * together with PSA IPC, which also defines the identifier</span></div><div class="line"><a name="l00067"></a><span class="lineno"> 67</span> <span class="comment"> * PSA_SUCCESS. We must not define PSA_SUCCESS ourselves in that case;</span></div><div class="line"><a name="l00068"></a><span class="lineno"> 68</span> <span class="comment"> * the other error code names don't clash. Also define psa_status_t as</span></div><div class="line"><a name="l00069"></a><span class="lineno"> 69</span> <span class="comment"> * an alias for the type used by PSA IPC. This is a temporary hack</span></div><div class="line"><a name="l00070"></a><span class="lineno"> 70</span> <span class="comment"> * until we unify error reporting in PSA IPC and PSA crypto.</span></div><div class="line"><a name="l00071"></a><span class="lineno"> 71</span> <span class="comment"> *</span></div><div class="line"><a name="l00072"></a><span class="lineno"> 72</span> <span class="comment"> * Note that psa_defs.h must be included before this header!</span></div><div class="line"><a name="l00073"></a><span class="lineno"> 73</span> <span class="comment"> */</span></div><div class="line"><a name="l00074"></a><span class="lineno"> 74</span> <span class="keyword">typedef</span> psa_error_t <a class="code" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>;</div><div class="line"><a name="l00075"></a><span class="lineno"> 75</span> </div><div class="line"><a name="l00076"></a><span class="lineno"> 76</span> <span class="preprocessor">#else </span><span class="comment">/* defined(PSA_SUCCESS) */</span><span class="preprocessor"></span></div><div class="line"><a name="l00077"></a><span class="lineno"> 77</span> </div><div class="line"><a name="l00085"></a><span class="lineno"><a class="line" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9"> 85</a></span> <span class="keyword">typedef</span> int32_t <a class="code" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>;</div><div class="line"><a name="l00086"></a><span class="lineno"> 86</span> </div><div class="line"><a name="l00088"></a><span class="lineno"><a class="line" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1"> 88</a></span> <span class="preprocessor">#define PSA_SUCCESS ((psa_status_t)0)</span></div><div class="line"><a name="l00089"></a><span class="lineno"> 89</span> </div><div class="line"><a name="l00090"></a><span class="lineno"> 90</span> <span class="preprocessor">#endif </span><span class="comment">/* !defined(PSA_SUCCESS) */</span><span class="preprocessor"></span></div><div class="line"><a name="l00091"></a><span class="lineno"> 91</span> </div><div class="line"><a name="l00097"></a><span class="lineno"><a class="line" href="group__basic.html#ga24d5fdcdd759f846f79d9e581c63a83f"> 97</a></span> <span class="preprocessor">#define PSA_ERROR_UNKNOWN_ERROR ((psa_status_t)1)</span></div><div class="line"><a name="l00098"></a><span class="lineno"> 98</span> </div><div class="line"><a name="l00106"></a><span class="lineno"><a class="line" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd"> 106</a></span> <span class="preprocessor">#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)2)</span></div><div class="line"><a name="l00107"></a><span class="lineno"> 107</span> </div><div class="line"><a name="l00119"></a><span class="lineno"><a class="line" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1"> 119</a></span> <span class="preprocessor">#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)3)</span></div><div class="line"><a name="l00120"></a><span class="lineno"> 120</span> </div><div class="line"><a name="l00131"></a><span class="lineno"><a class="line" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8"> 131</a></span> <span class="preprocessor">#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)4)</span></div><div class="line"><a name="l00132"></a><span class="lineno"> 132</span> </div><div class="line"><a name="l00139"></a><span class="lineno"><a class="line" href="group__basic.html#gac2fee3a51249fbea45360aaa911f3e58"> 139</a></span> <span class="preprocessor">#define PSA_ERROR_OCCUPIED_SLOT ((psa_status_t)5)</span></div><div class="line"><a name="l00140"></a><span class="lineno"> 140</span> </div><div class="line"><a name="l00147"></a><span class="lineno"><a class="line" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040"> 147</a></span> <span class="preprocessor">#define PSA_ERROR_EMPTY_SLOT ((psa_status_t)6)</span></div><div class="line"><a name="l00148"></a><span class="lineno"> 148</span> </div><div class="line"><a name="l00159"></a><span class="lineno"><a class="line" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84"> 159</a></span> <span class="preprocessor">#define PSA_ERROR_BAD_STATE ((psa_status_t)7)</span></div><div class="line"><a name="l00160"></a><span class="lineno"> 160</span> </div><div class="line"><a name="l00170"></a><span class="lineno"><a class="line" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f"> 170</a></span> <span class="preprocessor">#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)8)</span></div><div class="line"><a name="l00171"></a><span class="lineno"> 171</span> </div><div class="line"><a name="l00176"></a><span class="lineno"><a class="line" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5"> 176</a></span> <span class="preprocessor">#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)9)</span></div><div class="line"><a name="l00177"></a><span class="lineno"> 177</span> </div><div class="line"><a name="l00185"></a><span class="lineno"><a class="line" href="group__basic.html#ga897a45eb206a6f6b7be7ffbe36f0d766"> 185</a></span> <span class="preprocessor">#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)10)</span></div><div class="line"><a name="l00186"></a><span class="lineno"> 186</span> </div><div class="line"><a name="l00202"></a><span class="lineno"><a class="line" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7"> 202</a></span> <span class="preprocessor">#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)11)</span></div><div class="line"><a name="l00203"></a><span class="lineno"> 203</span> </div><div class="line"><a name="l00227"></a><span class="lineno"><a class="line" href="group__basic.html#gadd169a1af2707862b95fb9df91dfc37d"> 227</a></span> <span class="preprocessor">#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)12)</span></div><div class="line"><a name="l00228"></a><span class="lineno"> 228</span> </div><div class="line"><a name="l00233"></a><span class="lineno"><a class="line" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b"> 233</a></span> <span class="preprocessor">#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)13)</span></div><div class="line"><a name="l00234"></a><span class="lineno"> 234</span> </div><div class="line"><a name="l00264"></a><span class="lineno"><a class="line" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004"> 264</a></span> <span class="preprocessor">#define PSA_ERROR_TAMPERING_DETECTED ((psa_status_t)14)</span></div><div class="line"><a name="l00265"></a><span class="lineno"> 265</span> </div><div class="line"><a name="l00283"></a><span class="lineno"><a class="line" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675"> 283</a></span> <span class="preprocessor">#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)15)</span></div><div class="line"><a name="l00284"></a><span class="lineno"> 284</span> </div><div class="line"><a name="l00293"></a><span class="lineno"><a class="line" href="group__basic.html#ga35927f755d232c4766de600f2c49e9f2"> 293</a></span> <span class="preprocessor">#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)16)</span></div><div class="line"><a name="l00294"></a><span class="lineno"> 294</span> </div><div class="line"><a name="l00309"></a><span class="lineno"><a class="line" href="group__basic.html#gabe29594edbfb152cf153975b0597ac48"> 309</a></span> <span class="preprocessor">#define PSA_ERROR_INVALID_PADDING ((psa_status_t)17)</span></div><div class="line"><a name="l00310"></a><span class="lineno"> 310</span> </div><div class="line"><a name="l00315"></a><span class="lineno"><a class="line" href="group__basic.html#gaf1fa61f72e9e5b4a848c991bea495767"> 315</a></span> <span class="preprocessor">#define PSA_ERROR_INSUFFICIENT_CAPACITY ((psa_status_t)18)</span></div><div class="line"><a name="l00316"></a><span class="lineno"> 316</span> </div><div class="line"><a name="l00333"></a><span class="lineno"> 333</span> psa_status_t <a class="code" href="group__basic.html#ga2de150803fc2f7dc6101d5af7e921dd9">psa_crypto_init</a>(<span class="keywordtype">void</span>);</div><div class="line"><a name="l00334"></a><span class="lineno"> 334</span> </div><div class="line"><a name="l00335"></a><span class="lineno"> 335</span> <span class="preprocessor">#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8)</span></div><div class="line"><a name="l00336"></a><span class="lineno"> 336</span> <span class="preprocessor">#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8)</span></div><div class="line"><a name="l00337"></a><span class="lineno"> 337</span> </div><div class="line"><a name="l00346"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628"> 346</a></span> <span class="keyword">typedef</span> uint32_t <a class="code" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>;</div><div class="line"><a name="l00347"></a><span class="lineno"> 347</span> </div><div class="line"><a name="l00352"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gafce7ab2b54ce97ea5bff73f13a9f3e5b"> 352</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000)</span></div><div class="line"><a name="l00353"></a><span class="lineno"> 353</span> </div><div class="line"><a name="l00361"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7"> 361</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000)</span></div><div class="line"><a name="l00362"></a><span class="lineno"> 362</span> </div><div class="line"><a name="l00363"></a><span class="lineno"> 363</span> <span class="preprocessor">#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x7e000000)</span></div><div class="line"><a name="l00364"></a><span class="lineno"> 364</span> </div><div class="line"><a name="l00369"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gaa97f92025533102616b32d571c940d80"> 369</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x02000000)</span></div><div class="line"><a name="l00370"></a><span class="lineno"> 370</span> </div><div class="line"><a name="l00371"></a><span class="lineno"> 371</span> <span class="preprocessor">#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x04000000)</span></div><div class="line"><a name="l00372"></a><span class="lineno"> 372</span> <span class="preprocessor">#define PSA_KEY_TYPE_CATEGORY_ASYMMETRIC ((psa_key_type_t)0x06000000)</span></div><div class="line"><a name="l00373"></a><span class="lineno"> 373</span> <span class="preprocessor">#define PSA_KEY_TYPE_PAIR_FLAG ((psa_key_type_t)0x01000000)</span></div><div class="line"><a name="l00374"></a><span class="lineno"> 374</span> </div><div class="line"><a name="l00383"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga92d989f4ca64abd00f463defd773a6f8"> 383</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x02000001)</span></div><div class="line"><a name="l00384"></a><span class="lineno"> 384</span> </div><div class="line"><a name="l00390"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gae871b2357b8593f33bfd51abbf93ebb1"> 390</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x02000101)</span></div><div class="line"><a name="l00391"></a><span class="lineno"> 391</span> </div><div class="line"><a name="l00397"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga6ee54579dcf278c677eda4bb1a29575e"> 397</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x04000001)</span></div><div class="line"><a name="l00398"></a><span class="lineno"> 398</span> </div><div class="line"><a name="l00408"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga577562bfbbc691c820d55ec308333138"> 408</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x04000002)</span></div><div class="line"><a name="l00409"></a><span class="lineno"> 409</span> </div><div class="line"><a name="l00412"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gad8e5da742343fd5519f9d8a630c2ed81"> 412</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x04000003)</span></div><div class="line"><a name="l00413"></a><span class="lineno"> 413</span> </div><div class="line"><a name="l00418"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gae4d46e83f910dcaa126000a8ed03cde9"> 418</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x04000004)</span></div><div class="line"><a name="l00419"></a><span class="lineno"> 419</span> </div><div class="line"><a name="l00421"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b"> 421</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x06010000)</span></div><div class="line"><a name="l00422"></a><span class="lineno"> 422</span> </div><div class="line"><a name="l00423"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga581f50687f5d650456925278948f2799"> 423</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_RSA_KEYPAIR ((psa_key_type_t)0x07010000)</span></div><div class="line"><a name="l00424"></a><span class="lineno"> 424</span> </div><div class="line"><a name="l00426"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga5e7439c2905136366c3a876e62e5ddfc"> 426</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x06020000)</span></div><div class="line"><a name="l00427"></a><span class="lineno"> 427</span> </div><div class="line"><a name="l00428"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga011010ee28c20388f3d89fb27088ed62"> 428</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_DSA_KEYPAIR ((psa_key_type_t)0x07020000)</span></div><div class="line"><a name="l00429"></a><span class="lineno"> 429</span> </div><div class="line"><a name="l00430"></a><span class="lineno"> 430</span> <span class="preprocessor">#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x06030000)</span></div><div class="line"><a name="l00431"></a><span class="lineno"> 431</span> <span class="preprocessor">#define PSA_KEY_TYPE_ECC_KEYPAIR_BASE ((psa_key_type_t)0x07030000)</span></div><div class="line"><a name="l00432"></a><span class="lineno"> 432</span> <span class="preprocessor">#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff)</span></div><div class="line"><a name="l00433"></a><span class="lineno"> 433</span> </div><div class="line"><a name="l00434"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gadf3ad65d157bf5282849c954bf3f51af"> 434</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_ECC_KEYPAIR(curve) \</span></div><div class="line"><a name="l00435"></a><span class="lineno"> 435</span> <span class="preprocessor"> (PSA_KEY_TYPE_ECC_KEYPAIR_BASE | (curve))</span></div><div class="line"><a name="l00436"></a><span class="lineno"> 436</span> </div><div class="line"><a name="l00437"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gad54c03d3b47020e571a72cd01d978cf2"> 437</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \</span></div><div class="line"><a name="l00438"></a><span class="lineno"> 438</span> <span class="preprocessor"> (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve))</span></div><div class="line"><a name="l00439"></a><span class="lineno"> 439</span> </div><div class="line"><a name="l00441"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gadbe4c086a6562aefe344bc79e51bdfd3"> 441</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \</span></div><div class="line"><a name="l00442"></a><span class="lineno"> 442</span> <span class="preprocessor"> (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0)</span></div><div class="line"><a name="l00443"></a><span class="lineno"> 443</span> </div><div class="line"><a name="l00445"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gab138ae2ebf2905dfbaf4154db2620939"> 445</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \</span></div><div class="line"><a name="l00446"></a><span class="lineno"> 446</span> <span class="preprocessor"> (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)</span></div><div class="line"><a name="l00447"></a><span class="lineno"> 447</span> </div><div class="line"><a name="l00448"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gac674a0f059bc0cb72b47f0c517b4f45b"> 448</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \</span></div><div class="line"><a name="l00449"></a><span class="lineno"> 449</span> <span class="preprocessor"> (((type) & (PSA_KEY_TYPE_CATEGORY_MASK | PSA_KEY_TYPE_PAIR_FLAG)) == \</span></div><div class="line"><a name="l00450"></a><span class="lineno"> 450</span> <span class="preprocessor"> PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)</span></div><div class="line"><a name="l00451"></a><span class="lineno"> 451</span> </div><div class="line"><a name="l00453"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gac14c6d6e1b2b7f4a92a7b757465cff29"> 453</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_IS_KEYPAIR(type) \</span></div><div class="line"><a name="l00454"></a><span class="lineno"> 454</span> <span class="preprocessor"> (((type) & (PSA_KEY_TYPE_CATEGORY_MASK | PSA_KEY_TYPE_PAIR_FLAG)) == \</span></div><div class="line"><a name="l00455"></a><span class="lineno"> 455</span> <span class="preprocessor"> (PSA_KEY_TYPE_CATEGORY_ASYMMETRIC | PSA_KEY_TYPE_PAIR_FLAG))</span></div><div class="line"><a name="l00456"></a><span class="lineno"> 456</span> </div><div class="line"><a name="l00457"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gaf09f1ca1de6a7e7cff0fe516f3f6c91d"> 457</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY(type) \</span></div><div class="line"><a name="l00458"></a><span class="lineno"> 458</span> <span class="preprocessor"> ((type) | PSA_KEY_TYPE_PAIR_FLAG)</span></div><div class="line"><a name="l00459"></a><span class="lineno"> 459</span> </div><div class="line"><a name="l00460"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec"> 460</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) \</span></div><div class="line"><a name="l00461"></a><span class="lineno"> 461</span> <span class="preprocessor"> ((type) & ~PSA_KEY_TYPE_PAIR_FLAG)</span></div><div class="line"><a name="l00462"></a><span class="lineno"> 462</span> </div><div class="line"><a name="l00463"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a"> 463</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_IS_RSA(type) \</span></div><div class="line"><a name="l00464"></a><span class="lineno"> 464</span> <span class="preprocessor"> (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY)</span></div><div class="line"><a name="l00465"></a><span class="lineno"> 465</span> </div><div class="line"><a name="l00467"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66"> 467</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_IS_ECC(type) \</span></div><div class="line"><a name="l00468"></a><span class="lineno"> 468</span> <span class="preprocessor"> ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) & \</span></div><div class="line"><a name="l00469"></a><span class="lineno"> 469</span> <span class="preprocessor"> ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE)</span></div><div class="line"><a name="l00470"></a><span class="lineno"> 470</span> <span class="preprocessor">#define PSA_KEY_TYPE_IS_ECC_KEYPAIR(type) \</span></div><div class="line"><a name="l00471"></a><span class="lineno"> 471</span> <span class="preprocessor"> (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \</span></div><div class="line"><a name="l00472"></a><span class="lineno"> 472</span> <span class="preprocessor"> PSA_KEY_TYPE_ECC_KEYPAIR_BASE)</span></div><div class="line"><a name="l00473"></a><span class="lineno"> 473</span> <span class="preprocessor">#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \</span></div><div class="line"><a name="l00474"></a><span class="lineno"> 474</span> <span class="preprocessor"> (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \</span></div><div class="line"><a name="l00475"></a><span class="lineno"> 475</span> <span class="preprocessor"> PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE)</span></div><div class="line"><a name="l00476"></a><span class="lineno"> 476</span> </div><div class="line"><a name="l00478"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9"> 478</a></span> <span class="keyword">typedef</span> uint16_t <a class="code" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>;</div><div class="line"><a name="l00480"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga0c567210e6f80aa8f2aa87efa7a3a3f9"> 480</a></span> <span class="preprocessor">#define PSA_KEY_TYPE_GET_CURVE(type) \</span></div><div class="line"><a name="l00481"></a><span class="lineno"> 481</span> <span class="preprocessor"> ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \</span></div><div class="line"><a name="l00482"></a><span class="lineno"> 482</span> <span class="preprocessor"> ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \</span></div><div class="line"><a name="l00483"></a><span class="lineno"> 483</span> <span class="preprocessor"> 0))</span></div><div class="line"><a name="l00484"></a><span class="lineno"> 484</span> </div><div class="line"><a name="l00485"></a><span class="lineno"> 485</span> <span class="comment">/* The encoding of curve identifiers is currently aligned with the</span></div><div class="line"><a name="l00486"></a><span class="lineno"> 486</span> <span class="comment"> * TLS Supported Groups Registry (formerly known as the</span></div><div class="line"><a name="l00487"></a><span class="lineno"> 487</span> <span class="comment"> * TLS EC Named Curve Registry)</span></div><div class="line"><a name="l00488"></a><span class="lineno"> 488</span> <span class="comment"> * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8</span></div><div class="line"><a name="l00489"></a><span class="lineno"> 489</span> <span class="comment"> * The values are defined by RFC 4492, RFC 7027 and RFC 7919. */</span></div><div class="line"><a name="l00490"></a><span class="lineno"> 490</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001)</span></div><div class="line"><a name="l00491"></a><span class="lineno"> 491</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002)</span></div><div class="line"><a name="l00492"></a><span class="lineno"> 492</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003)</span></div><div class="line"><a name="l00493"></a><span class="lineno"> 493</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004)</span></div><div class="line"><a name="l00494"></a><span class="lineno"> 494</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005)</span></div><div class="line"><a name="l00495"></a><span class="lineno"> 495</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006)</span></div><div class="line"><a name="l00496"></a><span class="lineno"> 496</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007)</span></div><div class="line"><a name="l00497"></a><span class="lineno"> 497</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008)</span></div><div class="line"><a name="l00498"></a><span class="lineno"> 498</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009)</span></div><div class="line"><a name="l00499"></a><span class="lineno"> 499</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a)</span></div><div class="line"><a name="l00500"></a><span class="lineno"> 500</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b)</span></div><div class="line"><a name="l00501"></a><span class="lineno"> 501</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c)</span></div><div class="line"><a name="l00502"></a><span class="lineno"> 502</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d)</span></div><div class="line"><a name="l00503"></a><span class="lineno"> 503</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e)</span></div><div class="line"><a name="l00504"></a><span class="lineno"> 504</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f)</span></div><div class="line"><a name="l00505"></a><span class="lineno"> 505</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010)</span></div><div class="line"><a name="l00506"></a><span class="lineno"> 506</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011)</span></div><div class="line"><a name="l00507"></a><span class="lineno"> 507</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012)</span></div><div class="line"><a name="l00508"></a><span class="lineno"> 508</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013)</span></div><div class="line"><a name="l00509"></a><span class="lineno"> 509</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014)</span></div><div class="line"><a name="l00510"></a><span class="lineno"> 510</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015)</span></div><div class="line"><a name="l00511"></a><span class="lineno"> 511</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016)</span></div><div class="line"><a name="l00512"></a><span class="lineno"> 512</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017)</span></div><div class="line"><a name="l00513"></a><span class="lineno"> 513</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018)</span></div><div class="line"><a name="l00514"></a><span class="lineno"> 514</span> <span class="preprocessor">#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019)</span></div><div class="line"><a name="l00515"></a><span class="lineno"> 515</span> <span class="preprocessor">#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a)</span></div><div class="line"><a name="l00516"></a><span class="lineno"> 516</span> <span class="preprocessor">#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b)</span></div><div class="line"><a name="l00517"></a><span class="lineno"> 517</span> <span class="preprocessor">#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c)</span></div><div class="line"><a name="l00518"></a><span class="lineno"> 518</span> <span class="preprocessor">#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d)</span></div><div class="line"><a name="l00519"></a><span class="lineno"> 519</span> <span class="preprocessor">#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e)</span></div><div class="line"><a name="l00520"></a><span class="lineno"> 520</span> <span class="preprocessor">#define PSA_ECC_CURVE_FFDHE_2048 ((psa_ecc_curve_t) 0x0100)</span></div><div class="line"><a name="l00521"></a><span class="lineno"> 521</span> <span class="preprocessor">#define PSA_ECC_CURVE_FFDHE_3072 ((psa_ecc_curve_t) 0x0101)</span></div><div class="line"><a name="l00522"></a><span class="lineno"> 522</span> <span class="preprocessor">#define PSA_ECC_CURVE_FFDHE_4096 ((psa_ecc_curve_t) 0x0102)</span></div><div class="line"><a name="l00523"></a><span class="lineno"> 523</span> <span class="preprocessor">#define PSA_ECC_CURVE_FFDHE_6144 ((psa_ecc_curve_t) 0x0103)</span></div><div class="line"><a name="l00524"></a><span class="lineno"> 524</span> <span class="preprocessor">#define PSA_ECC_CURVE_FFDHE_8192 ((psa_ecc_curve_t) 0x0104)</span></div><div class="line"><a name="l00525"></a><span class="lineno"> 525</span> </div><div class="line"><a name="l00544"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gacaa366bdeb0413e63e87a667c5457b2e"> 544</a></span> <span class="preprocessor">#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \</span></div><div class="line"><a name="l00545"></a><span class="lineno"> 545</span> <span class="preprocessor"> ( \</span></div><div class="line"><a name="l00546"></a><span class="lineno"> 546</span> <span class="preprocessor"> (type) == PSA_KEY_TYPE_AES ? 16 : \</span></div><div class="line"><a name="l00547"></a><span class="lineno"> 547</span> <span class="preprocessor"> (type) == PSA_KEY_TYPE_DES ? 8 : \</span></div><div class="line"><a name="l00548"></a><span class="lineno"> 548</span> <span class="preprocessor"> (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \</span></div><div class="line"><a name="l00549"></a><span class="lineno"> 549</span> <span class="preprocessor"> (type) == PSA_KEY_TYPE_ARC4 ? 1 : \</span></div><div class="line"><a name="l00550"></a><span class="lineno"> 550</span> <span class="preprocessor"> 0)</span></div><div class="line"><a name="l00551"></a><span class="lineno"> 551</span> </div><div class="line"><a name="l00560"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69"> 560</a></span> <span class="keyword">typedef</span> uint32_t <a class="code" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>;</div><div class="line"><a name="l00561"></a><span class="lineno"> 561</span> </div><div class="line"><a name="l00562"></a><span class="lineno"> 562</span> <span class="preprocessor">#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000)</span></div><div class="line"><a name="l00563"></a><span class="lineno"> 563</span> <span class="preprocessor">#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000)</span></div><div class="line"><a name="l00564"></a><span class="lineno"> 564</span> <span class="preprocessor">#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000)</span></div><div class="line"><a name="l00565"></a><span class="lineno"> 565</span> <span class="preprocessor">#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000)</span></div><div class="line"><a name="l00566"></a><span class="lineno"> 566</span> <span class="preprocessor">#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000)</span></div><div class="line"><a name="l00567"></a><span class="lineno"> 567</span> <span class="preprocessor">#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000)</span></div><div class="line"><a name="l00568"></a><span class="lineno"> 568</span> <span class="preprocessor">#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000)</span></div><div class="line"><a name="l00569"></a><span class="lineno"> 569</span> <span class="preprocessor">#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000)</span></div><div class="line"><a name="l00570"></a><span class="lineno"> 570</span> <span class="preprocessor">#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x22000000)</span></div><div class="line"><a name="l00571"></a><span class="lineno"> 571</span> <span class="preprocessor">#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x30000000)</span></div><div class="line"><a name="l00572"></a><span class="lineno"> 572</span> </div><div class="line"><a name="l00573"></a><span class="lineno"> 573</span> <span class="preprocessor">#define PSA_ALG_IS_VENDOR_DEFINED(alg) \</span></div><div class="line"><a name="l00574"></a><span class="lineno"> 574</span> <span class="preprocessor"> (((alg) & PSA_ALG_VENDOR_FLAG) != 0)</span></div><div class="line"><a name="l00575"></a><span class="lineno"> 575</span> </div><div class="line"><a name="l00584"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f"> 584</a></span> <span class="preprocessor">#define PSA_ALG_IS_HASH(alg) \</span></div><div class="line"><a name="l00585"></a><span class="lineno"> 585</span> <span class="preprocessor"> (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH)</span></div><div class="line"><a name="l00586"></a><span class="lineno"> 586</span> </div><div class="line"><a name="l00595"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gaca7aee4c9dde316b3b1a150a26eab776"> 595</a></span> <span class="preprocessor">#define PSA_ALG_IS_MAC(alg) \</span></div><div class="line"><a name="l00596"></a><span class="lineno"> 596</span> <span class="preprocessor"> (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC)</span></div><div class="line"><a name="l00597"></a><span class="lineno"> 597</span> </div><div class="line"><a name="l00606"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga1d1a5a402ad89a2e68f12bfb535490eb"> 606</a></span> <span class="preprocessor">#define PSA_ALG_IS_CIPHER(alg) \</span></div><div class="line"><a name="l00607"></a><span class="lineno"> 607</span> <span class="preprocessor"> (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER)</span></div><div class="line"><a name="l00608"></a><span class="lineno"> 608</span> </div><div class="line"><a name="l00618"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8"> 618</a></span> <span class="preprocessor">#define PSA_ALG_IS_AEAD(alg) \</span></div><div class="line"><a name="l00619"></a><span class="lineno"> 619</span> <span class="preprocessor"> (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD)</span></div><div class="line"><a name="l00620"></a><span class="lineno"> 620</span> </div><div class="line"><a name="l00629"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga6d490d0904e0698f6c1268a89d72ff31"> 629</a></span> <span class="preprocessor">#define PSA_ALG_IS_SIGN(alg) \</span></div><div class="line"><a name="l00630"></a><span class="lineno"> 630</span> <span class="preprocessor"> (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN)</span></div><div class="line"><a name="l00631"></a><span class="lineno"> 631</span> </div><div class="line"><a name="l00640"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga41d2ee937d54efd76bd54a97b2ebc08a"> 640</a></span> <span class="preprocessor">#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \</span></div><div class="line"><a name="l00641"></a><span class="lineno"> 641</span> <span class="preprocessor"> (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION)</span></div><div class="line"><a name="l00642"></a><span class="lineno"> 642</span> </div><div class="line"><a name="l00651"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga59753742cb06553bd22751bbef472b6f"> 651</a></span> <span class="preprocessor">#define PSA_ALG_IS_KEY_AGREEMENT(alg) \</span></div><div class="line"><a name="l00652"></a><span class="lineno"> 652</span> <span class="preprocessor"> (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT)</span></div><div class="line"><a name="l00653"></a><span class="lineno"> 653</span> </div><div class="line"><a name="l00662"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gaf8b90c648aa53dbd06c236695e300cd0"> 662</a></span> <span class="preprocessor">#define PSA_ALG_IS_KEY_DERIVATION(alg) \</span></div><div class="line"><a name="l00663"></a><span class="lineno"> 663</span> <span class="preprocessor"> (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)</span></div><div class="line"><a name="l00664"></a><span class="lineno"> 664</span> </div><div class="line"><a name="l00665"></a><span class="lineno"> 665</span> <span class="preprocessor">#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff)</span></div><div class="line"><a name="l00666"></a><span class="lineno"> 666</span> <span class="preprocessor">#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001)</span></div><div class="line"><a name="l00667"></a><span class="lineno"> 667</span> <span class="preprocessor">#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002)</span></div><div class="line"><a name="l00668"></a><span class="lineno"> 668</span> <span class="preprocessor">#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003)</span></div><div class="line"><a name="l00669"></a><span class="lineno"> 669</span> <span class="preprocessor">#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004)</span></div><div class="line"><a name="l00670"></a><span class="lineno"> 670</span> <span class="preprocessor">#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005)</span></div><div class="line"><a name="l00671"></a><span class="lineno"> 671</span> </div><div class="line"><a name="l00672"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga25d6a3244d10a7148fe6b026d1979f7b"> 672</a></span> <span class="preprocessor">#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008)</span></div><div class="line"><a name="l00673"></a><span class="lineno"> 673</span> </div><div class="line"><a name="l00674"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga619471f978e13cdd0a1e37145e4bf341"> 674</a></span> <span class="preprocessor">#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009)</span></div><div class="line"><a name="l00675"></a><span class="lineno"> 675</span> </div><div class="line"><a name="l00676"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga58af64dd9a86a287e8da9ed7739eead4"> 676</a></span> <span class="preprocessor">#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a)</span></div><div class="line"><a name="l00677"></a><span class="lineno"> 677</span> </div><div class="line"><a name="l00678"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gafba3ae409f46d3dd7f37a0910660c3e9"> 678</a></span> <span class="preprocessor">#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b)</span></div><div class="line"><a name="l00679"></a><span class="lineno"> 679</span> </div><div class="line"><a name="l00680"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga3fe2d7c3c80e3186ca78d16a35d5d931"> 680</a></span> <span class="preprocessor">#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c)</span></div><div class="line"><a name="l00681"></a><span class="lineno"> 681</span> </div><div class="line"><a name="l00682"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga5910b3964c14e9613e8643a45b09c2d4"> 682</a></span> <span class="preprocessor">#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d)</span></div><div class="line"><a name="l00683"></a><span class="lineno"> 683</span> </div><div class="line"><a name="l00684"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga16f5fe34ccce68c2fada1224c054a999"> 684</a></span> <span class="preprocessor">#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010)</span></div><div class="line"><a name="l00685"></a><span class="lineno"> 685</span> </div><div class="line"><a name="l00686"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gaace70d9515489bbe3c5e7ac1b7d9155b"> 686</a></span> <span class="preprocessor">#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011)</span></div><div class="line"><a name="l00687"></a><span class="lineno"> 687</span> </div><div class="line"><a name="l00688"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gab0f079257ea75e2acfe2fc3b38c78cd8"> 688</a></span> <span class="preprocessor">#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012)</span></div><div class="line"><a name="l00689"></a><span class="lineno"> 689</span> </div><div class="line"><a name="l00690"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga37e5dbe936dddb155e76f2997de27188"> 690</a></span> <span class="preprocessor">#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013)</span></div><div class="line"><a name="l00691"></a><span class="lineno"> 691</span> </div><div class="line"><a name="l00692"></a><span class="lineno"> 692</span> <span class="preprocessor">#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000)</span></div><div class="line"><a name="l00693"></a><span class="lineno"> 693</span> <span class="preprocessor">#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000)</span></div><div class="line"><a name="l00694"></a><span class="lineno"> 694</span> </div><div class="line"><a name="l00705"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga70f397425684b3efcde1e0e34c28261f"> 705</a></span> <span class="preprocessor">#define PSA_ALG_HMAC(hash_alg) \</span></div><div class="line"><a name="l00706"></a><span class="lineno"> 706</span> <span class="preprocessor"> (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l00707"></a><span class="lineno"> 707</span> </div><div class="line"><a name="l00708"></a><span class="lineno"> 708</span> <span class="preprocessor">#define PSA_ALG_HMAC_HASH(hmac_alg) \</span></div><div class="line"><a name="l00709"></a><span class="lineno"> 709</span> <span class="preprocessor"> (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l00710"></a><span class="lineno"> 710</span> </div><div class="line"><a name="l00721"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga4a050c3c3cbc6eb96418f18847601c8a"> 721</a></span> <span class="preprocessor">#define PSA_ALG_IS_HMAC(alg) \</span></div><div class="line"><a name="l00722"></a><span class="lineno"> 722</span> <span class="preprocessor"> (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \</span></div><div class="line"><a name="l00723"></a><span class="lineno"> 723</span> <span class="preprocessor"> PSA_ALG_HMAC_BASE)</span></div><div class="line"><a name="l00724"></a><span class="lineno"> 724</span> </div><div class="line"><a name="l00725"></a><span class="lineno"> 725</span> <span class="preprocessor">#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000)</span></div><div class="line"><a name="l00726"></a><span class="lineno"> 726</span> <span class="preprocessor">#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001)</span></div><div class="line"><a name="l00727"></a><span class="lineno"> 727</span> <span class="preprocessor">#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002)</span></div><div class="line"><a name="l00728"></a><span class="lineno"> 728</span> <span class="preprocessor">#define PSA_ALG_GMAC ((psa_algorithm_t)0x02c00003)</span></div><div class="line"><a name="l00729"></a><span class="lineno"> 729</span> </div><div class="line"><a name="l00738"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga8986360ff97dbd91f220edf9202e375d"> 738</a></span> <span class="preprocessor">#define PSA_ALG_IS_CIPHER_MAC(alg) \</span></div><div class="line"><a name="l00739"></a><span class="lineno"> 739</span> <span class="preprocessor"> (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \</span></div><div class="line"><a name="l00740"></a><span class="lineno"> 740</span> <span class="preprocessor"> PSA_ALG_CIPHER_MAC_BASE)</span></div><div class="line"><a name="l00741"></a><span class="lineno"> 741</span> </div><div class="line"><a name="l00742"></a><span class="lineno"> 742</span> <span class="preprocessor">#define PSA_ALG_CIPHER_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000)</span></div><div class="line"><a name="l00743"></a><span class="lineno"> 743</span> <span class="preprocessor">#define PSA_ALG_BLOCK_CIPHER_BASE ((psa_algorithm_t)0x04000000)</span></div><div class="line"><a name="l00744"></a><span class="lineno"> 744</span> <span class="preprocessor">#define PSA_ALG_BLOCK_CIPHER_MODE_MASK ((psa_algorithm_t)0x000000ff)</span></div><div class="line"><a name="l00745"></a><span class="lineno"> 745</span> <span class="preprocessor">#define PSA_ALG_BLOCK_CIPHER_PADDING_MASK ((psa_algorithm_t)0x003f0000)</span></div><div class="line"><a name="l00746"></a><span class="lineno"> 746</span> </div><div class="line"><a name="l00752"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga0992d26a02a2a7dc316cd5abc5254966"> 752</a></span> <span class="preprocessor">#define PSA_ALG_BLOCK_CIPHER_PAD_NONE ((psa_algorithm_t)0x00000000)</span></div><div class="line"><a name="l00753"></a><span class="lineno"> 753</span> </div><div class="line"><a name="l00754"></a><span class="lineno"> 754</span> <span class="preprocessor">#define PSA_ALG_BLOCK_CIPHER_PAD_PKCS7 ((psa_algorithm_t)0x00010000)</span></div><div class="line"><a name="l00755"></a><span class="lineno"> 755</span> </div><div class="line"><a name="l00776"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga02e787d79c0cd666efcd090569d5b31c"> 776</a></span> <span class="preprocessor">#define PSA_ALG_IS_BLOCK_CIPHER(alg) \</span></div><div class="line"><a name="l00777"></a><span class="lineno"> 777</span> <span class="preprocessor"> (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_SUBCATEGORY_MASK)) == \</span></div><div class="line"><a name="l00778"></a><span class="lineno"> 778</span> <span class="preprocessor"> PSA_ALG_BLOCK_CIPHER_BASE)</span></div><div class="line"><a name="l00779"></a><span class="lineno"> 779</span> </div><div class="line"><a name="l00782"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga931f31d4f05c3dab9fd5d7fdcd3715f2"> 782</a></span> <span class="preprocessor">#define PSA_ALG_CBC_BASE ((psa_algorithm_t)0x04000001)</span></div><div class="line"><a name="l00783"></a><span class="lineno"> 783</span> <span class="preprocessor">#define PSA_ALG_CFB_BASE ((psa_algorithm_t)0x04000002)</span></div><div class="line"><a name="l00784"></a><span class="lineno"> 784</span> <span class="preprocessor">#define PSA_ALG_OFB_BASE ((psa_algorithm_t)0x04000003)</span></div><div class="line"><a name="l00785"></a><span class="lineno"> 785</span> <span class="preprocessor">#define PSA_ALG_XTS_BASE ((psa_algorithm_t)0x04000004)</span></div><div class="line"><a name="l00786"></a><span class="lineno"> 786</span> </div><div class="line"><a name="l00787"></a><span class="lineno"> 787</span> <span class="preprocessor">#define PSA_ALG_STREAM_CIPHER_BASE ((psa_algorithm_t)0x04800000)</span></div><div class="line"><a name="l00788"></a><span class="lineno"> 788</span> </div><div class="line"><a name="l00796"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gad318309706a769cffdc64e4c7e06b2e9"> 796</a></span> <span class="preprocessor">#define PSA_ALG_CTR ((psa_algorithm_t)0x04800001)</span></div><div class="line"><a name="l00797"></a><span class="lineno"> 797</span> </div><div class="line"><a name="l00800"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gab6a5284decb0e5e1b5b8740a41ef3c5e"> 800</a></span> <span class="preprocessor">#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800002)</span></div><div class="line"><a name="l00801"></a><span class="lineno"> 801</span> </div><div class="line"><a name="l00814"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gacfec68e0c6175e02e1b2ebc97df383c0"> 814</a></span> <span class="preprocessor">#define PSA_ALG_IS_STREAM_CIPHER(alg) \</span></div><div class="line"><a name="l00815"></a><span class="lineno"> 815</span> <span class="preprocessor"> (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_SUBCATEGORY_MASK)) == \</span></div><div class="line"><a name="l00816"></a><span class="lineno"> 816</span> <span class="preprocessor"> PSA_ALG_STREAM_CIPHER_BASE)</span></div><div class="line"><a name="l00817"></a><span class="lineno"> 817</span> </div><div class="line"><a name="l00818"></a><span class="lineno"> 818</span> <span class="preprocessor">#define PSA_ALG_CCM ((psa_algorithm_t)0x06000001)</span></div><div class="line"><a name="l00819"></a><span class="lineno"> 819</span> <span class="preprocessor">#define PSA_ALG_GCM ((psa_algorithm_t)0x06000002)</span></div><div class="line"><a name="l00820"></a><span class="lineno"> 820</span> </div><div class="line"><a name="l00821"></a><span class="lineno"> 821</span> <span class="preprocessor">#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000)</span></div><div class="line"><a name="l00822"></a><span class="lineno"> 822</span> </div><div class="line"><a name="l00835"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga702ff75385a6ae7d4247033f479439af"> 835</a></span> <span class="preprocessor">#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \</span></div><div class="line"><a name="l00836"></a><span class="lineno"> 836</span> <span class="preprocessor"> (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l00837"></a><span class="lineno"> 837</span> </div><div class="line"><a name="l00843"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga4215e2a78dcf834e9a625927faa2a817"> 843</a></span> <span class="preprocessor">#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE</span></div><div class="line"><a name="l00844"></a><span class="lineno"> 844</span> <span class="preprocessor">#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \</span></div><div class="line"><a name="l00845"></a><span class="lineno"> 845</span> <span class="preprocessor"> (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE)</span></div><div class="line"><a name="l00846"></a><span class="lineno"> 846</span> </div><div class="line"><a name="l00847"></a><span class="lineno"> 847</span> <span class="preprocessor">#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000)</span></div><div class="line"><a name="l00848"></a><span class="lineno"> 848</span> </div><div class="line"><a name="l00864"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga62152bf4cb4bf6aace5e1be8f143564d"> 864</a></span> <span class="preprocessor">#define PSA_ALG_RSA_PSS(hash_alg) \</span></div><div class="line"><a name="l00865"></a><span class="lineno"> 865</span> <span class="preprocessor"> (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l00866"></a><span class="lineno"> 866</span> <span class="preprocessor">#define PSA_ALG_IS_RSA_PSS(alg) \</span></div><div class="line"><a name="l00867"></a><span class="lineno"> 867</span> <span class="preprocessor"> (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE)</span></div><div class="line"><a name="l00868"></a><span class="lineno"> 868</span> </div><div class="line"><a name="l00869"></a><span class="lineno"> 869</span> <span class="preprocessor">#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x10040000)</span></div><div class="line"><a name="l00870"></a><span class="lineno"> 870</span> </div><div class="line"><a name="l00882"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga9a68efdddff5ae95f104a1416b12742e"> 882</a></span> <span class="preprocessor">#define PSA_ALG_DSA(hash_alg) \</span></div><div class="line"><a name="l00883"></a><span class="lineno"> 883</span> <span class="preprocessor"> (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l00884"></a><span class="lineno"> 884</span> <span class="preprocessor">#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x10050000)</span></div><div class="line"><a name="l00885"></a><span class="lineno"> 885</span> <span class="preprocessor">#define PSA_ALG_DSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000)</span></div><div class="line"><a name="l00886"></a><span class="lineno"> 886</span> <span class="preprocessor">#define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \</span></div><div class="line"><a name="l00887"></a><span class="lineno"> 887</span> <span class="preprocessor"> (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l00888"></a><span class="lineno"> 888</span> <span class="preprocessor">#define PSA_ALG_IS_DSA(alg) \</span></div><div class="line"><a name="l00889"></a><span class="lineno"> 889</span> <span class="preprocessor"> (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \</span></div><div class="line"><a name="l00890"></a><span class="lineno"> 890</span> <span class="preprocessor"> PSA_ALG_DSA_BASE)</span></div><div class="line"><a name="l00891"></a><span class="lineno"> 891</span> <span class="preprocessor">#define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \</span></div><div class="line"><a name="l00892"></a><span class="lineno"> 892</span> <span class="preprocessor"> (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)</span></div><div class="line"><a name="l00893"></a><span class="lineno"> 893</span> <span class="preprocessor">#define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \</span></div><div class="line"><a name="l00894"></a><span class="lineno"> 894</span> <span class="preprocessor"> (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg))</span></div><div class="line"><a name="l00895"></a><span class="lineno"> 895</span> <span class="preprocessor">#define PSA_ALG_IS_RANDOMIZED_DSA(alg) \</span></div><div class="line"><a name="l00896"></a><span class="lineno"> 896</span> <span class="preprocessor"> (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg))</span></div><div class="line"><a name="l00897"></a><span class="lineno"> 897</span> </div><div class="line"><a name="l00898"></a><span class="lineno"> 898</span> <span class="preprocessor">#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000)</span></div><div class="line"><a name="l00899"></a><span class="lineno"> 899</span> </div><div class="line"><a name="l00917"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga7e3ce9f514a227d5ba5d8318870452e3"> 917</a></span> <span class="preprocessor">#define PSA_ALG_ECDSA(hash_alg) \</span></div><div class="line"><a name="l00918"></a><span class="lineno"> 918</span> <span class="preprocessor"> (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l00919"></a><span class="lineno"> 919</span> </div><div class="line"><a name="l00928"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga51d6b6044a62e33cae0cf64bfc3b22a4"> 928</a></span> <span class="preprocessor">#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE</span></div><div class="line"><a name="l00929"></a><span class="lineno"> 929</span> <span class="preprocessor">#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000)</span></div><div class="line"><a name="l00930"></a><span class="lineno"> 930</span> </div><div class="line"><a name="l00950"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga11da566bcd341661c8de921e2ca5ed03"> 950</a></span> <span class="preprocessor">#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \</span></div><div class="line"><a name="l00951"></a><span class="lineno"> 951</span> <span class="preprocessor"> (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l00952"></a><span class="lineno"> 952</span> <span class="preprocessor">#define PSA_ALG_IS_ECDSA(alg) \</span></div><div class="line"><a name="l00953"></a><span class="lineno"> 953</span> <span class="preprocessor"> (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \</span></div><div class="line"><a name="l00954"></a><span class="lineno"> 954</span> <span class="preprocessor"> PSA_ALG_ECDSA_BASE)</span></div><div class="line"><a name="l00955"></a><span class="lineno"> 955</span> <span class="preprocessor">#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \</span></div><div class="line"><a name="l00956"></a><span class="lineno"> 956</span> <span class="preprocessor"> (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)</span></div><div class="line"><a name="l00957"></a><span class="lineno"> 957</span> <span class="preprocessor">#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \</span></div><div class="line"><a name="l00958"></a><span class="lineno"> 958</span> <span class="preprocessor"> (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))</span></div><div class="line"><a name="l00959"></a><span class="lineno"> 959</span> <span class="preprocessor">#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \</span></div><div class="line"><a name="l00960"></a><span class="lineno"> 960</span> <span class="preprocessor"> (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))</span></div><div class="line"><a name="l00961"></a><span class="lineno"> 961</span> </div><div class="line"><a name="l00980"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga24cf6d7bcd2b9aeeeff86f07b6c674e3"> 980</a></span> <span class="preprocessor">#define PSA_ALG_SIGN_GET_HASH(alg) \</span></div><div class="line"><a name="l00981"></a><span class="lineno"> 981</span> <span class="preprocessor"> (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \</span></div><div class="line"><a name="l00982"></a><span class="lineno"> 982</span> <span class="preprocessor"> PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg) ? \</span></div><div class="line"><a name="l00983"></a><span class="lineno"> 983</span> <span class="preprocessor"> ((alg) & PSA_ALG_HASH_MASK) == 0 ? </span><span class="comment">/*"raw" algorithm*/</span><span class="preprocessor"> 0 : \</span></div><div class="line"><a name="l00984"></a><span class="lineno"> 984</span> <span class="preprocessor"> ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \</span></div><div class="line"><a name="l00985"></a><span class="lineno"> 985</span> <span class="preprocessor"> 0)</span></div><div class="line"><a name="l00986"></a><span class="lineno"> 986</span> </div><div class="line"><a name="l00989"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga4c540d3abe43fb9abcb94f2bc51acef9"> 989</a></span> <span class="preprocessor">#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000)</span></div><div class="line"><a name="l00990"></a><span class="lineno"> 990</span> </div><div class="line"><a name="l00991"></a><span class="lineno"> 991</span> <span class="preprocessor">#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000)</span></div><div class="line"><a name="l00992"></a><span class="lineno"> 992</span> </div><div class="line"><a name="l01006"></a><span class="lineno"><a class="line" href="group__crypto__types.html#gaa1235dc3fdd9839c6c1b1a9857344c76"> 1006</a></span> <span class="preprocessor">#define PSA_ALG_RSA_OAEP(hash_alg) \</span></div><div class="line"><a name="l01007"></a><span class="lineno"> 1007</span> <span class="preprocessor"> (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l01008"></a><span class="lineno"> 1008</span> <span class="preprocessor">#define PSA_ALG_IS_RSA_OAEP(alg) \</span></div><div class="line"><a name="l01009"></a><span class="lineno"> 1009</span> <span class="preprocessor"> (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE)</span></div><div class="line"><a name="l01010"></a><span class="lineno"> 1010</span> <span class="preprocessor">#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \</span></div><div class="line"><a name="l01011"></a><span class="lineno"> 1011</span> <span class="preprocessor"> (PSA_ALG_IS_RSA_OAEP(alg) ? \</span></div><div class="line"><a name="l01012"></a><span class="lineno"> 1012</span> <span class="preprocessor"> ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \</span></div><div class="line"><a name="l01013"></a><span class="lineno"> 1013</span> <span class="preprocessor"> 0)</span></div><div class="line"><a name="l01014"></a><span class="lineno"> 1014</span> </div><div class="line"><a name="l01015"></a><span class="lineno"> 1015</span> <span class="preprocessor">#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x30000100)</span></div><div class="line"><a name="l01016"></a><span class="lineno"> 1016</span> </div><div class="line"><a name="l01027"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga32a888fb360e6e25cab8a343772c4a82"> 1027</a></span> <span class="preprocessor">#define PSA_ALG_HKDF(hash_alg) \</span></div><div class="line"><a name="l01028"></a><span class="lineno"> 1028</span> <span class="preprocessor"> (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l01029"></a><span class="lineno"> 1029</span> </div><div class="line"><a name="l01040"></a><span class="lineno"><a class="line" href="group__crypto__types.html#ga1979d0a76fcee6164cf2e65960f38db2"> 1040</a></span> <span class="preprocessor">#define PSA_ALG_IS_HKDF(alg) \</span></div><div class="line"><a name="l01041"></a><span class="lineno"> 1041</span> <span class="preprocessor"> (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE)</span></div><div class="line"><a name="l01042"></a><span class="lineno"> 1042</span> <span class="preprocessor">#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \</span></div><div class="line"><a name="l01043"></a><span class="lineno"> 1043</span> <span class="preprocessor"> (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK))</span></div><div class="line"><a name="l01044"></a><span class="lineno"> 1044</span> </div><div class="line"><a name="l01080"></a><span class="lineno"> 1080</span> psa_status_t <a class="code" href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5">psa_import_key</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01081"></a><span class="lineno"> 1081</span>  psa_key_type_t type,</div><div class="line"><a name="l01082"></a><span class="lineno"> 1082</span>  <span class="keyword">const</span> uint8_t *data,</div><div class="line"><a name="l01083"></a><span class="lineno"> 1083</span>  <span class="keywordtype">size_t</span> data_length);</div><div class="line"><a name="l01084"></a><span class="lineno"> 1084</span> </div><div class="line"><a name="l01118"></a><span class="lineno"> 1118</span> psa_status_t <a class="code" href="group__key__management.html#ga2e9a60a9525ce6b3082a72df2080f0c5">psa_destroy_key</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key);</div><div class="line"><a name="l01119"></a><span class="lineno"> 1119</span> </div><div class="line"><a name="l01138"></a><span class="lineno"> 1138</span> psa_status_t <a class="code" href="group__key__management.html#gaf105167657ab1d484cb4a51f93413717">psa_get_key_information</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01139"></a><span class="lineno"> 1139</span>  psa_key_type_t *type,</div><div class="line"><a name="l01140"></a><span class="lineno"> 1140</span>  <span class="keywordtype">size_t</span> *bits);</div><div class="line"><a name="l01141"></a><span class="lineno"> 1141</span> </div><div class="line"><a name="l01182"></a><span class="lineno"> 1182</span> psa_status_t <a class="code" href="group__key__management.html#gaa67bc459b20028b268f3d75a05afe022">psa_export_key</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01183"></a><span class="lineno"> 1183</span>  uint8_t *data,</div><div class="line"><a name="l01184"></a><span class="lineno"> 1184</span>  <span class="keywordtype">size_t</span> data_size,</div><div class="line"><a name="l01185"></a><span class="lineno"> 1185</span>  <span class="keywordtype">size_t</span> *data_length);</div><div class="line"><a name="l01186"></a><span class="lineno"> 1186</span> </div><div class="line"><a name="l01213"></a><span class="lineno"> 1213</span> psa_status_t <a class="code" href="group__key__management.html#ga7355b38f8eb9330db2786604f4a83a3b">psa_export_public_key</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01214"></a><span class="lineno"> 1214</span>  uint8_t *data,</div><div class="line"><a name="l01215"></a><span class="lineno"> 1215</span>  <span class="keywordtype">size_t</span> data_size,</div><div class="line"><a name="l01216"></a><span class="lineno"> 1216</span>  <span class="keywordtype">size_t</span> *data_length);</div><div class="line"><a name="l01217"></a><span class="lineno"> 1217</span> </div><div class="line"><a name="l01225"></a><span class="lineno"><a class="line" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25"> 1225</a></span> <span class="keyword">typedef</span> uint32_t <a class="code" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>;</div><div class="line"><a name="l01226"></a><span class="lineno"> 1226</span> </div><div class="line"><a name="l01238"></a><span class="lineno"><a class="line" href="group__policy.html#ga7dddccdd1303176e87a4d20c87b589ed"> 1238</a></span> <span class="preprocessor">#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001)</span></div><div class="line"><a name="l01239"></a><span class="lineno"> 1239</span> </div><div class="line"><a name="l01249"></a><span class="lineno"><a class="line" href="group__policy.html#ga75153b296d045d529d97203a6a995dad"> 1249</a></span> <span class="preprocessor">#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100)</span></div><div class="line"><a name="l01250"></a><span class="lineno"> 1250</span> </div><div class="line"><a name="l01260"></a><span class="lineno"><a class="line" href="group__policy.html#gac3f2d2e5983db1edde9f142ca9bf8e6a"> 1260</a></span> <span class="preprocessor">#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200)</span></div><div class="line"><a name="l01261"></a><span class="lineno"> 1261</span> </div><div class="line"><a name="l01270"></a><span class="lineno"><a class="line" href="group__policy.html#ga99b9f456cf59efc4b5579465407aef5a"> 1270</a></span> <span class="preprocessor">#define PSA_KEY_USAGE_SIGN ((psa_key_usage_t)0x00000400)</span></div><div class="line"><a name="l01271"></a><span class="lineno"> 1271</span> </div><div class="line"><a name="l01280"></a><span class="lineno"><a class="line" href="group__policy.html#ga39b54ffd5958b69634607924fa53cea6"> 1280</a></span> <span class="preprocessor">#define PSA_KEY_USAGE_VERIFY ((psa_key_usage_t)0x00000800)</span></div><div class="line"><a name="l01281"></a><span class="lineno"> 1281</span> </div><div class="line"><a name="l01284"></a><span class="lineno"><a class="line" href="group__policy.html#gaf19022acc5ef23cf12477f632b48a0b2"> 1284</a></span> <span class="preprocessor">#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000)</span></div><div class="line"><a name="l01285"></a><span class="lineno"> 1285</span> </div><div class="line"><a name="l01291"></a><span class="lineno"><a class="line" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607"> 1291</a></span> <span class="keyword">typedef</span> <span class="keyword">struct </span>psa_key_policy_s <a class="code" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a>;</div><div class="line"><a name="l01292"></a><span class="lineno"> 1292</span> </div><div class="line"><a name="l01298"></a><span class="lineno"> 1298</span> <span class="keywordtype">void</span> <a class="code" href="group__policy.html#gad49eb85e3fcbe70f763f511ac83e762e">psa_key_policy_init</a>(<a class="code" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy);</div><div class="line"><a name="l01299"></a><span class="lineno"> 1299</span> </div><div class="line"><a name="l01310"></a><span class="lineno"> 1310</span> <span class="keywordtype">void</span> <a class="code" href="group__policy.html#gac16792fd6d375a5f76d372090df40607">psa_key_policy_set_usage</a>(<a class="code" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy,</div><div class="line"><a name="l01311"></a><span class="lineno"> 1311</span>  psa_key_usage_t usage,</div><div class="line"><a name="l01312"></a><span class="lineno"> 1312</span>  psa_algorithm_t alg);</div><div class="line"><a name="l01313"></a><span class="lineno"> 1313</span> </div><div class="line"><a name="l01320"></a><span class="lineno"> 1320</span> psa_key_usage_t <a class="code" href="group__policy.html#ga7746662b7503e484774d0ecb5d8ac2ab">psa_key_policy_get_usage</a>(<span class="keyword">const</span> <a class="code" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy);</div><div class="line"><a name="l01321"></a><span class="lineno"> 1321</span> </div><div class="line"><a name="l01328"></a><span class="lineno"> 1328</span> psa_algorithm_t <a class="code" href="group__policy.html#gaadf16b89ace53e1d2cb5bcb0aef24c86">psa_key_policy_get_algorithm</a>(<span class="keyword">const</span> <a class="code" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy);</div><div class="line"><a name="l01329"></a><span class="lineno"> 1329</span> </div><div class="line"><a name="l01350"></a><span class="lineno"> 1350</span> psa_status_t <a class="code" href="group__policy.html#gad7faa7e64aa771f7441c44ceff21af19">psa_set_key_policy</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01351"></a><span class="lineno"> 1351</span>  <span class="keyword">const</span> <a class="code" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy);</div><div class="line"><a name="l01352"></a><span class="lineno"> 1352</span> </div><div class="line"><a name="l01363"></a><span class="lineno"> 1363</span> psa_status_t <a class="code" href="group__policy.html#ga613f28712124f9149bd640614376ab5a">psa_get_key_policy</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01364"></a><span class="lineno"> 1364</span>  <a class="code" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy);</div><div class="line"><a name="l01365"></a><span class="lineno"> 1365</span> </div><div class="line"><a name="l01374"></a><span class="lineno"><a class="line" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf"> 1374</a></span> <span class="keyword">typedef</span> uint32_t <a class="code" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a>;</div><div class="line"><a name="l01375"></a><span class="lineno"> 1375</span> </div><div class="line"><a name="l01379"></a><span class="lineno"><a class="line" href="group__persistence.html#ga8b438870ba69489b685730d346455108"> 1379</a></span> <span class="preprocessor">#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000)</span></div><div class="line"><a name="l01380"></a><span class="lineno"> 1380</span> </div><div class="line"><a name="l01384"></a><span class="lineno"><a class="line" href="group__persistence.html#ga3713a01c5fcd5f7eae46ff22ceaf6d02"> 1384</a></span> <span class="preprocessor">#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001)</span></div><div class="line"><a name="l01385"></a><span class="lineno"> 1385</span> </div><div class="line"><a name="l01389"></a><span class="lineno"><a class="line" href="group__persistence.html#gae6b8443238ef1900cf132550d7df557f"> 1389</a></span> <span class="preprocessor">#define PSA_KEY_LIFETIME_WRITE_ONCE ((psa_key_lifetime_t)0x7fffffff)</span></div><div class="line"><a name="l01390"></a><span class="lineno"> 1390</span> </div><div class="line"><a name="l01406"></a><span class="lineno"> 1406</span> psa_status_t <a class="code" href="group__persistence.html#gaf0daaa1dba14dc324ca83dfe1495a5e2">psa_get_key_lifetime</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01407"></a><span class="lineno"> 1407</span>  psa_key_lifetime_t *lifetime);</div><div class="line"><a name="l01408"></a><span class="lineno"> 1408</span> </div><div class="line"><a name="l01433"></a><span class="lineno"> 1433</span> psa_status_t <a class="code" href="group__persistence.html#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8">psa_set_key_lifetime</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01434"></a><span class="lineno"> 1434</span>  psa_key_lifetime_t lifetime);</div><div class="line"><a name="l01435"></a><span class="lineno"> 1435</span> </div><div class="line"><a name="l01447"></a><span class="lineno"><a class="line" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab"> 1447</a></span> <span class="keyword">typedef</span> <span class="keyword">struct </span>psa_hash_operation_s <a class="code" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a>;</div><div class="line"><a name="l01448"></a><span class="lineno"> 1448</span> </div><div class="line"><a name="l01463"></a><span class="lineno"><a class="line" href="group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99"> 1463</a></span> <span class="preprocessor">#define PSA_HASH_SIZE(alg) \</span></div><div class="line"><a name="l01464"></a><span class="lineno"> 1464</span> <span class="preprocessor"> ( \</span></div><div class="line"><a name="l01465"></a><span class="lineno"> 1465</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD2 ? 16 : \</span></div><div class="line"><a name="l01466"></a><span class="lineno"> 1466</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD4 ? 16 : \</span></div><div class="line"><a name="l01467"></a><span class="lineno"> 1467</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD5 ? 16 : \</span></div><div class="line"><a name="l01468"></a><span class="lineno"> 1468</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \</span></div><div class="line"><a name="l01469"></a><span class="lineno"> 1469</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \</span></div><div class="line"><a name="l01470"></a><span class="lineno"> 1470</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \</span></div><div class="line"><a name="l01471"></a><span class="lineno"> 1471</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \</span></div><div class="line"><a name="l01472"></a><span class="lineno"> 1472</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \</span></div><div class="line"><a name="l01473"></a><span class="lineno"> 1473</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \</span></div><div class="line"><a name="l01474"></a><span class="lineno"> 1474</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \</span></div><div class="line"><a name="l01475"></a><span class="lineno"> 1475</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \</span></div><div class="line"><a name="l01476"></a><span class="lineno"> 1476</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \</span></div><div class="line"><a name="l01477"></a><span class="lineno"> 1477</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \</span></div><div class="line"><a name="l01478"></a><span class="lineno"> 1478</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \</span></div><div class="line"><a name="l01479"></a><span class="lineno"> 1479</span> <span class="preprocessor"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \</span></div><div class="line"><a name="l01480"></a><span class="lineno"> 1480</span> <span class="preprocessor"> 0)</span></div><div class="line"><a name="l01481"></a><span class="lineno"> 1481</span> </div><div class="line"><a name="l01517"></a><span class="lineno"> 1517</span> psa_status_t <a class="code" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup</a>(<a class="code" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation,</div><div class="line"><a name="l01518"></a><span class="lineno"> 1518</span>  psa_algorithm_t alg);</div><div class="line"><a name="l01519"></a><span class="lineno"> 1519</span> </div><div class="line"><a name="l01539"></a><span class="lineno"> 1539</span> psa_status_t <a class="code" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">psa_hash_update</a>(<a class="code" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation,</div><div class="line"><a name="l01540"></a><span class="lineno"> 1540</span>  <span class="keyword">const</span> uint8_t *input,</div><div class="line"><a name="l01541"></a><span class="lineno"> 1541</span>  <span class="keywordtype">size_t</span> input_length);</div><div class="line"><a name="l01542"></a><span class="lineno"> 1542</span> </div><div class="line"><a name="l01580"></a><span class="lineno"> 1580</span> psa_status_t <a class="code" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">psa_hash_finish</a>(<a class="code" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation,</div><div class="line"><a name="l01581"></a><span class="lineno"> 1581</span>  uint8_t *hash,</div><div class="line"><a name="l01582"></a><span class="lineno"> 1582</span>  <span class="keywordtype">size_t</span> hash_size,</div><div class="line"><a name="l01583"></a><span class="lineno"> 1583</span>  <span class="keywordtype">size_t</span> *hash_length);</div><div class="line"><a name="l01584"></a><span class="lineno"> 1584</span> </div><div class="line"><a name="l01616"></a><span class="lineno"> 1616</span> psa_status_t <a class="code" href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">psa_hash_verify</a>(<a class="code" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation,</div><div class="line"><a name="l01617"></a><span class="lineno"> 1617</span>  <span class="keyword">const</span> uint8_t *hash,</div><div class="line"><a name="l01618"></a><span class="lineno"> 1618</span>  <span class="keywordtype">size_t</span> hash_length);</div><div class="line"><a name="l01619"></a><span class="lineno"> 1619</span> </div><div class="line"><a name="l01647"></a><span class="lineno"> 1647</span> psa_status_t <a class="code" href="group__hash.html#gab0b4d5f9912a615559497a467b532928">psa_hash_abort</a>(<a class="code" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation);</div><div class="line"><a name="l01648"></a><span class="lineno"> 1648</span> </div><div class="line"><a name="l01660"></a><span class="lineno"><a class="line" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37"> 1660</a></span> <span class="keyword">typedef</span> <span class="keyword">struct </span>psa_mac_operation_s <a class="code" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a>;</div><div class="line"><a name="l01661"></a><span class="lineno"> 1661</span> </div><div class="line"><a name="l01707"></a><span class="lineno"> 1707</span> psa_status_t <a class="code" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup</a>(<a class="code" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation,</div><div class="line"><a name="l01708"></a><span class="lineno"> 1708</span>  <a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01709"></a><span class="lineno"> 1709</span>  psa_algorithm_t alg);</div><div class="line"><a name="l01710"></a><span class="lineno"> 1710</span> </div><div class="line"><a name="l01755"></a><span class="lineno"> 1755</span> psa_status_t <a class="code" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup</a>(<a class="code" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation,</div><div class="line"><a name="l01756"></a><span class="lineno"> 1756</span>  <a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01757"></a><span class="lineno"> 1757</span>  psa_algorithm_t alg);</div><div class="line"><a name="l01758"></a><span class="lineno"> 1758</span> </div><div class="line"><a name="l01780"></a><span class="lineno"> 1780</span> psa_status_t <a class="code" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">psa_mac_update</a>(<a class="code" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation,</div><div class="line"><a name="l01781"></a><span class="lineno"> 1781</span>  <span class="keyword">const</span> uint8_t *input,</div><div class="line"><a name="l01782"></a><span class="lineno"> 1782</span>  <span class="keywordtype">size_t</span> input_length);</div><div class="line"><a name="l01783"></a><span class="lineno"> 1783</span> </div><div class="line"><a name="l01822"></a><span class="lineno"> 1822</span> psa_status_t <a class="code" href="group__MAC.html#gac22bc0125580c96724a09226cfbc97f2">psa_mac_sign_finish</a>(<a class="code" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation,</div><div class="line"><a name="l01823"></a><span class="lineno"> 1823</span>  uint8_t *mac,</div><div class="line"><a name="l01824"></a><span class="lineno"> 1824</span>  <span class="keywordtype">size_t</span> mac_size,</div><div class="line"><a name="l01825"></a><span class="lineno"> 1825</span>  <span class="keywordtype">size_t</span> *mac_length);</div><div class="line"><a name="l01826"></a><span class="lineno"> 1826</span> </div><div class="line"><a name="l01858"></a><span class="lineno"> 1858</span> psa_status_t <a class="code" href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">psa_mac_verify_finish</a>(<a class="code" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation,</div><div class="line"><a name="l01859"></a><span class="lineno"> 1859</span>  <span class="keyword">const</span> uint8_t *mac,</div><div class="line"><a name="l01860"></a><span class="lineno"> 1860</span>  <span class="keywordtype">size_t</span> mac_length);</div><div class="line"><a name="l01861"></a><span class="lineno"> 1861</span> </div><div class="line"><a name="l01890"></a><span class="lineno"> 1890</span> psa_status_t <a class="code" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">psa_mac_abort</a>(<a class="code" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation);</div><div class="line"><a name="l01891"></a><span class="lineno"> 1891</span> </div><div class="line"><a name="l01903"></a><span class="lineno"><a class="line" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa"> 1903</a></span> <span class="keyword">typedef</span> <span class="keyword">struct </span>psa_cipher_operation_s <a class="code" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a>;</div><div class="line"><a name="l01904"></a><span class="lineno"> 1904</span> </div><div class="line"><a name="l01951"></a><span class="lineno"> 1951</span> psa_status_t <a class="code" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup</a>(<a class="code" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation,</div><div class="line"><a name="l01952"></a><span class="lineno"> 1952</span>  <a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l01953"></a><span class="lineno"> 1953</span>  psa_algorithm_t alg);</div><div class="line"><a name="l01954"></a><span class="lineno"> 1954</span> </div><div class="line"><a name="l02000"></a><span class="lineno"> 2000</span> psa_status_t <a class="code" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup</a>(<a class="code" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation,</div><div class="line"><a name="l02001"></a><span class="lineno"> 2001</span>  <a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l02002"></a><span class="lineno"> 2002</span>  psa_algorithm_t alg);</div><div class="line"><a name="l02003"></a><span class="lineno"> 2003</span> </div><div class="line"><a name="l02032"></a><span class="lineno"> 2032</span> psa_status_t <a class="code" href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">psa_cipher_generate_iv</a>(<a class="code" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation,</div><div class="line"><a name="l02033"></a><span class="lineno"> 2033</span>  <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *iv,</div><div class="line"><a name="l02034"></a><span class="lineno"> 2034</span>  <span class="keywordtype">size_t</span> iv_size,</div><div class="line"><a name="l02035"></a><span class="lineno"> 2035</span>  <span class="keywordtype">size_t</span> *iv_length);</div><div class="line"><a name="l02036"></a><span class="lineno"> 2036</span> </div><div class="line"><a name="l02067"></a><span class="lineno"> 2067</span> psa_status_t <a class="code" href="group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42">psa_cipher_set_iv</a>(<a class="code" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation,</div><div class="line"><a name="l02068"></a><span class="lineno"> 2068</span>  <span class="keyword">const</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *iv,</div><div class="line"><a name="l02069"></a><span class="lineno"> 2069</span>  <span class="keywordtype">size_t</span> iv_length);</div><div class="line"><a name="l02070"></a><span class="lineno"> 2070</span> </div><div class="line"><a name="l02103"></a><span class="lineno"> 2103</span> psa_status_t <a class="code" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update</a>(<a class="code" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation,</div><div class="line"><a name="l02104"></a><span class="lineno"> 2104</span>  <span class="keyword">const</span> uint8_t *input,</div><div class="line"><a name="l02105"></a><span class="lineno"> 2105</span>  <span class="keywordtype">size_t</span> input_length,</div><div class="line"><a name="l02106"></a><span class="lineno"> 2106</span>  <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *output,</div><div class="line"><a name="l02107"></a><span class="lineno"> 2107</span>  <span class="keywordtype">size_t</span> output_size,</div><div class="line"><a name="l02108"></a><span class="lineno"> 2108</span>  <span class="keywordtype">size_t</span> *output_length);</div><div class="line"><a name="l02109"></a><span class="lineno"> 2109</span> </div><div class="line"><a name="l02141"></a><span class="lineno"> 2141</span> psa_status_t <a class="code" href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">psa_cipher_finish</a>(<a class="code" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation,</div><div class="line"><a name="l02142"></a><span class="lineno"> 2142</span>  uint8_t *output,</div><div class="line"><a name="l02143"></a><span class="lineno"> 2143</span>  <span class="keywordtype">size_t</span> output_size,</div><div class="line"><a name="l02144"></a><span class="lineno"> 2144</span>  <span class="keywordtype">size_t</span> *output_length);</div><div class="line"><a name="l02145"></a><span class="lineno"> 2145</span> </div><div class="line"><a name="l02174"></a><span class="lineno"> 2174</span> psa_status_t <a class="code" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">psa_cipher_abort</a>(<a class="code" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation);</div><div class="line"><a name="l02175"></a><span class="lineno"> 2175</span> </div><div class="line"><a name="l02197"></a><span class="lineno"><a class="line" href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4"> 2197</a></span> <span class="preprocessor">#define PSA_AEAD_TAG_SIZE(alg) \</span></div><div class="line"><a name="l02198"></a><span class="lineno"> 2198</span> <span class="preprocessor"> ((alg) == PSA_ALG_GCM ? 16 : \</span></div><div class="line"><a name="l02199"></a><span class="lineno"> 2199</span> <span class="preprocessor"> (alg) == PSA_ALG_CCM ? 16 : \</span></div><div class="line"><a name="l02200"></a><span class="lineno"> 2200</span> <span class="preprocessor"> 0)</span></div><div class="line"><a name="l02201"></a><span class="lineno"> 2201</span> </div><div class="line"><a name="l02243"></a><span class="lineno"> 2243</span> psa_status_t <a class="code" href="group__aead.html#ga14e4068a3d328515a4884f3037904d54">psa_aead_encrypt</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l02244"></a><span class="lineno"> 2244</span>  psa_algorithm_t alg,</div><div class="line"><a name="l02245"></a><span class="lineno"> 2245</span>  <span class="keyword">const</span> uint8_t *nonce,</div><div class="line"><a name="l02246"></a><span class="lineno"> 2246</span>  <span class="keywordtype">size_t</span> nonce_length,</div><div class="line"><a name="l02247"></a><span class="lineno"> 2247</span>  <span class="keyword">const</span> uint8_t *additional_data,</div><div class="line"><a name="l02248"></a><span class="lineno"> 2248</span>  <span class="keywordtype">size_t</span> additional_data_length,</div><div class="line"><a name="l02249"></a><span class="lineno"> 2249</span>  <span class="keyword">const</span> uint8_t *plaintext,</div><div class="line"><a name="l02250"></a><span class="lineno"> 2250</span>  <span class="keywordtype">size_t</span> plaintext_length,</div><div class="line"><a name="l02251"></a><span class="lineno"> 2251</span>  uint8_t *ciphertext,</div><div class="line"><a name="l02252"></a><span class="lineno"> 2252</span>  <span class="keywordtype">size_t</span> ciphertext_size,</div><div class="line"><a name="l02253"></a><span class="lineno"> 2253</span>  <span class="keywordtype">size_t</span> *ciphertext_length);</div><div class="line"><a name="l02254"></a><span class="lineno"> 2254</span> </div><div class="line"><a name="l02296"></a><span class="lineno"> 2296</span> psa_status_t <a class="code" href="group__aead.html#ga5b88ad2cfbf2e98039858416fa3ebd7a">psa_aead_decrypt</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l02297"></a><span class="lineno"> 2297</span>  psa_algorithm_t alg,</div><div class="line"><a name="l02298"></a><span class="lineno"> 2298</span>  <span class="keyword">const</span> uint8_t *nonce,</div><div class="line"><a name="l02299"></a><span class="lineno"> 2299</span>  <span class="keywordtype">size_t</span> nonce_length,</div><div class="line"><a name="l02300"></a><span class="lineno"> 2300</span>  <span class="keyword">const</span> uint8_t *additional_data,</div><div class="line"><a name="l02301"></a><span class="lineno"> 2301</span>  <span class="keywordtype">size_t</span> additional_data_length,</div><div class="line"><a name="l02302"></a><span class="lineno"> 2302</span>  <span class="keyword">const</span> uint8_t *ciphertext,</div><div class="line"><a name="l02303"></a><span class="lineno"> 2303</span>  <span class="keywordtype">size_t</span> ciphertext_length,</div><div class="line"><a name="l02304"></a><span class="lineno"> 2304</span>  uint8_t *plaintext,</div><div class="line"><a name="l02305"></a><span class="lineno"> 2305</span>  <span class="keywordtype">size_t</span> plaintext_size,</div><div class="line"><a name="l02306"></a><span class="lineno"> 2306</span>  <span class="keywordtype">size_t</span> *plaintext_length);</div><div class="line"><a name="l02307"></a><span class="lineno"> 2307</span> </div><div class="line"><a name="l02322"></a><span class="lineno"><a class="line" href="group__asymmetric.html#ga10c472a35f04051add6b20cc228ffc11"> 2322</a></span> <span class="preprocessor">#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \</span></div><div class="line"><a name="l02323"></a><span class="lineno"> 2323</span> <span class="preprocessor"> (PSA_BITS_TO_BYTES(curve_bits) * 2)</span></div><div class="line"><a name="l02324"></a><span class="lineno"> 2324</span> </div><div class="line"><a name="l02359"></a><span class="lineno"> 2359</span> psa_status_t <a class="code" href="group__asymmetric.html#ga48091460d1ead078d93caa3611aec976">psa_asymmetric_sign</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l02360"></a><span class="lineno"> 2360</span>  psa_algorithm_t alg,</div><div class="line"><a name="l02361"></a><span class="lineno"> 2361</span>  <span class="keyword">const</span> uint8_t *hash,</div><div class="line"><a name="l02362"></a><span class="lineno"> 2362</span>  <span class="keywordtype">size_t</span> hash_length,</div><div class="line"><a name="l02363"></a><span class="lineno"> 2363</span>  uint8_t *signature,</div><div class="line"><a name="l02364"></a><span class="lineno"> 2364</span>  <span class="keywordtype">size_t</span> signature_size,</div><div class="line"><a name="l02365"></a><span class="lineno"> 2365</span>  <span class="keywordtype">size_t</span> *signature_length);</div><div class="line"><a name="l02366"></a><span class="lineno"> 2366</span> </div><div class="line"><a name="l02398"></a><span class="lineno"> 2398</span> psa_status_t <a class="code" href="group__asymmetric.html#gaee3e92946c1c4b3dfa90879e2f7d1321">psa_asymmetric_verify</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l02399"></a><span class="lineno"> 2399</span>  psa_algorithm_t alg,</div><div class="line"><a name="l02400"></a><span class="lineno"> 2400</span>  <span class="keyword">const</span> uint8_t *hash,</div><div class="line"><a name="l02401"></a><span class="lineno"> 2401</span>  <span class="keywordtype">size_t</span> hash_length,</div><div class="line"><a name="l02402"></a><span class="lineno"> 2402</span>  <span class="keyword">const</span> uint8_t *signature,</div><div class="line"><a name="l02403"></a><span class="lineno"> 2403</span>  <span class="keywordtype">size_t</span> signature_length);</div><div class="line"><a name="l02404"></a><span class="lineno"> 2404</span> </div><div class="line"><a name="l02405"></a><span class="lineno"> 2405</span> <span class="preprocessor">#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \</span></div><div class="line"><a name="l02406"></a><span class="lineno"> 2406</span> <span class="preprocessor"> (PSA_ALG_IS_RSA_OAEP(alg) ? \</span></div><div class="line"><a name="l02407"></a><span class="lineno"> 2407</span> <span class="preprocessor"> 2 * PSA_HASH_FINAL_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \</span></div><div class="line"><a name="l02408"></a><span class="lineno"> 2408</span> <span class="preprocessor"> 11 </span><span class="comment">/*PKCS#1v1.5*/</span><span class="preprocessor">)</span></div><div class="line"><a name="l02409"></a><span class="lineno"> 2409</span> </div><div class="line"><a name="l02452"></a><span class="lineno"> 2452</span> psa_status_t <a class="code" href="group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2">psa_asymmetric_encrypt</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l02453"></a><span class="lineno"> 2453</span>  psa_algorithm_t alg,</div><div class="line"><a name="l02454"></a><span class="lineno"> 2454</span>  <span class="keyword">const</span> uint8_t *input,</div><div class="line"><a name="l02455"></a><span class="lineno"> 2455</span>  <span class="keywordtype">size_t</span> input_length,</div><div class="line"><a name="l02456"></a><span class="lineno"> 2456</span>  <span class="keyword">const</span> uint8_t *salt,</div><div class="line"><a name="l02457"></a><span class="lineno"> 2457</span>  <span class="keywordtype">size_t</span> salt_length,</div><div class="line"><a name="l02458"></a><span class="lineno"> 2458</span>  uint8_t *output,</div><div class="line"><a name="l02459"></a><span class="lineno"> 2459</span>  <span class="keywordtype">size_t</span> output_size,</div><div class="line"><a name="l02460"></a><span class="lineno"> 2460</span>  <span class="keywordtype">size_t</span> *output_length);</div><div class="line"><a name="l02461"></a><span class="lineno"> 2461</span> </div><div class="line"><a name="l02504"></a><span class="lineno"> 2504</span> psa_status_t <a class="code" href="group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6">psa_asymmetric_decrypt</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l02505"></a><span class="lineno"> 2505</span>  psa_algorithm_t alg,</div><div class="line"><a name="l02506"></a><span class="lineno"> 2506</span>  <span class="keyword">const</span> uint8_t *input,</div><div class="line"><a name="l02507"></a><span class="lineno"> 2507</span>  <span class="keywordtype">size_t</span> input_length,</div><div class="line"><a name="l02508"></a><span class="lineno"> 2508</span>  <span class="keyword">const</span> uint8_t *salt,</div><div class="line"><a name="l02509"></a><span class="lineno"> 2509</span>  <span class="keywordtype">size_t</span> salt_length,</div><div class="line"><a name="l02510"></a><span class="lineno"> 2510</span>  uint8_t *output,</div><div class="line"><a name="l02511"></a><span class="lineno"> 2511</span>  <span class="keywordtype">size_t</span> output_size,</div><div class="line"><a name="l02512"></a><span class="lineno"> 2512</span>  <span class="keywordtype">size_t</span> *output_length);</div><div class="line"><a name="l02513"></a><span class="lineno"> 2513</span> </div><div class="line"><a name="l02549"></a><span class="lineno"><a class="line" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b"> 2549</a></span> <span class="keyword">typedef</span> <span class="keyword">struct </span>psa_crypto_generator_s <a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a>;</div><div class="line"><a name="l02550"></a><span class="lineno"> 2550</span> </div><div class="line"><a name="l02556"></a><span class="lineno"> 2556</span> <span class="preprocessor">#ifdef __DOXYGEN_ONLY__</span></div><div class="line"><a name="l02557"></a><span class="lineno"> 2557</span> <span class="comment">/* This is an example definition for documentation purposes.</span></div><div class="line"><a name="l02558"></a><span class="lineno"> 2558</span> <span class="comment"> * Implementations should define a suitable value in `crypto_struct.h`.</span></div><div class="line"><a name="l02559"></a><span class="lineno"> 2559</span> <span class="comment"> */</span></div><div class="line"><a name="l02560"></a><span class="lineno"><a class="line" href="group__generators.html#ga4788b471385fc667876fbd8a0d3fe062"> 2560</a></span> <span class="preprocessor">#define PSA_CRYPTO_GENERATOR_INIT {0}</span></div><div class="line"><a name="l02561"></a><span class="lineno"> 2561</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l02562"></a><span class="lineno"> 2562</span> </div><div class="line"><a name="l02565"></a><span class="lineno"> 2565</span> <span class="keyword">static</span> <a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> psa_crypto_generator_init(<span class="keywordtype">void</span>);</div><div class="line"><a name="l02566"></a><span class="lineno"> 2566</span> </div><div class="line"><a name="l02579"></a><span class="lineno"> 2579</span> psa_status_t <a class="code" href="group__generators.html#ga7453491e3b440193be2c5dccc2040fd2">psa_get_generator_capacity</a>(<span class="keyword">const</span> <a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator,</div><div class="line"><a name="l02580"></a><span class="lineno"> 2580</span>  <span class="keywordtype">size_t</span> *capacity);</div><div class="line"><a name="l02581"></a><span class="lineno"> 2581</span> </div><div class="line"><a name="l02607"></a><span class="lineno"> 2607</span> psa_status_t <a class="code" href="group__generators.html#gab5712ad29b78c2b170e64cc5bcfc1bce">psa_generator_read</a>(<a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator,</div><div class="line"><a name="l02608"></a><span class="lineno"> 2608</span>  uint8_t *output,</div><div class="line"><a name="l02609"></a><span class="lineno"> 2609</span>  <span class="keywordtype">size_t</span> output_length);</div><div class="line"><a name="l02610"></a><span class="lineno"> 2610</span> </div><div class="line"><a name="l02654"></a><span class="lineno"> 2654</span> psa_status_t <a class="code" href="group__generators.html#ga06c1ba3d989827d909b4b01ffe983beb">psa_generator_import_key</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l02655"></a><span class="lineno"> 2655</span>  psa_key_type_t type,</div><div class="line"><a name="l02656"></a><span class="lineno"> 2656</span>  <span class="keywordtype">size_t</span> bits,</div><div class="line"><a name="l02657"></a><span class="lineno"> 2657</span>  <a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator);</div><div class="line"><a name="l02658"></a><span class="lineno"> 2658</span> </div><div class="line"><a name="l02681"></a><span class="lineno"> 2681</span> psa_status_t <a class="code" href="group__generators.html#ga563ca64537d90368899286b36d8cf7f3">psa_generator_abort</a>(<a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator);</div><div class="line"><a name="l02682"></a><span class="lineno"> 2682</span> </div><div class="line"><a name="l02727"></a><span class="lineno"> 2727</span> psa_status_t <a class="code" href="group__derivation.html#ga1b6429f443a45e5f3209043abbbe8315">psa_key_derivation</a>(<a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator,</div><div class="line"><a name="l02728"></a><span class="lineno"> 2728</span>  <a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l02729"></a><span class="lineno"> 2729</span>  psa_algorithm_t alg,</div><div class="line"><a name="l02730"></a><span class="lineno"> 2730</span>  <span class="keyword">const</span> uint8_t *salt,</div><div class="line"><a name="l02731"></a><span class="lineno"> 2731</span>  <span class="keywordtype">size_t</span> salt_length,</div><div class="line"><a name="l02732"></a><span class="lineno"> 2732</span>  <span class="keyword">const</span> uint8_t *label,</div><div class="line"><a name="l02733"></a><span class="lineno"> 2733</span>  <span class="keywordtype">size_t</span> label_length,</div><div class="line"><a name="l02734"></a><span class="lineno"> 2734</span>  <span class="keywordtype">size_t</span> capacity);</div><div class="line"><a name="l02735"></a><span class="lineno"> 2735</span> </div><div class="line"><a name="l02761"></a><span class="lineno"> 2761</span> psa_status_t <a class="code" href="group__random.html#ga1985eae417dfbccedf50d5fff54ea8c5">psa_generate_random</a>(uint8_t *output,</div><div class="line"><a name="l02762"></a><span class="lineno"> 2762</span>  <span class="keywordtype">size_t</span> output_size);</div><div class="line"><a name="l02763"></a><span class="lineno"> 2763</span> </div><div class="line"><a name="l02769"></a><span class="lineno"><a class="line" href="structpsa__generate__key__extra__rsa.html"> 2769</a></span> <span class="keyword">typedef</span> <span class="keyword">struct </span>{</div><div class="line"><a name="l02770"></a><span class="lineno"><a class="line" href="structpsa__generate__key__extra__rsa.html#a53ccb9e4375f3c9af6e3ecfe111ce11d"> 2770</a></span>  uint32_t <a class="code" href="structpsa__generate__key__extra__rsa.html#a53ccb9e4375f3c9af6e3ecfe111ce11d">e</a>; </div><div class="line"><a name="l02771"></a><span class="lineno"> 2771</span> } <a class="code" href="structpsa__generate__key__extra__rsa.html">psa_generate_key_extra_rsa</a>;</div><div class="line"><a name="l02772"></a><span class="lineno"> 2772</span> </div><div class="line"><a name="l02815"></a><span class="lineno"> 2815</span> psa_status_t <a class="code" href="group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10">psa_generate_key</a>(<a class="code" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key,</div><div class="line"><a name="l02816"></a><span class="lineno"> 2816</span>  psa_key_type_t type,</div><div class="line"><a name="l02817"></a><span class="lineno"> 2817</span>  <span class="keywordtype">size_t</span> bits,</div><div class="line"><a name="l02818"></a><span class="lineno"> 2818</span>  <span class="keyword">const</span> <span class="keywordtype">void</span> *extra,</div><div class="line"><a name="l02819"></a><span class="lineno"> 2819</span>  <span class="keywordtype">size_t</span> extra_size);</div><div class="line"><a name="l02820"></a><span class="lineno"> 2820</span> </div><div class="line"><a name="l02823"></a><span class="lineno"> 2823</span> <span class="preprocessor">#ifdef __cplusplus</span></div><div class="line"><a name="l02824"></a><span class="lineno"> 2824</span> }</div><div class="line"><a name="l02825"></a><span class="lineno"> 2825</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l02826"></a><span class="lineno"> 2826</span> </div><div class="line"><a name="l02827"></a><span class="lineno"> 2827</span> <span class="comment">/* The file "crypto_sizes.h" contains definitions for size calculation</span></div><div class="line"><a name="l02828"></a><span class="lineno"> 2828</span> <span class="comment"> * macros whose definitions are implementation-specific. */</span></div><div class="line"><a name="l02829"></a><span class="lineno"> 2829</span> <span class="preprocessor">#include "<a class="code" href="crypto__sizes_8h.html">crypto_sizes.h</a>"</span></div><div class="line"><a name="l02830"></a><span class="lineno"> 2830</span> </div><div class="line"><a name="l02831"></a><span class="lineno"> 2831</span> <span class="comment">/* The file "crypto_struct.h" contains definitions for</span></div><div class="line"><a name="l02832"></a><span class="lineno"> 2832</span> <span class="comment"> * implementation-specific structs that are declared above. */</span></div><div class="line"><a name="l02833"></a><span class="lineno"> 2833</span> <span class="preprocessor">#include "crypto_struct.h"</span></div><div class="line"><a name="l02834"></a><span class="lineno"> 2834</span> </div><div class="line"><a name="l02835"></a><span class="lineno"> 2835</span> <span class="comment">/* The file "crypto_extra.h" contains vendor-specific definitions. This</span></div><div class="line"><a name="l02836"></a><span class="lineno"> 2836</span> <span class="comment"> * can include vendor-defined algorithms, extra functions, etc. */</span></div><div class="line"><a name="l02837"></a><span class="lineno"> 2837</span> <span class="preprocessor">#include "crypto_extra.h"</span></div><div class="line"><a name="l02838"></a><span class="lineno"> 2838</span> </div><div class="line"><a name="l02839"></a><span class="lineno"> 2839</span> <span class="preprocessor">#endif </span><span class="comment">/* PSA_CRYPTO_H */</span><span class="preprocessor"></span></div><div class="ttc" id="group__MAC_html_gac92b2930d6728e1be4d011c05d485822"><div class="ttname"><a href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">psa_mac_verify_finish</a></div><div class="ttdeci">psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, const uint8_t *mac, size_t mac_length)</div></div>
+<div class="ttc" id="group__random_html_ga1985eae417dfbccedf50d5fff54ea8c5"><div class="ttname"><a href="group__random.html#ga1985eae417dfbccedf50d5fff54ea8c5">psa_generate_random</a></div><div class="ttdeci">psa_status_t psa_generate_random(uint8_t *output, size_t output_size)</div><div class="ttdoc">Generate random bytes. </div></div>
+<div class="ttc" id="group__asymmetric_html_ga3c0ba402bac217d623dba8320c2240c2"><div class="ttname"><a href="group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2">psa_asymmetric_encrypt</a></div><div class="ttdeci">psa_status_t psa_asymmetric_encrypt(psa_key_slot_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length)</div><div class="ttdoc">Encrypt a short message with a public key. </div></div>
+<div class="ttc" id="group__policy_html_ga613f28712124f9149bd640614376ab5a"><div class="ttname"><a href="group__policy.html#ga613f28712124f9149bd640614376ab5a">psa_get_key_policy</a></div><div class="ttdeci">psa_status_t psa_get_key_policy(psa_key_slot_t key, psa_key_policy_t *policy)</div><div class="ttdoc">Get the usage policy for a key slot. </div></div>
+<div class="ttc" id="group__policy_html_ga7746662b7503e484774d0ecb5d8ac2ab"><div class="ttname"><a href="group__policy.html#ga7746662b7503e484774d0ecb5d8ac2ab">psa_key_policy_get_usage</a></div><div class="ttdeci">psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy)</div><div class="ttdoc">Retrieve the usage field of a policy structure. </div></div>
+<div class="ttc" id="group__derivation_html_ga1b6429f443a45e5f3209043abbbe8315"><div class="ttname"><a href="group__derivation.html#ga1b6429f443a45e5f3209043abbbe8315">psa_key_derivation</a></div><div class="ttdeci">psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, psa_key_slot_t key, psa_algorithm_t alg, const uint8_t *salt, size_t salt_length, const uint8_t *label, size_t label_length, size_t capacity)</div></div>
+<div class="ttc" id="group__crypto__types_html_ga4e8977c145cce5077c4bce7fec890ad9"><div class="ttname"><a href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a></div><div class="ttdeci">uint16_t psa_ecc_curve_t</div><div class="ttdef"><b>Definition:</b> crypto.h:478</div></div>
+<div class="ttc" id="group__generators_html_ga563ca64537d90368899286b36d8cf7f3"><div class="ttname"><a href="group__generators.html#ga563ca64537d90368899286b36d8cf7f3">psa_generator_abort</a></div><div class="ttdeci">psa_status_t psa_generator_abort(psa_crypto_generator_t *generator)</div></div>
+<div class="ttc" id="group__policy_html_gad7faa7e64aa771f7441c44ceff21af19"><div class="ttname"><a href="group__policy.html#gad7faa7e64aa771f7441c44ceff21af19">psa_set_key_policy</a></div><div class="ttdeci">psa_status_t psa_set_key_policy(psa_key_slot_t key, const psa_key_policy_t *policy)</div><div class="ttdoc">Set the usage policy on a key slot. </div></div>
+<div class="ttc" id="group__cipher_html_gafd0caea99cf1052527e4089d37f5ab91"><div class="ttname"><a href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update</a></div><div class="ttdeci">psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, unsigned char *output, size_t output_size, size_t *output_length)</div></div>
+<div class="ttc" id="group__MAC_html_ga68ac2ad3253e9e27fcfbc788a4df8177"><div class="ttname"><a href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup</a></div><div class="ttdeci">psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, psa_key_slot_t key, psa_algorithm_t alg)</div></div>
+<div class="ttc" id="group__cipher_html_ga1359b2101f31637496ce7cc36c6e3d42"><div class="ttname"><a href="group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42">psa_cipher_set_iv</a></div><div class="ttdeci">psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, const unsigned char *iv, size_t iv_length)</div></div>
+<div class="ttc" id="group__generators_html_gab5712ad29b78c2b170e64cc5bcfc1bce"><div class="ttname"><a href="group__generators.html#gab5712ad29b78c2b170e64cc5bcfc1bce">psa_generator_read</a></div><div class="ttdeci">psa_status_t psa_generator_read(psa_crypto_generator_t *generator, uint8_t *output, size_t output_length)</div></div>
+<div class="ttc" id="group__persistence_html_ga1bd1ee6d00ebd9962fc6ad72cbd22ef8"><div class="ttname"><a href="group__persistence.html#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8">psa_set_key_lifetime</a></div><div class="ttdeci">psa_status_t psa_set_key_lifetime(psa_key_slot_t key, psa_key_lifetime_t lifetime)</div><div class="ttdoc">Change the lifetime of a key slot. </div></div>
+<div class="ttc" id="group__hash_html_ga65b16ef97d7f650899b7db4b7d1112ff"><div class="ttname"><a href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">psa_hash_update</a></div><div class="ttdeci">psa_status_t psa_hash_update(psa_hash_operation_t *operation, const uint8_t *input, size_t input_length)</div></div>
+<div class="ttc" id="group__key__management_html_ga2e9a60a9525ce6b3082a72df2080f0c5"><div class="ttname"><a href="group__key__management.html#ga2e9a60a9525ce6b3082a72df2080f0c5">psa_destroy_key</a></div><div class="ttdeci">psa_status_t psa_destroy_key(psa_key_slot_t key)</div><div class="ttdoc">Destroy a key and restore the slot to its default state. </div></div>
+<div class="ttc" id="group__key__management_html_gaf105167657ab1d484cb4a51f93413717"><div class="ttname"><a href="group__key__management.html#gaf105167657ab1d484cb4a51f93413717">psa_get_key_information</a></div><div class="ttdeci">psa_status_t psa_get_key_information(psa_key_slot_t key, psa_key_type_t *type, size_t *bits)</div><div class="ttdoc">Get basic metadata about a key. </div></div>
+<div class="ttc" id="group__basic_html_ga2de150803fc2f7dc6101d5af7e921dd9"><div class="ttname"><a href="group__basic.html#ga2de150803fc2f7dc6101d5af7e921dd9">psa_crypto_init</a></div><div class="ttdeci">psa_status_t psa_crypto_init(void)</div><div class="ttdoc">Library initialization. </div></div>
+<div class="ttc" id="group__generators_html_ga06c1ba3d989827d909b4b01ffe983beb"><div class="ttname"><a href="group__generators.html#ga06c1ba3d989827d909b4b01ffe983beb">psa_generator_import_key</a></div><div class="ttdeci">psa_status_t psa_generator_import_key(psa_key_slot_t key, psa_key_type_t type, size_t bits, psa_crypto_generator_t *generator)</div></div>
+<div class="ttc" id="group__MAC_html_gac22bc0125580c96724a09226cfbc97f2"><div class="ttname"><a href="group__MAC.html#gac22bc0125580c96724a09226cfbc97f2">psa_mac_sign_finish</a></div><div class="ttdeci">psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, size_t *mac_length)</div></div>
+<div class="ttc" id="group__cipher_html_ga1dcb58b8befe23f8a4d7a1d49c99249b"><div class="ttname"><a href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">psa_cipher_finish</a></div><div class="ttdeci">psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length)</div></div>
+<div class="ttc" id="group__cipher_html_ga735c9d51b820e1d4cb45f2406ebfae98"><div class="ttname"><a href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup</a></div><div class="ttdeci">psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, psa_key_slot_t key, psa_algorithm_t alg)</div></div>
+<div class="ttc" id="group__cipher_html_ga44857cf5e0c3d134a3c560f8ff5b50aa"><div class="ttname"><a href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">psa_cipher_generate_iv</a></div><div class="ttdeci">psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, unsigned char *iv, size_t iv_size, size_t *iv_length)</div></div>
+<div class="ttc" id="group__hash_html_ga7be923c5700c9c70ef77ee9b76d1a5c0"><div class="ttname"><a href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">psa_hash_verify</a></div><div class="ttdeci">psa_status_t psa_hash_verify(psa_hash_operation_t *operation, const uint8_t *hash, size_t hash_length)</div></div>
+<div class="ttc" id="group__asymmetric_html_ga48091460d1ead078d93caa3611aec976"><div class="ttname"><a href="group__asymmetric.html#ga48091460d1ead078d93caa3611aec976">psa_asymmetric_sign</a></div><div class="ttdeci">psa_status_t psa_asymmetric_sign(psa_key_slot_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length)</div><div class="ttdoc">Sign a hash or short message with a private key. </div></div>
+<div class="ttc" id="group__policy_html_gad49eb85e3fcbe70f763f511ac83e762e"><div class="ttname"><a href="group__policy.html#gad49eb85e3fcbe70f763f511ac83e762e">psa_key_policy_init</a></div><div class="ttdeci">void psa_key_policy_init(psa_key_policy_t *policy)</div><div class="ttdoc">Initialize a key policy structure to a default that forbids all usage of the key. ...</div></div>
+<div class="ttc" id="structpsa__generate__key__extra__rsa_html_a53ccb9e4375f3c9af6e3ecfe111ce11d"><div class="ttname"><a href="structpsa__generate__key__extra__rsa.html#a53ccb9e4375f3c9af6e3ecfe111ce11d">psa_generate_key_extra_rsa::e</a></div><div class="ttdeci">uint32_t e</div><div class="ttdef"><b>Definition:</b> crypto.h:2770</div></div>
+<div class="ttc" id="group__crypto__types_html_gac2e4d47f1300d73c2f829a6d99252d69"><div class="ttname"><a href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a></div><div class="ttdeci">uint32_t psa_algorithm_t</div><div class="ttdoc">Encoding of a cryptographic algorithm. </div><div class="ttdef"><b>Definition:</b> crypto.h:560</div></div>
+<div class="ttc" id="group__hash_html_ga3c4205d2ce66c4095fc5c78c25273fab"><div class="ttname"><a href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a></div><div class="ttdeci">struct psa_hash_operation_s psa_hash_operation_t</div><div class="ttdef"><b>Definition:</b> crypto.h:1447</div></div>
+<div class="ttc" id="group__MAC_html_gacd8dd54855ba1bc0a03f104f252884fd"><div class="ttname"><a href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">psa_mac_abort</a></div><div class="ttdeci">psa_status_t psa_mac_abort(psa_mac_operation_t *operation)</div></div>
+<div class="ttc" id="group__hash_html_ga8d72896cf70fc4d514c5c6b978912515"><div class="ttname"><a href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup</a></div><div class="ttdeci">psa_status_t psa_hash_setup(psa_hash_operation_t *operation, psa_algorithm_t alg)</div></div>
+<div class="ttc" id="group__aead_html_ga5b88ad2cfbf2e98039858416fa3ebd7a"><div class="ttname"><a href="group__aead.html#ga5b88ad2cfbf2e98039858416fa3ebd7a">psa_aead_decrypt</a></div><div class="ttdeci">psa_status_t psa_aead_decrypt(psa_key_slot_t key, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)</div></div>
+<div class="ttc" id="group__key__management_html_gace37363530e2525a2562f07ceec8efb5"><div class="ttname"><a href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5">psa_import_key</a></div><div class="ttdeci">psa_status_t psa_import_key(psa_key_slot_t key, psa_key_type_t type, const uint8_t *data, size_t data_length)</div><div class="ttdoc">Import a key in binary format. </div></div>
+<div class="ttc" id="group__policy_html_ga7bb9de71337e0e98de843aa7f9b55f25"><div class="ttname"><a href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a></div><div class="ttdeci">uint32_t psa_key_usage_t</div><div class="ttdoc">Encoding of permitted usage on a key. </div><div class="ttdef"><b>Definition:</b> crypto.h:1225</div></div>
+<div class="ttc" id="group__persistence_html_gaf0daaa1dba14dc324ca83dfe1495a5e2"><div class="ttname"><a href="group__persistence.html#gaf0daaa1dba14dc324ca83dfe1495a5e2">psa_get_key_lifetime</a></div><div class="ttdeci">psa_status_t psa_get_key_lifetime(psa_key_slot_t key, psa_key_lifetime_t *lifetime)</div><div class="ttdoc">Retrieve the lifetime of a key slot. </div></div>
+<div class="ttc" id="group__policy_html_gaf553efd409845b6d09ff25ce2ba36607"><div class="ttname"><a href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a></div><div class="ttdeci">struct psa_key_policy_s psa_key_policy_t</div><div class="ttdef"><b>Definition:</b> crypto.h:1291</div></div>
+<div class="ttc" id="group__aead_html_ga14e4068a3d328515a4884f3037904d54"><div class="ttname"><a href="group__aead.html#ga14e4068a3d328515a4884f3037904d54">psa_aead_encrypt</a></div><div class="ttdeci">psa_status_t psa_aead_encrypt(psa_key_slot_t key, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)</div></div>
+<div class="ttc" id="group__asymmetric_html_gaee3e92946c1c4b3dfa90879e2f7d1321"><div class="ttname"><a href="group__asymmetric.html#gaee3e92946c1c4b3dfa90879e2f7d1321">psa_asymmetric_verify</a></div><div class="ttdeci">psa_status_t psa_asymmetric_verify(psa_key_slot_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length)</div><div class="ttdoc">Verify the signature a hash or short message using a public key. </div></div>
+<div class="ttc" id="group__policy_html_gac16792fd6d375a5f76d372090df40607"><div class="ttname"><a href="group__policy.html#gac16792fd6d375a5f76d372090df40607">psa_key_policy_set_usage</a></div><div class="ttdeci">void psa_key_policy_set_usage(psa_key_policy_t *policy, psa_key_usage_t usage, psa_algorithm_t alg)</div><div class="ttdoc">Set the standard fields of a policy structure. </div></div>
+<div class="ttc" id="group__random_html_gada1d701903f6b4de6b4c6a1d613c1b10"><div class="ttname"><a href="group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10">psa_generate_key</a></div><div class="ttdeci">psa_status_t psa_generate_key(psa_key_slot_t key, psa_key_type_t type, size_t bits, const void *extra, size_t extra_size)</div><div class="ttdoc">Generate a key or key pair. </div></div>
+<div class="ttc" id="group__key__management_html_gaa67bc459b20028b268f3d75a05afe022"><div class="ttname"><a href="group__key__management.html#gaa67bc459b20028b268f3d75a05afe022">psa_export_key</a></div><div class="ttdeci">psa_status_t psa_export_key(psa_key_slot_t key, uint8_t *data, size_t data_size, size_t *data_length)</div><div class="ttdoc">Export a key in binary format. </div></div>
+<div class="ttc" id="crypto__sizes_8h_html"><div class="ttname"><a href="crypto__sizes_8h.html">crypto_sizes.h</a></div><div class="ttdoc">PSA cryptography module: Mbed TLS buffer size macros. </div></div>
+<div class="ttc" id="group__MAC_html_ga5560af371497babefe03c9da4e8a1c05"><div class="ttname"><a href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">psa_mac_update</a></div><div class="ttdeci">psa_status_t psa_mac_update(psa_mac_operation_t *operation, const uint8_t *input, size_t input_length)</div></div>
+<div class="ttc" id="group__hash_html_gab0b4d5f9912a615559497a467b532928"><div class="ttname"><a href="group__hash.html#gab0b4d5f9912a615559497a467b532928">psa_hash_abort</a></div><div class="ttdeci">psa_status_t psa_hash_abort(psa_hash_operation_t *operation)</div></div>
+<div class="ttc" id="group__cipher_html_ga1399de29db657e3737bb09927aae51fa"><div class="ttname"><a href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a></div><div class="ttdeci">struct psa_cipher_operation_s psa_cipher_operation_t</div><div class="ttdef"><b>Definition:</b> crypto.h:1903</div></div>
+<div class="ttc" id="group__crypto__types_html_ga578159487dfc7096cb191b0d2befe628"><div class="ttname"><a href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a></div><div class="ttdeci">uint32_t psa_key_type_t</div><div class="ttdoc">Encoding of a key type. </div><div class="ttdef"><b>Definition:</b> crypto.h:346</div></div>
+<div class="ttc" id="group__key__management_html_ga7355b38f8eb9330db2786604f4a83a3b"><div class="ttname"><a href="group__key__management.html#ga7355b38f8eb9330db2786604f4a83a3b">psa_export_public_key</a></div><div class="ttdeci">psa_status_t psa_export_public_key(psa_key_slot_t key, uint8_t *data, size_t data_size, size_t *data_length)</div><div class="ttdoc">Export a public key or the public part of a key pair in binary format. </div></div>
+<div class="ttc" id="group__MAC_html_gac7d1c3d075ce1604a54cbbc9933fa39d"><div class="ttname"><a href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup</a></div><div class="ttdeci">psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, psa_key_slot_t key, psa_algorithm_t alg)</div></div>
+<div class="ttc" id="group__asymmetric_html_ga3094be979f37aa2865c283167ba907e6"><div class="ttname"><a href="group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6">psa_asymmetric_decrypt</a></div><div class="ttdeci">psa_status_t psa_asymmetric_decrypt(psa_key_slot_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length)</div><div class="ttdoc">Decrypt a short message with a private key. </div></div>
+<div class="ttc" id="group__cipher_html_ga8ce1efaa648d7e0dd00e878d655d2950"><div class="ttname"><a href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup</a></div><div class="ttdeci">psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, psa_key_slot_t key, psa_algorithm_t alg)</div></div>
+<div class="ttc" id="group__platform_html_gac3da92a6b8a7f0c01dc348f8e0432e4c"><div class="ttname"><a href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a></div><div class="ttdeci">_unsigned_integral_type_ psa_key_slot_t</div><div class="ttdoc">Key slot number. </div><div class="ttdef"><b>Definition:</b> crypto.h:51</div></div>
+<div class="ttc" id="group__MAC_html_ga78f0838b0c4e3db28b26355624d4bd37"><div class="ttname"><a href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a></div><div class="ttdeci">struct psa_mac_operation_s psa_mac_operation_t</div><div class="ttdef"><b>Definition:</b> crypto.h:1660</div></div>
+<div class="ttc" id="group__persistence_html_ga6821ff6dd39dc2bc370ded760ad8b0cf"><div class="ttname"><a href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a></div><div class="ttdeci">uint32_t psa_key_lifetime_t</div><div class="ttdef"><b>Definition:</b> crypto.h:1374</div></div>
+<div class="ttc" id="group__policy_html_gaadf16b89ace53e1d2cb5bcb0aef24c86"><div class="ttname"><a href="group__policy.html#gaadf16b89ace53e1d2cb5bcb0aef24c86">psa_key_policy_get_algorithm</a></div><div class="ttdeci">psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy)</div><div class="ttdoc">Retrieve the algorithm field of a policy structure. </div></div>
+<div class="ttc" id="group__generators_html_ga7453491e3b440193be2c5dccc2040fd2"><div class="ttname"><a href="group__generators.html#ga7453491e3b440193be2c5dccc2040fd2">psa_get_generator_capacity</a></div><div class="ttdeci">psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, size_t *capacity)</div></div>
+<div class="ttc" id="group__basic_html_ga05676e70ba5c6a7565aff3c36677c1f9"><div class="ttname"><a href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a></div><div class="ttdeci">int32_t psa_status_t</div><div class="ttdoc">Function return status. </div><div class="ttdef"><b>Definition:</b> crypto.h:85</div></div>
+<div class="ttc" id="group__cipher_html_gaad482cdca2098bca0620596aaa02eaa4"><div class="ttname"><a href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">psa_cipher_abort</a></div><div class="ttdeci">psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)</div></div>
+<div class="ttc" id="group__generators_html_ga1f894c4fba202ef8e307d72caf489e3b"><div class="ttname"><a href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a></div><div class="ttdeci">struct psa_crypto_generator_s psa_crypto_generator_t</div><div class="ttdef"><b>Definition:</b> crypto.h:2549</div></div>
+<div class="ttc" id="group__hash_html_ga4795fd06a0067b0adcd92e9627b8c97e"><div class="ttname"><a href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">psa_hash_finish</a></div><div class="ttdeci">psa_status_t psa_hash_finish(psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length)</div></div>
+<div class="ttc" id="structpsa__generate__key__extra__rsa_html"><div class="ttname"><a href="structpsa__generate__key__extra__rsa.html">psa_generate_key_extra_rsa</a></div><div class="ttdef"><b>Definition:</b> crypto.h:2769</div></div>
+</div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/crypto__sizes_8h.html b/docs/html/crypto__sizes_8h.html
new file mode 100644
index 0000000..f52fc16
--- /dev/null
+++ b/docs/html/crypto__sizes_8h.html
@@ -0,0 +1,462 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: psa/crypto_sizes.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_7dae9cfde651cd3cb034485ce5e391b9.html">psa</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#define-members">Macros</a> </div>
+ <div class="headertitle">
+<div class="title">crypto_sizes.h File Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>PSA cryptography module: Mbed TLS buffer size macros.
+<a href="#details">More...</a></p>
+<div class="textblock"><code>#include "../mbedtls/config.h"</code><br />
+</div><div class="textblock"><div class="dynheader">
+Include dependency graph for crypto_sizes.h:</div>
+<div class="dyncontent">
+<div class="center"><img src="crypto__sizes_8h__incl.png" border="0" usemap="#psa_2crypto__sizes_8h" alt=""/></div>
+<map name="psa_2crypto__sizes_8h" id="psa_2crypto__sizes_8h">
+</map>
+</div>
+</div><div class="textblock"><div class="dynheader">
+This graph shows which files directly or indirectly include this file:</div>
+<div class="dyncontent">
+<div class="center"><img src="crypto__sizes_8h__dep__incl.png" border="0" usemap="#psa_2crypto__sizes_8hdep" alt=""/></div>
+<map name="psa_2crypto__sizes_8hdep" id="psa_2crypto__sizes_8hdep">
+<area shape="rect" id="node2" href="crypto_8h.html" title="Platform Security Architecture cryptography module. " alt="" coords="24,80,119,107"/>
+</map>
+</div>
+</div>
+<p><a href="crypto__sizes_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:a6ce1014efbbc0bcca286ef7f9a72cb29"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto__sizes_8h.html#a6ce1014efbbc0bcca286ef7f9a72cb29">PSA_HASH_MAX_SIZE</a>   64</td></tr>
+<tr class="separator:a6ce1014efbbc0bcca286ef7f9a72cb29"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:a123539632874601194b1d86a398e14ff"><td class="memItemLeft" align="right" valign="top"><a id="a123539632874601194b1d86a398e14ff"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_HMAC_MAX_HASH_BLOCK_SIZE</b>   128</td></tr>
+<tr class="separator:a123539632874601194b1d86a398e14ff"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:a4681cc4f6226883a2160122c562ca682"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto__sizes_8h.html#a4681cc4f6226883a2160122c562ca682">PSA_MAC_MAX_SIZE</a>   <a class="el" href="crypto__sizes_8h.html#a6ce1014efbbc0bcca286ef7f9a72cb29">PSA_HASH_MAX_SIZE</a></td></tr>
+<tr class="separator:a4681cc4f6226883a2160122c562ca682"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:a2ab9324235c63e9e8cdee5bb1793eabe"><td class="memItemLeft" align="right" valign="top"><a id="a2ab9324235c63e9e8cdee5bb1793eabe"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_VENDOR_RSA_MAX_KEY_BITS</b>   4096</td></tr>
+<tr class="separator:a2ab9324235c63e9e8cdee5bb1793eabe"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:a81080a6cbbab87f35b114cb991e3f550"><td class="memItemLeft" align="right" valign="top"><a id="a81080a6cbbab87f35b114cb991e3f550"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_VENDOR_ECC_MAX_CURVE_BITS</b>   521</td></tr>
+<tr class="separator:a81080a6cbbab87f35b114cb991e3f550"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ad755101764dba14589e5919ee41be7ca"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto__sizes_8h.html#ad755101764dba14589e5919ee41be7ca">PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE</a></td></tr>
+<tr class="separator:ad755101764dba14589e5919ee41be7ca"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:aa84c5fb384ac7cb1bfc52adde96588ee"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto__sizes_8h.html#aa84c5fb384ac7cb1bfc52adde96588ee">PSA_MAC_FINAL_SIZE</a>(key_type, key_bits, alg)</td></tr>
+<tr class="separator:aa84c5fb384ac7cb1bfc52adde96588ee"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:a85667d47a7aa6c7b99a80e5273671266"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto__sizes_8h.html#a85667d47a7aa6c7b99a80e5273671266">PSA_AEAD_ENCRYPT_OUTPUT_SIZE</a>(alg, plaintext_length)</td></tr>
+<tr class="separator:a85667d47a7aa6c7b99a80e5273671266"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:a1d057796166c16eb673ad1997e48a60b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto__sizes_8h.html#a1d057796166c16eb673ad1997e48a60b">PSA_AEAD_DECRYPT_OUTPUT_SIZE</a>(alg, ciphertext_length)</td></tr>
+<tr class="separator:a1d057796166c16eb673ad1997e48a60b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:a77565b9b4fe6d8730fd2120f4c8378ab"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto__sizes_8h.html#a77565b9b4fe6d8730fd2120f4c8378ab">PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE</a>(key_type, key_bits, alg)</td></tr>
+<tr class="separator:a77565b9b4fe6d8730fd2120f4c8378ab"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:a66ba3bd93e5ec52870ccc3848778bad8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto__sizes_8h.html#a66ba3bd93e5ec52870ccc3848778bad8">PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE</a>(key_type, key_bits, alg)</td></tr>
+<tr class="separator:a66ba3bd93e5ec52870ccc3848778bad8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:a61a246f3eac41989821d982e56fea6c1"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto__sizes_8h.html#a61a246f3eac41989821d982e56fea6c1">PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE</a>(key_type, key_bits, alg)</td></tr>
+<tr class="separator:a61a246f3eac41989821d982e56fea6c1"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>PSA cryptography module: Mbed TLS buffer size macros. </p>
+<dl class="section note"><dt>Note</dt><dd>This file may not be included directly. Applications must include <a class="el" href="crypto_8h.html" title="Platform Security Architecture cryptography module. ">psa/crypto.h</a>.</dd></dl>
+<p>This file contains the definitions of macros that are useful to compute buffer sizes. The signatures and semantics of these macros are standardized, but the definitions are not, because they depend on the available algorithms and, in some cases, on permitted tolerances on buffer sizes.</p>
+<p>In implementations with isolation between the application and the cryptography module, implementers should take care to ensure that the definitions that are exposed to applications match what the module implements.</p>
+<p>Macros that compute sizes whose values do not depend on the implementation are in <a class="el" href="crypto_8h.html" title="Platform Security Architecture cryptography module. ">crypto.h</a>. </p>
+</div><h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="a1d057796166c16eb673ad1997e48a60b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1d057796166c16eb673ad1997e48a60b">◆ </a></span>PSA_AEAD_DECRYPT_OUTPUT_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_AEAD_DECRYPT_OUTPUT_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> </td>
+ <td class="paramname">ciphertext_length </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(<a class="code" href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4">PSA_AEAD_TAG_SIZE</a>(alg) != 0 ? \</div><div class="line"> (plaintext_length) - <a class="code" href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4">PSA_AEAD_TAG_SIZE</a>(alg) : \</div><div class="line"> 0)</div><div class="ttc" id="group__aead_html_ga337ef01fe3c9f71d62ccced33e8917f4"><div class="ttname"><a href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4">PSA_AEAD_TAG_SIZE</a></div><div class="ttdeci">#define PSA_AEAD_TAG_SIZE(alg)</div><div class="ttdef"><b>Definition:</b> crypto.h:2197</div></div>
+</div><!-- fragment --><p>The maximum size of the output of <a class="el" href="group__aead.html#ga5b88ad2cfbf2e98039858416fa3ebd7a">psa_aead_decrypt()</a>, in bytes.</p>
+<p>If the size of the plaintext buffer is at least this large, it is guaranteed that <a class="el" href="group__aead.html#ga5b88ad2cfbf2e98039858416fa3ebd7a">psa_aead_decrypt()</a> will not fail due to an insufficient buffer size. Depending on the algorithm, the actual size of the plaintext may be smaller.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An AEAD algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8">PSA_ALG_IS_AEAD(alg)</a> is true). </td></tr>
+ <tr><td class="paramname">ciphertext_length</td><td>Size of the plaintext in bytes.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The AEAD ciphertext size for the specified algorithm. If the AEAD algorithm is not recognized, return 0. An implementation may return either 0 or a correct size for an AEAD algorithm that it recognizes, but does not support. </dd></dl>
+
+</div>
+</div>
+<a id="a85667d47a7aa6c7b99a80e5273671266"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a85667d47a7aa6c7b99a80e5273671266">◆ </a></span>PSA_AEAD_ENCRYPT_OUTPUT_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> </td>
+ <td class="paramname">plaintext_length </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(<a class="code" href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4">PSA_AEAD_TAG_SIZE</a>(alg) != 0 ? \</div><div class="line"> (plaintext_length) + <a class="code" href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4">PSA_AEAD_TAG_SIZE</a>(alg) : \</div><div class="line"> 0)</div><div class="ttc" id="group__aead_html_ga337ef01fe3c9f71d62ccced33e8917f4"><div class="ttname"><a href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4">PSA_AEAD_TAG_SIZE</a></div><div class="ttdeci">#define PSA_AEAD_TAG_SIZE(alg)</div><div class="ttdef"><b>Definition:</b> crypto.h:2197</div></div>
+</div><!-- fragment --><p>The maximum size of the output of <a class="el" href="group__aead.html#ga14e4068a3d328515a4884f3037904d54">psa_aead_encrypt()</a>, in bytes.</p>
+<p>If the size of the ciphertext buffer is at least this large, it is guaranteed that <a class="el" href="group__aead.html#ga14e4068a3d328515a4884f3037904d54">psa_aead_encrypt()</a> will not fail due to an insufficient buffer size. Depending on the algorithm, the actual size of the ciphertext may be smaller.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An AEAD algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8">PSA_ALG_IS_AEAD(alg)</a> is true). </td></tr>
+ <tr><td class="paramname">plaintext_length</td><td>Size of the plaintext in bytes.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The AEAD ciphertext size for the specified algorithm. If the AEAD algorithm is not recognized, return 0. An implementation may return either 0 or a correct size for an AEAD algorithm that it recognizes, but does not support. </dd></dl>
+
+</div>
+</div>
+<a id="a61a246f3eac41989821d982e56fea6c1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a61a246f3eac41989821d982e56fea6c1">◆ </a></span>PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">key_type, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> </td>
+ <td class="paramname">key_bits, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(<a class="code" href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a">PSA_KEY_TYPE_IS_RSA</a>(key_type) ? \</div><div class="line"> PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \</div><div class="line"> 0)</div><div class="ttc" id="group__crypto__types_html_ga0e1d8f241228e49c9cadadfb4579ef1a"><div class="ttname"><a href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a">PSA_KEY_TYPE_IS_RSA</a></div><div class="ttdeci">#define PSA_KEY_TYPE_IS_RSA(type)</div><div class="ttdef"><b>Definition:</b> crypto.h:463</div></div>
+</div><!-- fragment --><p>Safe output buffer size for <a class="el" href="group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6" title="Decrypt a short message with a private key. ">psa_asymmetric_decrypt()</a>.</p>
+<p>This macro returns a safe buffer size for a ciphertext produced using a key of the specified type and size, with the specified algorithm. Note that the actual size of the ciphertext may be smaller, depending on the algorithm.</p>
+<dl class="section warning"><dt>Warning</dt><dd>This function may call its arguments multiple times or zero times, so you should not pass arguments that contain side effects.</dd></dl>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">key_type</td><td>An asymmetric key type (this may indifferently be a key pair type or a public key type). </td></tr>
+ <tr><td class="paramname">key_bits</td><td>The size of the key in bits. </td></tr>
+ <tr><td class="paramname">alg</td><td>The signature algorithm.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>If the parameters are valid and supported, return a buffer size in bytes that guarantees that <a class="el" href="group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6" title="Decrypt a short message with a private key. ">psa_asymmetric_decrypt()</a> will not fail with <a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a>. If the parameters are a valid combination that is not supported by the implementation, this macro either shall return either a sensible size or 0. If the parameters are not valid, the return value is unspecified. </dd></dl>
+
+</div>
+</div>
+<a id="a66ba3bd93e5ec52870ccc3848778bad8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a66ba3bd93e5ec52870ccc3848778bad8">◆ </a></span>PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">key_type, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> </td>
+ <td class="paramname">key_bits, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(<a class="code" href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a">PSA_KEY_TYPE_IS_RSA</a>(key_type) ? \</div><div class="line"> ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \</div><div class="line"> 0)</div><div class="ttc" id="group__crypto__types_html_ga0e1d8f241228e49c9cadadfb4579ef1a"><div class="ttname"><a href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a">PSA_KEY_TYPE_IS_RSA</a></div><div class="ttdeci">#define PSA_KEY_TYPE_IS_RSA(type)</div><div class="ttdef"><b>Definition:</b> crypto.h:463</div></div>
+</div><!-- fragment --><p>Safe output buffer size for <a class="el" href="group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2" title="Encrypt a short message with a public key. ">psa_asymmetric_encrypt()</a>.</p>
+<p>This macro returns a safe buffer size for a ciphertext produced using a key of the specified type and size, with the specified algorithm. Note that the actual size of the ciphertext may be smaller, depending on the algorithm.</p>
+<dl class="section warning"><dt>Warning</dt><dd>This function may call its arguments multiple times or zero times, so you should not pass arguments that contain side effects.</dd></dl>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">key_type</td><td>An asymmetric key type (this may indifferently be a key pair type or a public key type). </td></tr>
+ <tr><td class="paramname">key_bits</td><td>The size of the key in bits. </td></tr>
+ <tr><td class="paramname">alg</td><td>The signature algorithm.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>If the parameters are valid and supported, return a buffer size in bytes that guarantees that <a class="el" href="group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2" title="Encrypt a short message with a public key. ">psa_asymmetric_encrypt()</a> will not fail with <a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a>. If the parameters are a valid combination that is not supported by the implementation, this macro either shall return either a sensible size or 0. If the parameters are not valid, the return value is unspecified. </dd></dl>
+
+</div>
+</div>
+<a id="a77565b9b4fe6d8730fd2120f4c8378ab"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a77565b9b4fe6d8730fd2120f4c8378ab">◆ </a></span>PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">key_type, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> </td>
+ <td class="paramname">key_bits, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(<a class="code" href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a">PSA_KEY_TYPE_IS_RSA</a>(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \</div><div class="line"> <a class="code" href="group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66">PSA_KEY_TYPE_IS_ECC</a>(key_type) ? <a class="code" href="group__asymmetric.html#ga10c472a35f04051add6b20cc228ffc11">PSA_ECDSA_SIGNATURE_SIZE</a>(key_bits) : \</div><div class="line"> ((void)alg, 0))</div><div class="ttc" id="group__crypto__types_html_ga0e1d8f241228e49c9cadadfb4579ef1a"><div class="ttname"><a href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a">PSA_KEY_TYPE_IS_RSA</a></div><div class="ttdeci">#define PSA_KEY_TYPE_IS_RSA(type)</div><div class="ttdef"><b>Definition:</b> crypto.h:463</div></div>
+<div class="ttc" id="group__asymmetric_html_ga10c472a35f04051add6b20cc228ffc11"><div class="ttname"><a href="group__asymmetric.html#ga10c472a35f04051add6b20cc228ffc11">PSA_ECDSA_SIGNATURE_SIZE</a></div><div class="ttdeci">#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits)</div><div class="ttdoc">ECDSA signature size for a given curve bit size. </div><div class="ttdef"><b>Definition:</b> crypto.h:2322</div></div>
+<div class="ttc" id="group__crypto__types_html_ga88e01fa06b585654689a99bcc06bbe66"><div class="ttname"><a href="group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66">PSA_KEY_TYPE_IS_ECC</a></div><div class="ttdeci">#define PSA_KEY_TYPE_IS_ECC(type)</div><div class="ttdef"><b>Definition:</b> crypto.h:467</div></div>
+</div><!-- fragment --><p>Safe signature buffer size for <a class="el" href="group__asymmetric.html#ga48091460d1ead078d93caa3611aec976" title="Sign a hash or short message with a private key. ">psa_asymmetric_sign()</a>.</p>
+<p>This macro returns a safe buffer size for a signature using a key of the specified type and size, with the specified algorithm. Note that the actual size of the signature may be smaller (some algorithms produce a variable-size signature).</p>
+<dl class="section warning"><dt>Warning</dt><dd>This function may call its arguments multiple times or zero times, so you should not pass arguments that contain side effects.</dd></dl>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">key_type</td><td>An asymmetric key type (this may indifferently be a key pair type or a public key type). </td></tr>
+ <tr><td class="paramname">key_bits</td><td>The size of the key in bits. </td></tr>
+ <tr><td class="paramname">alg</td><td>The signature algorithm.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>If the parameters are valid and supported, return a buffer size in bytes that guarantees that <a class="el" href="group__asymmetric.html#ga48091460d1ead078d93caa3611aec976" title="Sign a hash or short message with a private key. ">psa_asymmetric_sign()</a> will not fail with <a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a>. If the parameters are a valid combination that is not supported by the implementation, this macro either shall return either a sensible size or 0. If the parameters are not valid, the return value is unspecified. </dd></dl>
+
+</div>
+</div>
+<a id="ad755101764dba14589e5919ee41be7ca"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad755101764dba14589e5919ee41be7ca">◆ </a></span>PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">PSA_BITS_TO_BYTES( \</div><div class="line"> PSA_VENDOR_RSA_MAX_KEY_BITS > PSA_VENDOR_ECC_MAX_CURVE_BITS ? \</div><div class="line"> PSA_VENDOR_RSA_MAX_KEY_BITS : \</div><div class="line"> PSA_VENDOR_ECC_MAX_CURVE_BITS \</div><div class="line"> )</div></div><!-- fragment --><p>Maximum size of an asymmetric signature.</p>
+<p>This macro must expand to a compile-time constant integer. This value should be the maximum size of a MAC supported by the implementation, in bytes, and must be no smaller than this maximum. </p>
+
+</div>
+</div>
+<a id="a6ce1014efbbc0bcca286ef7f9a72cb29"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a6ce1014efbbc0bcca286ef7f9a72cb29">◆ </a></span>PSA_HASH_MAX_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_HASH_MAX_SIZE   64</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Maximum size of a hash.</p>
+<p>This macro must expand to a compile-time constant integer. This value should be the maximum size of a hash supported by the implementation, in bytes, and must be no smaller than this maximum. </p>
+
+</div>
+</div>
+<a id="aa84c5fb384ac7cb1bfc52adde96588ee"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa84c5fb384ac7cb1bfc52adde96588ee">◆ </a></span>PSA_MAC_FINAL_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_MAC_FINAL_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">key_type, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> </td>
+ <td class="paramname">key_bits, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(<a class="code" href="group__crypto__types.html#ga4a050c3c3cbc6eb96418f18847601c8a">PSA_ALG_IS_HMAC</a>(alg) ? <a class="code" href="group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99">PSA_HASH_SIZE</a>(PSA_ALG_HMAC_HASH(alg)) : \</div><div class="line"> PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? <a class="code" href="group__crypto__types.html#gacaa366bdeb0413e63e87a667c5457b2e">PSA_BLOCK_CIPHER_BLOCK_SIZE</a>(key_type) : \</div><div class="line"> 0)</div><div class="ttc" id="group__crypto__types_html_gacaa366bdeb0413e63e87a667c5457b2e"><div class="ttname"><a href="group__crypto__types.html#gacaa366bdeb0413e63e87a667c5457b2e">PSA_BLOCK_CIPHER_BLOCK_SIZE</a></div><div class="ttdeci">#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type)</div><div class="ttdef"><b>Definition:</b> crypto.h:544</div></div>
+<div class="ttc" id="group__hash_html_gaef340331ce3cba2b57e1fc5624bf1f99"><div class="ttname"><a href="group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99">PSA_HASH_SIZE</a></div><div class="ttdeci">#define PSA_HASH_SIZE(alg)</div><div class="ttdef"><b>Definition:</b> crypto.h:1463</div></div>
+<div class="ttc" id="group__crypto__types_html_ga4a050c3c3cbc6eb96418f18847601c8a"><div class="ttname"><a href="group__crypto__types.html#ga4a050c3c3cbc6eb96418f18847601c8a">PSA_ALG_IS_HMAC</a></div><div class="ttdeci">#define PSA_ALG_IS_HMAC(alg)</div><div class="ttdef"><b>Definition:</b> crypto.h:721</div></div>
+</div><!-- fragment --><p>The size of the output of <a class="el" href="group__MAC.html#gac22bc0125580c96724a09226cfbc97f2">psa_mac_sign_finish()</a>, in bytes.</p>
+<p>This is also the MAC size that <a class="el" href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">psa_mac_verify_finish()</a> expects.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">key_type</td><td>The type of the MAC key. </td></tr>
+ <tr><td class="paramname">key_bits</td><td>The size of the MAC key in bits. </td></tr>
+ <tr><td class="paramname">alg</td><td>A MAC algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gaca7aee4c9dde316b3b1a150a26eab776">PSA_ALG_IS_MAC(alg)</a> is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The MAC size for the specified algorithm with the specified key parameters. </dd>
+<dd>
+0 if the MAC algorithm is not recognized. </dd>
+<dd>
+Either 0 or the correct size for a MAC algorithm that the implementation recognizes, but does not support. </dd>
+<dd>
+Unspecified if the key parameters are not consistent with the algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="a4681cc4f6226883a2160122c562ca682"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a4681cc4f6226883a2160122c562ca682">◆ </a></span>PSA_MAC_MAX_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_MAC_MAX_SIZE   <a class="el" href="crypto__sizes_8h.html#a6ce1014efbbc0bcca286ef7f9a72cb29">PSA_HASH_MAX_SIZE</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Maximum size of a MAC.</p>
+<p>This macro must expand to a compile-time constant integer. This value should be the maximum size of a MAC supported by the implementation, in bytes, and must be no smaller than this maximum. </p>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/crypto__sizes_8h__dep__incl.map b/docs/html/crypto__sizes_8h__dep__incl.map
new file mode 100644
index 0000000..549dc4c
--- /dev/null
+++ b/docs/html/crypto__sizes_8h__dep__incl.map
@@ -0,0 +1,3 @@
+<map id="psa/crypto_sizes.h" name="psa/crypto_sizes.h">
+<area shape="rect" id="node2" href="$crypto_8h.html" title="Platform Security Architecture cryptography module. " alt="" coords="24,80,119,107"/>
+</map>
diff --git a/docs/html/crypto__sizes_8h__dep__incl.md5 b/docs/html/crypto__sizes_8h__dep__incl.md5
new file mode 100644
index 0000000..dffb86f
--- /dev/null
+++ b/docs/html/crypto__sizes_8h__dep__incl.md5
@@ -0,0 +1 @@
+f9551c4c11392baf7460101f66a22afe
\ No newline at end of file
diff --git a/docs/html/crypto__sizes_8h__dep__incl.png b/docs/html/crypto__sizes_8h__dep__incl.png
new file mode 100644
index 0000000..ce52e5b
--- /dev/null
+++ b/docs/html/crypto__sizes_8h__dep__incl.png
Binary files differ
diff --git a/docs/html/crypto__sizes_8h__incl.map b/docs/html/crypto__sizes_8h__incl.map
new file mode 100644
index 0000000..8e2ba95
--- /dev/null
+++ b/docs/html/crypto__sizes_8h__incl.map
@@ -0,0 +1,2 @@
+<map id="psa/crypto_sizes.h" name="psa/crypto_sizes.h">
+</map>
diff --git a/docs/html/crypto__sizes_8h__incl.md5 b/docs/html/crypto__sizes_8h__incl.md5
new file mode 100644
index 0000000..649e679
--- /dev/null
+++ b/docs/html/crypto__sizes_8h__incl.md5
@@ -0,0 +1 @@
+e99fd9ff67cdaedc935f8d8f57bb92bb
\ No newline at end of file
diff --git a/docs/html/crypto__sizes_8h__incl.png b/docs/html/crypto__sizes_8h__incl.png
new file mode 100644
index 0000000..2b0c46a
--- /dev/null
+++ b/docs/html/crypto__sizes_8h__incl.png
Binary files differ
diff --git a/docs/html/crypto__sizes_8h_source.html b/docs/html/crypto__sizes_8h_source.html
new file mode 100644
index 0000000..2d725bb
--- /dev/null
+++ b/docs/html/crypto__sizes_8h_source.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: psa/crypto_sizes.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_7dae9cfde651cd3cb034485ce5e391b9.html">psa</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">crypto_sizes.h</div> </div>
+</div><!--header-->
+<div class="contents">
+<a href="crypto__sizes_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span> </div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span> <span class="comment">/*</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span> <span class="comment"> * Copyright (C) 2018, ARM Limited, All Rights Reserved</span></div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span> <span class="comment"> * SPDX-License-Identifier: Apache-2.0</span></div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span> <span class="comment"> *</span></div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span> <span class="comment"> * Licensed under the Apache License, Version 2.0 (the "License"); you may</span></div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span> <span class="comment"> * not use this file except in compliance with the License.</span></div><div class="line"><a name="l00029"></a><span class="lineno"> 29</span> <span class="comment"> * You may obtain a copy of the License at</span></div><div class="line"><a name="l00030"></a><span class="lineno"> 30</span> <span class="comment"> *</span></div><div class="line"><a name="l00031"></a><span class="lineno"> 31</span> <span class="comment"> * http://www.apache.org/licenses/LICENSE-2.0</span></div><div class="line"><a name="l00032"></a><span class="lineno"> 32</span> <span class="comment"> *</span></div><div class="line"><a name="l00033"></a><span class="lineno"> 33</span> <span class="comment"> * Unless required by applicable law or agreed to in writing, software</span></div><div class="line"><a name="l00034"></a><span class="lineno"> 34</span> <span class="comment"> * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT</span></div><div class="line"><a name="l00035"></a><span class="lineno"> 35</span> <span class="comment"> * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div><div class="line"><a name="l00036"></a><span class="lineno"> 36</span> <span class="comment"> * See the License for the specific language governing permissions and</span></div><div class="line"><a name="l00037"></a><span class="lineno"> 37</span> <span class="comment"> * limitations under the License.</span></div><div class="line"><a name="l00038"></a><span class="lineno"> 38</span> <span class="comment"> *</span></div><div class="line"><a name="l00039"></a><span class="lineno"> 39</span> <span class="comment"> * This file is part of mbed TLS (https://tls.mbed.org)</span></div><div class="line"><a name="l00040"></a><span class="lineno"> 40</span> <span class="comment"> */</span></div><div class="line"><a name="l00041"></a><span class="lineno"> 41</span> </div><div class="line"><a name="l00042"></a><span class="lineno"> 42</span> <span class="preprocessor">#ifndef PSA_CRYPTO_SIZES_H</span></div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span> <span class="preprocessor">#define PSA_CRYPTO_SIZES_H</span></div><div class="line"><a name="l00044"></a><span class="lineno"> 44</span> </div><div class="line"><a name="l00045"></a><span class="lineno"> 45</span> <span class="comment">/* Include the Mbed TLS configuration file, the way Mbed TLS does it</span></div><div class="line"><a name="l00046"></a><span class="lineno"> 46</span> <span class="comment"> * in each of its header files. */</span></div><div class="line"><a name="l00047"></a><span class="lineno"> 47</span> <span class="preprocessor">#if !defined(MBEDTLS_CONFIG_FILE)</span></div><div class="line"><a name="l00048"></a><span class="lineno"> 48</span> <span class="preprocessor">#include "../mbedtls/config.h"</span></div><div class="line"><a name="l00049"></a><span class="lineno"> 49</span> <span class="preprocessor">#else</span></div><div class="line"><a name="l00050"></a><span class="lineno"> 50</span> <span class="preprocessor">#include MBEDTLS_CONFIG_FILE</span></div><div class="line"><a name="l00051"></a><span class="lineno"> 51</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00052"></a><span class="lineno"> 52</span> </div><div class="line"><a name="l00061"></a><span class="lineno"> 61</span> <span class="preprocessor">#if defined(MBEDTLS_SHA512_C)</span></div><div class="line"><a name="l00062"></a><span class="lineno"><a class="line" href="crypto__sizes_8h.html#a6ce1014efbbc0bcca286ef7f9a72cb29"> 62</a></span> <span class="preprocessor">#define PSA_HASH_MAX_SIZE 64</span></div><div class="line"><a name="l00063"></a><span class="lineno"> 63</span> <span class="preprocessor">#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128</span></div><div class="line"><a name="l00064"></a><span class="lineno"> 64</span> <span class="preprocessor">#else</span></div><div class="line"><a name="l00065"></a><span class="lineno"> 65</span> <span class="preprocessor">#define PSA_HASH_MAX_SIZE 32</span></div><div class="line"><a name="l00066"></a><span class="lineno"> 66</span> <span class="preprocessor">#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64</span></div><div class="line"><a name="l00067"></a><span class="lineno"> 67</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00068"></a><span class="lineno"> 68</span> </div><div class="line"><a name="l00077"></a><span class="lineno"> 77</span> <span class="comment">/* All non-HMAC MACs have a maximum size that's smaller than the</span></div><div class="line"><a name="l00078"></a><span class="lineno"> 78</span> <span class="comment"> * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */</span></div><div class="line"><a name="l00079"></a><span class="lineno"><a class="line" href="crypto__sizes_8h.html#a4681cc4f6226883a2160122c562ca682"> 79</a></span> <span class="preprocessor">#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE</span></div><div class="line"><a name="l00080"></a><span class="lineno"> 80</span> </div><div class="line"><a name="l00081"></a><span class="lineno"> 81</span> <span class="comment">/* The maximum size of an RSA key on this implementation, in bits.</span></div><div class="line"><a name="l00082"></a><span class="lineno"> 82</span> <span class="comment"> * This is a vendor-specific macro.</span></div><div class="line"><a name="l00083"></a><span class="lineno"> 83</span> <span class="comment"> *</span></div><div class="line"><a name="l00084"></a><span class="lineno"> 84</span> <span class="comment"> * Mbed TLS does not set a hard limit on the size of RSA keys: any key</span></div><div class="line"><a name="l00085"></a><span class="lineno"> 85</span> <span class="comment"> * whose parameters fit in a bignum is accepted. However large keys can</span></div><div class="line"><a name="l00086"></a><span class="lineno"> 86</span> <span class="comment"> * induce a large memory usage and long computation times. Unlike other</span></div><div class="line"><a name="l00087"></a><span class="lineno"> 87</span> <span class="comment"> * auxiliary macros in this file and in crypto.h, which reflect how the</span></div><div class="line"><a name="l00088"></a><span class="lineno"> 88</span> <span class="comment"> * library is configured, this macro defines how the library is</span></div><div class="line"><a name="l00089"></a><span class="lineno"> 89</span> <span class="comment"> * configured. This implementation refuses to import or generate an</span></div><div class="line"><a name="l00090"></a><span class="lineno"> 90</span> <span class="comment"> * RSA key whose size is larger than the value defined here.</span></div><div class="line"><a name="l00091"></a><span class="lineno"> 91</span> <span class="comment"> *</span></div><div class="line"><a name="l00092"></a><span class="lineno"> 92</span> <span class="comment"> * Note that an implementation may set different size limits for different</span></div><div class="line"><a name="l00093"></a><span class="lineno"> 93</span> <span class="comment"> * operations, and does not need to accept all key sizes up to the limit. */</span></div><div class="line"><a name="l00094"></a><span class="lineno"> 94</span> <span class="preprocessor">#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096</span></div><div class="line"><a name="l00095"></a><span class="lineno"> 95</span> </div><div class="line"><a name="l00096"></a><span class="lineno"> 96</span> <span class="comment">/* The maximum size of an ECC key on this implementation, in bits.</span></div><div class="line"><a name="l00097"></a><span class="lineno"> 97</span> <span class="comment"> * This is a vendor-specific macro. */</span></div><div class="line"><a name="l00098"></a><span class="lineno"> 98</span> <span class="preprocessor">#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)</span></div><div class="line"><a name="l00099"></a><span class="lineno"> 99</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521</span></div><div class="line"><a name="l00100"></a><span class="lineno"> 100</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)</span></div><div class="line"><a name="l00101"></a><span class="lineno"> 101</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512</span></div><div class="line"><a name="l00102"></a><span class="lineno"> 102</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)</span></div><div class="line"><a name="l00103"></a><span class="lineno"> 103</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448</span></div><div class="line"><a name="l00104"></a><span class="lineno"> 104</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)</span></div><div class="line"><a name="l00105"></a><span class="lineno"> 105</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384</span></div><div class="line"><a name="l00106"></a><span class="lineno"> 106</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)</span></div><div class="line"><a name="l00107"></a><span class="lineno"> 107</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384</span></div><div class="line"><a name="l00108"></a><span class="lineno"> 108</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)</span></div><div class="line"><a name="l00109"></a><span class="lineno"> 109</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256</span></div><div class="line"><a name="l00110"></a><span class="lineno"> 110</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)</span></div><div class="line"><a name="l00111"></a><span class="lineno"> 111</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256</span></div><div class="line"><a name="l00112"></a><span class="lineno"> 112</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)</span></div><div class="line"><a name="l00113"></a><span class="lineno"> 113</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256</span></div><div class="line"><a name="l00114"></a><span class="lineno"> 114</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)</span></div><div class="line"><a name="l00115"></a><span class="lineno"> 115</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255</span></div><div class="line"><a name="l00116"></a><span class="lineno"> 116</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)</span></div><div class="line"><a name="l00117"></a><span class="lineno"> 117</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224</span></div><div class="line"><a name="l00118"></a><span class="lineno"> 118</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)</span></div><div class="line"><a name="l00119"></a><span class="lineno"> 119</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224</span></div><div class="line"><a name="l00120"></a><span class="lineno"> 120</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)</span></div><div class="line"><a name="l00121"></a><span class="lineno"> 121</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192</span></div><div class="line"><a name="l00122"></a><span class="lineno"> 122</span> <span class="preprocessor">#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)</span></div><div class="line"><a name="l00123"></a><span class="lineno"> 123</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192</span></div><div class="line"><a name="l00124"></a><span class="lineno"> 124</span> <span class="preprocessor">#else</span></div><div class="line"><a name="l00125"></a><span class="lineno"> 125</span> <span class="preprocessor">#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0</span></div><div class="line"><a name="l00126"></a><span class="lineno"> 126</span> <span class="preprocessor">#endif</span></div><div class="line"><a name="l00127"></a><span class="lineno"> 127</span> </div><div class="line"><a name="l00136"></a><span class="lineno"><a class="line" href="crypto__sizes_8h.html#ad755101764dba14589e5919ee41be7ca"> 136</a></span> <span class="preprocessor">#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \</span></div><div class="line"><a name="l00137"></a><span class="lineno"> 137</span> <span class="preprocessor"> PSA_BITS_TO_BYTES( \</span></div><div class="line"><a name="l00138"></a><span class="lineno"> 138</span> <span class="preprocessor"> PSA_VENDOR_RSA_MAX_KEY_BITS > PSA_VENDOR_ECC_MAX_CURVE_BITS ? \</span></div><div class="line"><a name="l00139"></a><span class="lineno"> 139</span> <span class="preprocessor"> PSA_VENDOR_RSA_MAX_KEY_BITS : \</span></div><div class="line"><a name="l00140"></a><span class="lineno"> 140</span> <span class="preprocessor"> PSA_VENDOR_ECC_MAX_CURVE_BITS \</span></div><div class="line"><a name="l00141"></a><span class="lineno"> 141</span> <span class="preprocessor"> )</span></div><div class="line"><a name="l00142"></a><span class="lineno"> 142</span> </div><div class="line"><a name="l00143"></a><span class="lineno"> 143</span> </div><div class="line"><a name="l00144"></a><span class="lineno"> 144</span> </div><div class="line"><a name="l00162"></a><span class="lineno"><a class="line" href="crypto__sizes_8h.html#aa84c5fb384ac7cb1bfc52adde96588ee"> 162</a></span> <span class="preprocessor">#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \</span></div><div class="line"><a name="l00163"></a><span class="lineno"> 163</span> <span class="preprocessor"> (PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_HASH(alg)) : \</span></div><div class="line"><a name="l00164"></a><span class="lineno"> 164</span> <span class="preprocessor"> PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \</span></div><div class="line"><a name="l00165"></a><span class="lineno"> 165</span> <span class="preprocessor"> 0)</span></div><div class="line"><a name="l00166"></a><span class="lineno"> 166</span> </div><div class="line"><a name="l00186"></a><span class="lineno"><a class="line" href="crypto__sizes_8h.html#a85667d47a7aa6c7b99a80e5273671266"> 186</a></span> <span class="preprocessor">#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \</span></div><div class="line"><a name="l00187"></a><span class="lineno"> 187</span> <span class="preprocessor"> (PSA_AEAD_TAG_SIZE(alg) != 0 ? \</span></div><div class="line"><a name="l00188"></a><span class="lineno"> 188</span> <span class="preprocessor"> (plaintext_length) + PSA_AEAD_TAG_SIZE(alg) : \</span></div><div class="line"><a name="l00189"></a><span class="lineno"> 189</span> <span class="preprocessor"> 0)</span></div><div class="line"><a name="l00190"></a><span class="lineno"> 190</span> </div><div class="line"><a name="l00210"></a><span class="lineno"><a class="line" href="crypto__sizes_8h.html#a1d057796166c16eb673ad1997e48a60b"> 210</a></span> <span class="preprocessor">#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \</span></div><div class="line"><a name="l00211"></a><span class="lineno"> 211</span> <span class="preprocessor"> (PSA_AEAD_TAG_SIZE(alg) != 0 ? \</span></div><div class="line"><a name="l00212"></a><span class="lineno"> 212</span> <span class="preprocessor"> (plaintext_length) - PSA_AEAD_TAG_SIZE(alg) : \</span></div><div class="line"><a name="l00213"></a><span class="lineno"> 213</span> <span class="preprocessor"> 0)</span></div><div class="line"><a name="l00214"></a><span class="lineno"> 214</span> </div><div class="line"><a name="l00241"></a><span class="lineno"><a class="line" href="crypto__sizes_8h.html#a77565b9b4fe6d8730fd2120f4c8378ab"> 241</a></span> <span class="preprocessor">#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \</span></div><div class="line"><a name="l00242"></a><span class="lineno"> 242</span> <span class="preprocessor"> (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \</span></div><div class="line"><a name="l00243"></a><span class="lineno"> 243</span> <span class="preprocessor"> PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \</span></div><div class="line"><a name="l00244"></a><span class="lineno"> 244</span> <span class="preprocessor"> ((void)alg, 0))</span></div><div class="line"><a name="l00245"></a><span class="lineno"> 245</span> </div><div class="line"><a name="l00272"></a><span class="lineno"><a class="line" href="crypto__sizes_8h.html#a66ba3bd93e5ec52870ccc3848778bad8"> 272</a></span> <span class="preprocessor">#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \</span></div><div class="line"><a name="l00273"></a><span class="lineno"> 273</span> <span class="preprocessor"> (PSA_KEY_TYPE_IS_RSA(key_type) ? \</span></div><div class="line"><a name="l00274"></a><span class="lineno"> 274</span> <span class="preprocessor"> ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \</span></div><div class="line"><a name="l00275"></a><span class="lineno"> 275</span> <span class="preprocessor"> 0)</span></div><div class="line"><a name="l00276"></a><span class="lineno"> 276</span> </div><div class="line"><a name="l00303"></a><span class="lineno"><a class="line" href="crypto__sizes_8h.html#a61a246f3eac41989821d982e56fea6c1"> 303</a></span> <span class="preprocessor">#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \</span></div><div class="line"><a name="l00304"></a><span class="lineno"> 304</span> <span class="preprocessor"> (PSA_KEY_TYPE_IS_RSA(key_type) ? \</span></div><div class="line"><a name="l00305"></a><span class="lineno"> 305</span> <span class="preprocessor"> PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \</span></div><div class="line"><a name="l00306"></a><span class="lineno"> 306</span> <span class="preprocessor"> 0)</span></div><div class="line"><a name="l00307"></a><span class="lineno"> 307</span> </div><div class="line"><a name="l00308"></a><span class="lineno"> 308</span> <span class="preprocessor">#endif </span><span class="comment">/* PSA_CRYPTO_SIZES_H */</span><span class="preprocessor"></span></div></div><!-- fragment --></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/dir_7dae9cfde651cd3cb034485ce5e391b9.html b/docs/html/dir_7dae9cfde651cd3cb034485ce5e391b9.html
new file mode 100644
index 0000000..1b9a053
--- /dev/null
+++ b/docs/html/dir_7dae9cfde651cd3cb034485ce5e391b9.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: psa Directory Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+ <ul>
+<li class="navelem"><a class="el" href="dir_7dae9cfde651cd3cb034485ce5e391b9.html">psa</a></li> </ul>
+</div>
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">psa Directory Reference</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="files"></a>
+Files</h2></td></tr>
+<tr class="memitem:crypto_8h"><td class="memItemLeft" align="right" valign="top">file  </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto_8h.html">crypto.h</a> <a href="crypto_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:crypto_8h"><td class="mdescLeft"> </td><td class="mdescRight">Platform Security Architecture cryptography module. <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:crypto__sizes_8h"><td class="memItemLeft" align="right" valign="top">file  </td><td class="memItemRight" valign="bottom"><a class="el" href="crypto__sizes_8h.html">crypto_sizes.h</a> <a href="crypto__sizes_8h_source.html">[code]</a></td></tr>
+<tr class="memdesc:crypto__sizes_8h"><td class="mdescLeft"> </td><td class="mdescRight">PSA cryptography module: Mbed TLS buffer size macros. <br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/doc.png b/docs/html/doc.png
new file mode 100644
index 0000000..17edabf
--- /dev/null
+++ b/docs/html/doc.png
Binary files differ
diff --git a/docs/html/doxygen.css b/docs/html/doxygen.css
new file mode 100644
index 0000000..4f1ab91
--- /dev/null
+++ b/docs/html/doxygen.css
@@ -0,0 +1,1596 @@
+/* The standard CSS for doxygen 1.8.13 */
+
+body, table, div, p, dl {
+ font: 400 14px/22px Roboto,sans-serif;
+}
+
+p.reference, p.definition {
+ font: 400 14px/22px Roboto,sans-serif;
+}
+
+/* @group Heading Levels */
+
+h1.groupheader {
+ font-size: 150%;
+}
+
+.title {
+ font: 400 14px/28px Roboto,sans-serif;
+ font-size: 150%;
+ font-weight: bold;
+ margin: 10px 2px;
+}
+
+h2.groupheader {
+ border-bottom: 1px solid #879ECB;
+ color: #354C7B;
+ font-size: 150%;
+ font-weight: normal;
+ margin-top: 1.75em;
+ padding-top: 8px;
+ padding-bottom: 4px;
+ width: 100%;
+}
+
+h3.groupheader {
+ font-size: 100%;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ -webkit-transition: text-shadow 0.5s linear;
+ -moz-transition: text-shadow 0.5s linear;
+ -ms-transition: text-shadow 0.5s linear;
+ -o-transition: text-shadow 0.5s linear;
+ transition: text-shadow 0.5s linear;
+ margin-right: 15px;
+}
+
+h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
+ text-shadow: 0 0 15px cyan;
+}
+
+dt {
+ font-weight: bold;
+}
+
+div.multicol {
+ -moz-column-gap: 1em;
+ -webkit-column-gap: 1em;
+ -moz-column-count: 3;
+ -webkit-column-count: 3;
+}
+
+p.startli, p.startdd {
+ margin-top: 2px;
+}
+
+p.starttd {
+ margin-top: 0px;
+}
+
+p.endli {
+ margin-bottom: 0px;
+}
+
+p.enddd {
+ margin-bottom: 4px;
+}
+
+p.endtd {
+ margin-bottom: 2px;
+}
+
+/* @end */
+
+caption {
+ font-weight: bold;
+}
+
+span.legend {
+ font-size: 70%;
+ text-align: center;
+}
+
+h3.version {
+ font-size: 90%;
+ text-align: center;
+}
+
+div.qindex, div.navtab{
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
+ text-align: center;
+}
+
+div.qindex, div.navpath {
+ width: 100%;
+ line-height: 140%;
+}
+
+div.navtab {
+ margin-right: 15px;
+}
+
+/* @group Link Styling */
+
+a {
+ color: #3D578C;
+ font-weight: normal;
+ text-decoration: none;
+}
+
+.contents a:visited {
+ color: #4665A2;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+a.qindex {
+ font-weight: bold;
+}
+
+a.qindexHL {
+ font-weight: bold;
+ background-color: #9CAFD4;
+ color: #ffffff;
+ border: 1px double #869DCA;
+}
+
+.contents a.qindexHL:visited {
+ color: #ffffff;
+}
+
+a.el {
+ font-weight: bold;
+}
+
+a.elRef {
+}
+
+a.code, a.code:visited, a.line, a.line:visited {
+ color: #4665A2;
+}
+
+a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
+ color: #4665A2;
+}
+
+/* @end */
+
+dl.el {
+ margin-left: -1cm;
+}
+
+pre.fragment {
+ border: 1px solid #C4CFE5;
+ background-color: #FBFCFD;
+ padding: 4px 6px;
+ margin: 4px 8px 4px 2px;
+ overflow: auto;
+ word-wrap: break-word;
+ font-size: 9pt;
+ line-height: 125%;
+ font-family: monospace, fixed;
+ font-size: 105%;
+}
+
+div.fragment {
+ padding: 0px;
+ margin: 4px 8px 4px 2px;
+ background-color: #FBFCFD;
+ border: 1px solid #C4CFE5;
+}
+
+div.line {
+ font-family: monospace, fixed;
+ font-size: 13px;
+ min-height: 13px;
+ line-height: 1.0;
+ text-wrap: unrestricted;
+ white-space: -moz-pre-wrap; /* Moz */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ white-space: pre-wrap; /* CSS3 */
+ word-wrap: break-word; /* IE 5.5+ */
+ text-indent: -53px;
+ padding-left: 53px;
+ padding-bottom: 0px;
+ margin: 0px;
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+div.line:after {
+ content:"\000A";
+ white-space: pre;
+}
+
+div.line.glow {
+ background-color: cyan;
+ box-shadow: 0 0 10px cyan;
+}
+
+
+span.lineno {
+ padding-right: 4px;
+ text-align: right;
+ border-right: 2px solid #0F0;
+ background-color: #E8E8E8;
+ white-space: pre;
+}
+span.lineno a {
+ background-color: #D8D8D8;
+}
+
+span.lineno a:hover {
+ background-color: #C8C8C8;
+}
+
+.lineno {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+div.ah, span.ah {
+ background-color: black;
+ font-weight: bold;
+ color: #ffffff;
+ margin-bottom: 3px;
+ margin-top: 3px;
+ padding: 0.2em;
+ border: solid thin #333;
+ border-radius: 0.5em;
+ -webkit-border-radius: .5em;
+ -moz-border-radius: .5em;
+ box-shadow: 2px 2px 3px #999;
+ -webkit-box-shadow: 2px 2px 3px #999;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
+ background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%);
+}
+
+div.classindex ul {
+ list-style: none;
+ padding-left: 0;
+}
+
+div.classindex span.ai {
+ display: inline-block;
+}
+
+div.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ font-weight: bold;
+}
+
+div.groupText {
+ margin-left: 16px;
+ font-style: italic;
+}
+
+body {
+ background-color: white;
+ color: black;
+ margin: 0;
+}
+
+div.contents {
+ margin-top: 10px;
+ margin-left: 12px;
+ margin-right: 8px;
+}
+
+td.indexkey {
+ background-color: #EBEFF6;
+ font-weight: bold;
+ border: 1px solid #C4CFE5;
+ margin: 2px 0px 2px 0;
+ padding: 2px 10px;
+ white-space: nowrap;
+ vertical-align: top;
+}
+
+td.indexvalue {
+ background-color: #EBEFF6;
+ border: 1px solid #C4CFE5;
+ padding: 2px 10px;
+ margin: 2px 0px;
+}
+
+tr.memlist {
+ background-color: #EEF1F7;
+}
+
+p.formulaDsp {
+ text-align: center;
+}
+
+img.formulaDsp {
+
+}
+
+img.formulaInl {
+ vertical-align: middle;
+}
+
+div.center {
+ text-align: center;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+}
+
+div.center img {
+ border: 0px;
+}
+
+address.footer {
+ text-align: right;
+ padding-right: 12px;
+}
+
+img.footer {
+ border: 0px;
+ vertical-align: middle;
+}
+
+/* @group Code Colorization */
+
+span.keyword {
+ color: #008000
+}
+
+span.keywordtype {
+ color: #604020
+}
+
+span.keywordflow {
+ color: #e08000
+}
+
+span.comment {
+ color: #800000
+}
+
+span.preprocessor {
+ color: #806020
+}
+
+span.stringliteral {
+ color: #002080
+}
+
+span.charliteral {
+ color: #008080
+}
+
+span.vhdldigit {
+ color: #ff00ff
+}
+
+span.vhdlchar {
+ color: #000000
+}
+
+span.vhdlkeyword {
+ color: #700070
+}
+
+span.vhdllogic {
+ color: #ff0000
+}
+
+blockquote {
+ background-color: #F7F8FB;
+ border-left: 2px solid #9CAFD4;
+ margin: 0 24px 0 4px;
+ padding: 0 12px 0 16px;
+}
+
+/* @end */
+
+/*
+.search {
+ color: #003399;
+ font-weight: bold;
+}
+
+form.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+
+input.search {
+ font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+*/
+
+td.tiny {
+ font-size: 75%;
+}
+
+.dirtab {
+ padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #A3B4D7;
+}
+
+th.dirtab {
+ background: #EBEFF6;
+ font-weight: bold;
+}
+
+hr {
+ height: 0px;
+ border: none;
+ border-top: 1px solid #4A6AAA;
+}
+
+hr.footer {
+ height: 1px;
+}
+
+/* @group Member Descriptions */
+
+table.memberdecls {
+ border-spacing: 0px;
+ padding: 0px;
+}
+
+.memberdecls td, .fieldtable tr {
+ -webkit-transition-property: background-color, box-shadow;
+ -webkit-transition-duration: 0.5s;
+ -moz-transition-property: background-color, box-shadow;
+ -moz-transition-duration: 0.5s;
+ -ms-transition-property: background-color, box-shadow;
+ -ms-transition-duration: 0.5s;
+ -o-transition-property: background-color, box-shadow;
+ -o-transition-duration: 0.5s;
+ transition-property: background-color, box-shadow;
+ transition-duration: 0.5s;
+}
+
+.memberdecls td.glow, .fieldtable tr.glow {
+ background-color: cyan;
+ box-shadow: 0 0 15px cyan;
+}
+
+.mdescLeft, .mdescRight,
+.memItemLeft, .memItemRight,
+.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
+ background-color: #F9FAFC;
+ border: none;
+ margin: 4px;
+ padding: 1px 0 0 8px;
+}
+
+.mdescLeft, .mdescRight {
+ padding: 0px 8px 4px 8px;
+ color: #555;
+}
+
+.memSeparator {
+ border-bottom: 1px solid #DEE4F0;
+ line-height: 1px;
+ margin: 0px;
+ padding: 0px;
+}
+
+.memItemLeft, .memTemplItemLeft {
+ white-space: nowrap;
+}
+
+.memItemRight {
+ width: 100%;
+}
+
+.memTemplParams {
+ color: #4665A2;
+ white-space: nowrap;
+ font-size: 80%;
+}
+
+/* @end */
+
+/* @group Member Details */
+
+/* Styles for detailed member documentation */
+
+.memtitle {
+ padding: 8px;
+ border-top: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ margin-bottom: -1px;
+ background-image: url('nav_f.png');
+ background-repeat: repeat-x;
+ background-color: #E2E8F2;
+ line-height: 1.25;
+ font-weight: 300;
+ float:left;
+}
+
+.permalink
+{
+ font-size: 65%;
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.memtemplate {
+ font-size: 80%;
+ color: #4665A2;
+ font-weight: normal;
+ margin-left: 9px;
+}
+
+.memnav {
+ background-color: #EBEFF6;
+ border: 1px solid #A3B4D7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+
+.mempage {
+ width: 100%;
+}
+
+.memitem {
+ padding: 0;
+ margin-bottom: 10px;
+ margin-right: 5px;
+ -webkit-transition: box-shadow 0.5s linear;
+ -moz-transition: box-shadow 0.5s linear;
+ -ms-transition: box-shadow 0.5s linear;
+ -o-transition: box-shadow 0.5s linear;
+ transition: box-shadow 0.5s linear;
+ display: table !important;
+ width: 100%;
+}
+
+.memitem.glow {
+ box-shadow: 0 0 15px cyan;
+}
+
+.memname {
+ font-weight: 400;
+ margin-left: 6px;
+}
+
+.memname td {
+ vertical-align: bottom;
+}
+
+.memproto, dl.reflist dt {
+ border-top: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 0px 6px 0px;
+ color: #253555;
+ font-weight: bold;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ background-color: #DFE5F1;
+ /* opera specific markup */
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ border-top-right-radius: 4px;
+ /* firefox specific markup */
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ -moz-border-radius-topright: 4px;
+ /* webkit specific markup */
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ -webkit-border-top-right-radius: 4px;
+
+}
+
+.overload {
+ font-family: "courier new",courier,monospace;
+ font-size: 65%;
+}
+
+.memdoc, dl.reflist dd {
+ border-bottom: 1px solid #A8B8D9;
+ border-left: 1px solid #A8B8D9;
+ border-right: 1px solid #A8B8D9;
+ padding: 6px 10px 2px 10px;
+ background-color: #FBFCFD;
+ border-top-width: 0;
+ background-image:url('nav_g.png');
+ background-repeat:repeat-x;
+ background-color: #FFFFFF;
+ /* opera specific markup */
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+ /* firefox specific markup */
+ -moz-border-radius-bottomleft: 4px;
+ -moz-border-radius-bottomright: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+ /* webkit specific markup */
+ -webkit-border-bottom-left-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+dl.reflist dt {
+ padding: 5px;
+}
+
+dl.reflist dd {
+ margin: 0px 0px 10px 0px;
+ padding: 5px;
+}
+
+.paramkey {
+ text-align: right;
+}
+
+.paramtype {
+ white-space: nowrap;
+}
+
+.paramname {
+ color: #602020;
+ white-space: nowrap;
+}
+.paramname em {
+ font-style: normal;
+}
+.paramname code {
+ line-height: 14px;
+}
+
+.params, .retval, .exception, .tparams {
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+.params .paramname, .retval .paramname {
+ font-weight: bold;
+ vertical-align: top;
+}
+
+.params .paramtype {
+ font-style: italic;
+ vertical-align: top;
+}
+
+.params .paramdir {
+ font-family: "courier new",courier,monospace;
+ vertical-align: top;
+}
+
+table.mlabels {
+ border-spacing: 0px;
+}
+
+td.mlabels-left {
+ width: 100%;
+ padding: 0px;
+}
+
+td.mlabels-right {
+ vertical-align: bottom;
+ padding: 0px;
+ white-space: nowrap;
+}
+
+span.mlabels {
+ margin-left: 8px;
+}
+
+span.mlabel {
+ background-color: #728DC1;
+ border-top:1px solid #5373B4;
+ border-left:1px solid #5373B4;
+ border-right:1px solid #C4CFE5;
+ border-bottom:1px solid #C4CFE5;
+ text-shadow: none;
+ color: white;
+ margin-right: 4px;
+ padding: 2px 3px;
+ border-radius: 3px;
+ font-size: 7pt;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+
+
+/* @end */
+
+/* these are for tree view inside a (index) page */
+
+div.directory {
+ margin: 10px 0px;
+ border-top: 1px solid #9CAFD4;
+ border-bottom: 1px solid #9CAFD4;
+ width: 100%;
+}
+
+.directory table {
+ border-collapse:collapse;
+}
+
+.directory td {
+ margin: 0px;
+ padding: 0px;
+ vertical-align: top;
+}
+
+.directory td.entry {
+ white-space: nowrap;
+ padding-right: 6px;
+ padding-top: 3px;
+}
+
+.directory td.entry a {
+ outline:none;
+}
+
+.directory td.entry a img {
+ border: none;
+}
+
+.directory td.desc {
+ width: 100%;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 3px;
+ border-left: 1px solid rgba(0,0,0,0.05);
+}
+
+.directory tr.even {
+ padding-left: 6px;
+ background-color: #F7F8FB;
+}
+
+.directory img {
+ vertical-align: -30%;
+}
+
+.directory .levels {
+ white-space: nowrap;
+ width: 100%;
+ text-align: right;
+ font-size: 9pt;
+}
+
+.directory .levels span {
+ cursor: pointer;
+ padding-left: 2px;
+ padding-right: 2px;
+ color: #3D578C;
+}
+
+.arrow {
+ color: #9CAFD4;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ cursor: pointer;
+ font-size: 80%;
+ display: inline-block;
+ width: 16px;
+ height: 22px;
+}
+
+.icon {
+ font-family: Arial, Helvetica;
+ font-weight: bold;
+ font-size: 12px;
+ height: 14px;
+ width: 16px;
+ display: inline-block;
+ background-color: #728DC1;
+ color: white;
+ text-align: center;
+ border-radius: 4px;
+ margin-left: 2px;
+ margin-right: 2px;
+}
+
+.icona {
+ width: 24px;
+ height: 22px;
+ display: inline-block;
+}
+
+.iconfopen {
+ width: 24px;
+ height: 18px;
+ margin-bottom: 4px;
+ background-image:url('folderopen.png');
+ background-position: 0px -4px;
+ background-repeat: repeat-y;
+ vertical-align:top;
+ display: inline-block;
+}
+
+.iconfclosed {
+ width: 24px;
+ height: 18px;
+ margin-bottom: 4px;
+ background-image:url('folderclosed.png');
+ background-position: 0px -4px;
+ background-repeat: repeat-y;
+ vertical-align:top;
+ display: inline-block;
+}
+
+.icondoc {
+ width: 24px;
+ height: 18px;
+ margin-bottom: 4px;
+ background-image:url('doc.png');
+ background-position: 0px -4px;
+ background-repeat: repeat-y;
+ vertical-align:top;
+ display: inline-block;
+}
+
+table.directory {
+ font: 400 14px Roboto,sans-serif;
+}
+
+/* @end */
+
+div.dynheader {
+ margin-top: 8px;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+address {
+ font-style: normal;
+ color: #2A3D61;
+}
+
+table.doxtable caption {
+ caption-side: top;
+}
+
+table.doxtable {
+ border-collapse:collapse;
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+table.doxtable td, table.doxtable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+table.doxtable th {
+ background-color: #374F7F;
+ color: #FFFFFF;
+ font-size: 110%;
+ padding-bottom: 4px;
+ padding-top: 5px;
+}
+
+table.fieldtable {
+ /*width: 100%;*/
+ margin-bottom: 10px;
+ border: 1px solid #A8B8D9;
+ border-spacing: 0px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+ -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+ box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+}
+
+.fieldtable td, .fieldtable th {
+ padding: 3px 7px 2px;
+}
+
+.fieldtable td.fieldtype, .fieldtable td.fieldname {
+ white-space: nowrap;
+ border-right: 1px solid #A8B8D9;
+ border-bottom: 1px solid #A8B8D9;
+ vertical-align: top;
+}
+
+.fieldtable td.fieldname {
+ padding-top: 3px;
+}
+
+.fieldtable td.fielddoc {
+ border-bottom: 1px solid #A8B8D9;
+ /*width: 100%;*/
+}
+
+.fieldtable td.fielddoc p:first-child {
+ margin-top: 0px;
+}
+
+.fieldtable td.fielddoc p:last-child {
+ margin-bottom: 2px;
+}
+
+.fieldtable tr:last-child td {
+ border-bottom: none;
+}
+
+.fieldtable th {
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ background-color: #E2E8F2;
+ font-size: 90%;
+ color: #253555;
+ padding-bottom: 4px;
+ padding-top: 5px;
+ text-align:left;
+ font-weight: 400;
+ -moz-border-radius-topleft: 4px;
+ -moz-border-radius-topright: 4px;
+ -webkit-border-top-left-radius: 4px;
+ -webkit-border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ border-bottom: 1px solid #A8B8D9;
+}
+
+
+.tabsearch {
+ top: 0px;
+ left: 10px;
+ height: 36px;
+ background-image: url('tab_b.png');
+ z-index: 101;
+ overflow: hidden;
+ font-size: 13px;
+}
+
+.navpath ul
+{
+ font-size: 11px;
+ background-image:url('tab_b.png');
+ background-repeat:repeat-x;
+ background-position: 0 -5px;
+ height:30px;
+ line-height:30px;
+ color:#8AA0CC;
+ border:solid 1px #C2CDE4;
+ overflow:hidden;
+ margin:0px;
+ padding:0px;
+}
+
+.navpath li
+{
+ list-style-type:none;
+ float:left;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:url('bc_s.png');
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+}
+
+.navpath li.navelem a
+{
+ height:32px;
+ display:block;
+ text-decoration: none;
+ outline: none;
+ color: #283A5D;
+ font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
+ text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+ text-decoration: none;
+}
+
+.navpath li.navelem a:hover
+{
+ color:#6884BD;
+}
+
+.navpath li.footer
+{
+ list-style-type:none;
+ float:right;
+ padding-left:10px;
+ padding-right:15px;
+ background-image:none;
+ background-repeat:no-repeat;
+ background-position:right;
+ color:#364D7C;
+ font-size: 8pt;
+}
+
+
+div.summary
+{
+ float: right;
+ font-size: 8pt;
+ padding-right: 5px;
+ width: 50%;
+ text-align: right;
+}
+
+div.summary a
+{
+ white-space: nowrap;
+}
+
+table.classindex
+{
+ margin: 10px;
+ white-space: nowrap;
+ margin-left: 3%;
+ margin-right: 3%;
+ width: 94%;
+ border: 0;
+ border-spacing: 0;
+ padding: 0;
+}
+
+div.ingroups
+{
+ font-size: 8pt;
+ width: 50%;
+ text-align: left;
+}
+
+div.ingroups a
+{
+ white-space: nowrap;
+}
+
+div.header
+{
+ background-image:url('nav_h.png');
+ background-repeat:repeat-x;
+ background-color: #F9FAFC;
+ margin: 0px;
+ border-bottom: 1px solid #C4CFE5;
+}
+
+div.headertitle
+{
+ padding: 5px 5px 5px 10px;
+}
+
+dl
+{
+ padding: 0 0 0 10px;
+}
+
+/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */
+dl.section
+{
+ margin-left: 0px;
+ padding-left: 0px;
+}
+
+dl.note
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #D0C000;
+}
+
+dl.warning, dl.attention
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #FF0000;
+}
+
+dl.pre, dl.post, dl.invariant
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00D000;
+}
+
+dl.deprecated
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #505050;
+}
+
+dl.todo
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #00C0E0;
+}
+
+dl.test
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #3030E0;
+}
+
+dl.bug
+{
+ margin-left:-7px;
+ padding-left: 3px;
+ border-left:4px solid;
+ border-color: #C08050;
+}
+
+dl.section dd {
+ margin-bottom: 6px;
+}
+
+
+#projectlogo
+{
+ text-align: center;
+ vertical-align: bottom;
+ border-collapse: separate;
+}
+
+#projectlogo img
+{
+ border: 0px none;
+}
+
+#projectalign
+{
+ vertical-align: middle;
+}
+
+#projectname
+{
+ font: 300% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 2px 0px;
+}
+
+#projectbrief
+{
+ font: 120% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#projectnumber
+{
+ font: 50% Tahoma, Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+#titlearea
+{
+ padding: 0px;
+ margin: 0px;
+ width: 100%;
+ border-bottom: 1px solid #5373B4;
+}
+
+.image
+{
+ text-align: center;
+}
+
+.dotgraph
+{
+ text-align: center;
+}
+
+.mscgraph
+{
+ text-align: center;
+}
+
+.plantumlgraph
+{
+ text-align: center;
+}
+
+.diagraph
+{
+ text-align: center;
+}
+
+.caption
+{
+ font-weight: bold;
+}
+
+div.zoom
+{
+ border: 1px solid #90A5CE;
+}
+
+dl.citelist {
+ margin-bottom:50px;
+}
+
+dl.citelist dt {
+ color:#334975;
+ float:left;
+ font-weight:bold;
+ margin-right:10px;
+ padding:5px;
+}
+
+dl.citelist dd {
+ margin:2px 0;
+ padding:5px 0;
+}
+
+div.toc {
+ padding: 14px 25px;
+ background-color: #F4F6FA;
+ border: 1px solid #D8DFEE;
+ border-radius: 7px 7px 7px 7px;
+ float: right;
+ height: auto;
+ margin: 0 8px 10px 10px;
+ width: 200px;
+}
+
+div.toc li {
+ background: url("bdwn.png") no-repeat scroll 0 5px transparent;
+ font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif;
+ margin-top: 5px;
+ padding-left: 10px;
+ padding-top: 2px;
+}
+
+div.toc h3 {
+ font: bold 12px/1.2 Arial,FreeSans,sans-serif;
+ color: #4665A2;
+ border-bottom: 0 none;
+ margin: 0;
+}
+
+div.toc ul {
+ list-style: none outside none;
+ border: medium none;
+ padding: 0px;
+}
+
+div.toc li.level1 {
+ margin-left: 0px;
+}
+
+div.toc li.level2 {
+ margin-left: 15px;
+}
+
+div.toc li.level3 {
+ margin-left: 30px;
+}
+
+div.toc li.level4 {
+ margin-left: 45px;
+}
+
+.inherit_header {
+ font-weight: bold;
+ color: gray;
+ cursor: pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.inherit_header td {
+ padding: 6px 0px 2px 5px;
+}
+
+.inherit {
+ display: none;
+}
+
+tr.heading h2 {
+ margin-top: 12px;
+ margin-bottom: 4px;
+}
+
+/* tooltip related style info */
+
+.ttc {
+ position: absolute;
+ display: none;
+}
+
+#powerTip {
+ cursor: default;
+ white-space: nowrap;
+ background-color: white;
+ border: 1px solid gray;
+ border-radius: 4px 4px 4px 4px;
+ box-shadow: 1px 1px 7px gray;
+ display: none;
+ font-size: smaller;
+ max-width: 80%;
+ opacity: 0.9;
+ padding: 1ex 1em 1em;
+ position: absolute;
+ z-index: 2147483647;
+}
+
+#powerTip div.ttdoc {
+ color: grey;
+ font-style: italic;
+}
+
+#powerTip div.ttname a {
+ font-weight: bold;
+}
+
+#powerTip div.ttname {
+ font-weight: bold;
+}
+
+#powerTip div.ttdeci {
+ color: #006318;
+}
+
+#powerTip div {
+ margin: 0px;
+ padding: 0px;
+ font: 12px/16px Roboto,sans-serif;
+}
+
+#powerTip:before, #powerTip:after {
+ content: "";
+ position: absolute;
+ margin: 0px;
+}
+
+#powerTip.n:after, #powerTip.n:before,
+#powerTip.s:after, #powerTip.s:before,
+#powerTip.w:after, #powerTip.w:before,
+#powerTip.e:after, #powerTip.e:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.nw:after, #powerTip.nw:before,
+#powerTip.sw:after, #powerTip.sw:before {
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+}
+
+#powerTip.n:after, #powerTip.s:after,
+#powerTip.w:after, #powerTip.e:after,
+#powerTip.nw:after, #powerTip.ne:after,
+#powerTip.sw:after, #powerTip.se:after {
+ border-color: rgba(255, 255, 255, 0);
+}
+
+#powerTip.n:before, #powerTip.s:before,
+#powerTip.w:before, #powerTip.e:before,
+#powerTip.nw:before, #powerTip.ne:before,
+#powerTip.sw:before, #powerTip.se:before {
+ border-color: rgba(128, 128, 128, 0);
+}
+
+#powerTip.n:after, #powerTip.n:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.nw:after, #powerTip.nw:before {
+ top: 100%;
+}
+
+#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after {
+ border-top-color: #ffffff;
+ border-width: 10px;
+ margin: 0px -10px;
+}
+#powerTip.n:before {
+ border-top-color: #808080;
+ border-width: 11px;
+ margin: 0px -11px;
+}
+#powerTip.n:after, #powerTip.n:before {
+ left: 50%;
+}
+
+#powerTip.nw:after, #powerTip.nw:before {
+ right: 14px;
+}
+
+#powerTip.ne:after, #powerTip.ne:before {
+ left: 14px;
+}
+
+#powerTip.s:after, #powerTip.s:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.sw:after, #powerTip.sw:before {
+ bottom: 100%;
+}
+
+#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after {
+ border-bottom-color: #ffffff;
+ border-width: 10px;
+ margin: 0px -10px;
+}
+
+#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before {
+ border-bottom-color: #808080;
+ border-width: 11px;
+ margin: 0px -11px;
+}
+
+#powerTip.s:after, #powerTip.s:before {
+ left: 50%;
+}
+
+#powerTip.sw:after, #powerTip.sw:before {
+ right: 14px;
+}
+
+#powerTip.se:after, #powerTip.se:before {
+ left: 14px;
+}
+
+#powerTip.e:after, #powerTip.e:before {
+ left: 100%;
+}
+#powerTip.e:after {
+ border-left-color: #ffffff;
+ border-width: 10px;
+ top: 50%;
+ margin-top: -10px;
+}
+#powerTip.e:before {
+ border-left-color: #808080;
+ border-width: 11px;
+ top: 50%;
+ margin-top: -11px;
+}
+
+#powerTip.w:after, #powerTip.w:before {
+ right: 100%;
+}
+#powerTip.w:after {
+ border-right-color: #ffffff;
+ border-width: 10px;
+ top: 50%;
+ margin-top: -10px;
+}
+#powerTip.w:before {
+ border-right-color: #808080;
+ border-width: 11px;
+ top: 50%;
+ margin-top: -11px;
+}
+
+@media print
+{
+ #top { display: none; }
+ #side-nav { display: none; }
+ #nav-path { display: none; }
+ body { overflow:visible; }
+ h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
+ .summary { display: none; }
+ .memitem { page-break-inside: avoid; }
+ #doc-content
+ {
+ margin-left:0 !important;
+ height:auto !important;
+ width:auto !important;
+ overflow:inherit;
+ display:inline;
+ }
+}
+
+/* @group Markdown */
+
+/*
+table.markdownTable {
+ border-collapse:collapse;
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+table.markdownTable td, table.markdownTable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+table.markdownTableHead tr {
+}
+
+table.markdownTableBodyLeft td, table.markdownTable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+th.markdownTableHeadLeft th.markdownTableHeadRight th.markdownTableHeadCenter th.markdownTableHeadNone {
+ background-color: #374F7F;
+ color: #FFFFFF;
+ font-size: 110%;
+ padding-bottom: 4px;
+ padding-top: 5px;
+}
+
+th.markdownTableHeadLeft {
+ text-align: left
+}
+
+th.markdownTableHeadRight {
+ text-align: right
+}
+
+th.markdownTableHeadCenter {
+ text-align: center
+}
+*/
+
+table.markdownTable {
+ border-collapse:collapse;
+ margin-top: 4px;
+ margin-bottom: 4px;
+}
+
+table.markdownTable td, table.markdownTable th {
+ border: 1px solid #2D4068;
+ padding: 3px 7px 2px;
+}
+
+table.markdownTable tr {
+}
+
+th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone {
+ background-color: #374F7F;
+ color: #FFFFFF;
+ font-size: 110%;
+ padding-bottom: 4px;
+ padding-top: 5px;
+}
+
+th.markdownTableHeadLeft, td.markdownTableBodyLeft {
+ text-align: left
+}
+
+th.markdownTableHeadRight, td.markdownTableBodyRight {
+ text-align: right
+}
+
+th.markdownTableHeadCenter, td.markdownTableBodyCenter {
+ text-align: center
+}
+
+
+/* @end */
diff --git a/docs/html/doxygen.png b/docs/html/doxygen.png
new file mode 100644
index 0000000..3ff17d8
--- /dev/null
+++ b/docs/html/doxygen.png
Binary files differ
diff --git a/docs/html/dynsections.js b/docs/html/dynsections.js
new file mode 100644
index 0000000..85e1836
--- /dev/null
+++ b/docs/html/dynsections.js
@@ -0,0 +1,97 @@
+function toggleVisibility(linkObj)
+{
+ var base = $(linkObj).attr('id');
+ var summary = $('#'+base+'-summary');
+ var content = $('#'+base+'-content');
+ var trigger = $('#'+base+'-trigger');
+ var src=$(trigger).attr('src');
+ if (content.is(':visible')===true) {
+ content.hide();
+ summary.show();
+ $(linkObj).addClass('closed').removeClass('opened');
+ $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png');
+ } else {
+ content.show();
+ summary.hide();
+ $(linkObj).removeClass('closed').addClass('opened');
+ $(trigger).attr('src',src.substring(0,src.length-10)+'open.png');
+ }
+ return false;
+}
+
+function updateStripes()
+{
+ $('table.directory tr').
+ removeClass('even').filter(':visible:even').addClass('even');
+}
+
+function toggleLevel(level)
+{
+ $('table.directory tr').each(function() {
+ var l = this.id.split('_').length-1;
+ var i = $('#img'+this.id.substring(3));
+ var a = $('#arr'+this.id.substring(3));
+ if (l<level+1) {
+ i.removeClass('iconfopen iconfclosed').addClass('iconfopen');
+ a.html('▼');
+ $(this).show();
+ } else if (l==level+1) {
+ i.removeClass('iconfclosed iconfopen').addClass('iconfclosed');
+ a.html('►');
+ $(this).show();
+ } else {
+ $(this).hide();
+ }
+ });
+ updateStripes();
+}
+
+function toggleFolder(id)
+{
+ // the clicked row
+ var currentRow = $('#row_'+id);
+
+ // all rows after the clicked row
+ var rows = currentRow.nextAll("tr");
+
+ var re = new RegExp('^row_'+id+'\\d+_$', "i"); //only one sub
+
+ // only match elements AFTER this one (can't hide elements before)
+ var childRows = rows.filter(function() { return this.id.match(re); });
+
+ // first row is visible we are HIDING
+ if (childRows.filter(':first').is(':visible')===true) {
+ // replace down arrow by right arrow for current row
+ var currentRowSpans = currentRow.find("span");
+ currentRowSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
+ currentRowSpans.filter(".arrow").html('►');
+ rows.filter("[id^=row_"+id+"]").hide(); // hide all children
+ } else { // we are SHOWING
+ // replace right arrow by down arrow for current row
+ var currentRowSpans = currentRow.find("span");
+ currentRowSpans.filter(".iconfclosed").removeClass("iconfclosed").addClass("iconfopen");
+ currentRowSpans.filter(".arrow").html('▼');
+ // replace down arrows by right arrows for child rows
+ var childRowsSpans = childRows.find("span");
+ childRowsSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
+ childRowsSpans.filter(".arrow").html('►');
+ childRows.show(); //show all children
+ }
+ updateStripes();
+}
+
+
+function toggleInherit(id)
+{
+ var rows = $('tr.inherit.'+id);
+ var img = $('tr.inherit_header.'+id+' img');
+ var src = $(img).attr('src');
+ if (rows.filter(':first').is(':visible')===true) {
+ rows.css('display','none');
+ $(img).attr('src',src.substring(0,src.length-8)+'closed.png');
+ } else {
+ rows.css('display','table-row'); // using show() causes jump in firefox
+ $(img).attr('src',src.substring(0,src.length-10)+'open.png');
+ }
+}
+
diff --git a/docs/html/files.html b/docs/html/files.html
new file mode 100644
index 0000000..3fdfb89
--- /dev/null
+++ b/docs/html/files.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: File List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">File List</div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here is a list of all documented files with brief descriptions:</div><div class="directory">
+<div class="levels">[detail level <span onclick="javascript:toggleLevel(1);">1</span><span onclick="javascript:toggleLevel(2);">2</span>]</div><table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:0px;display:inline-block;"> </span><span id="arr_0_" class="arrow" onclick="toggleFolder('0_')">▼</span><span id="img_0_" class="iconfopen" onclick="toggleFolder('0_')"> </span><a class="el" href="dir_7dae9cfde651cd3cb034485ce5e391b9.html" target="_self">psa</a></td><td class="desc"></td></tr>
+<tr id="row_0_0_"><td class="entry"><span style="width:32px;display:inline-block;"> </span><a href="crypto_8h_source.html"><span class="icondoc"></span></a><a class="el" href="crypto_8h.html" target="_self">crypto.h</a></td><td class="desc">Platform Security Architecture cryptography module </td></tr>
+<tr id="row_0_1_" class="even"><td class="entry"><span style="width:32px;display:inline-block;"> </span><a href="crypto__sizes_8h_source.html"><span class="icondoc"></span></a><a class="el" href="crypto__sizes_8h.html" target="_self">crypto_sizes.h</a></td><td class="desc">PSA cryptography module: Mbed TLS buffer size macros </td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/folderclosed.png b/docs/html/folderclosed.png
new file mode 100644
index 0000000..bb8ab35
--- /dev/null
+++ b/docs/html/folderclosed.png
Binary files differ
diff --git a/docs/html/folderopen.png b/docs/html/folderopen.png
new file mode 100644
index 0000000..d6c7f67
--- /dev/null
+++ b/docs/html/folderopen.png
Binary files differ
diff --git a/docs/html/functions.html b/docs/html/functions.html
new file mode 100644
index 0000000..cd5b542
--- /dev/null
+++ b/docs/html/functions.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Class Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+<div class="textblock">Here is a list of all documented class members with links to the class documentation for each member:</div><ul>
+<li>e
+: <a class="el" href="structpsa__generate__key__extra__rsa.html#a53ccb9e4375f3c9af6e3ecfe111ce11d">psa_generate_key_extra_rsa</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/functions_vars.html b/docs/html/functions_vars.html
new file mode 100644
index 0000000..e025400
--- /dev/null
+++ b/docs/html/functions_vars.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Class Members - Variables</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+ <ul>
+<li>e
+: <a class="el" href="structpsa__generate__key__extra__rsa.html#a53ccb9e4375f3c9af6e3ecfe111ce11d">psa_generate_key_extra_rsa</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/globals.html b/docs/html/globals.html
new file mode 100644
index 0000000..8085206
--- /dev/null
+++ b/docs/html/globals.html
@@ -0,0 +1,560 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+<div class="textblock">Here is a list of all documented file members with links to the documentation:</div>
+
+<h3><a id="index_p"></a>- p -</h3><ul>
+<li>psa_aead_decrypt()
+: <a class="el" href="group__aead.html#ga5b88ad2cfbf2e98039858416fa3ebd7a">crypto.h</a>
+</li>
+<li>PSA_AEAD_DECRYPT_OUTPUT_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a1d057796166c16eb673ad1997e48a60b">crypto_sizes.h</a>
+</li>
+<li>psa_aead_encrypt()
+: <a class="el" href="group__aead.html#ga14e4068a3d328515a4884f3037904d54">crypto.h</a>
+</li>
+<li>PSA_AEAD_ENCRYPT_OUTPUT_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a85667d47a7aa6c7b99a80e5273671266">crypto_sizes.h</a>
+</li>
+<li>PSA_AEAD_TAG_SIZE
+: <a class="el" href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4">crypto.h</a>
+</li>
+<li>PSA_ALG_ARC4
+: <a class="el" href="group__crypto__types.html#gab6a5284decb0e5e1b5b8740a41ef3c5e">crypto.h</a>
+</li>
+<li>PSA_ALG_BLOCK_CIPHER_PAD_NONE
+: <a class="el" href="group__crypto__types.html#ga0992d26a02a2a7dc316cd5abc5254966">crypto.h</a>
+</li>
+<li>PSA_ALG_CBC_BASE
+: <a class="el" href="group__crypto__types.html#ga931f31d4f05c3dab9fd5d7fdcd3715f2">crypto.h</a>
+</li>
+<li>PSA_ALG_CTR
+: <a class="el" href="group__crypto__types.html#gad318309706a769cffdc64e4c7e06b2e9">crypto.h</a>
+</li>
+<li>PSA_ALG_DETERMINISTIC_ECDSA
+: <a class="el" href="group__crypto__types.html#ga11da566bcd341661c8de921e2ca5ed03">crypto.h</a>
+</li>
+<li>PSA_ALG_DSA
+: <a class="el" href="group__crypto__types.html#ga9a68efdddff5ae95f104a1416b12742e">crypto.h</a>
+</li>
+<li>PSA_ALG_ECDSA
+: <a class="el" href="group__crypto__types.html#ga7e3ce9f514a227d5ba5d8318870452e3">crypto.h</a>
+</li>
+<li>PSA_ALG_ECDSA_ANY
+: <a class="el" href="group__crypto__types.html#ga51d6b6044a62e33cae0cf64bfc3b22a4">crypto.h</a>
+</li>
+<li>PSA_ALG_HKDF
+: <a class="el" href="group__crypto__types.html#ga32a888fb360e6e25cab8a343772c4a82">crypto.h</a>
+</li>
+<li>PSA_ALG_HMAC
+: <a class="el" href="group__crypto__types.html#ga70f397425684b3efcde1e0e34c28261f">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_AEAD
+: <a class="el" href="group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_ASYMMETRIC_ENCRYPTION
+: <a class="el" href="group__crypto__types.html#ga41d2ee937d54efd76bd54a97b2ebc08a">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_BLOCK_CIPHER
+: <a class="el" href="group__crypto__types.html#ga02e787d79c0cd666efcd090569d5b31c">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_CIPHER
+: <a class="el" href="group__crypto__types.html#ga1d1a5a402ad89a2e68f12bfb535490eb">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_CIPHER_MAC
+: <a class="el" href="group__crypto__types.html#ga8986360ff97dbd91f220edf9202e375d">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_HASH
+: <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_HKDF
+: <a class="el" href="group__crypto__types.html#ga1979d0a76fcee6164cf2e65960f38db2">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_HMAC
+: <a class="el" href="group__crypto__types.html#ga4a050c3c3cbc6eb96418f18847601c8a">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_KEY_AGREEMENT
+: <a class="el" href="group__crypto__types.html#ga59753742cb06553bd22751bbef472b6f">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_KEY_DERIVATION
+: <a class="el" href="group__crypto__types.html#gaf8b90c648aa53dbd06c236695e300cd0">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_MAC
+: <a class="el" href="group__crypto__types.html#gaca7aee4c9dde316b3b1a150a26eab776">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_SIGN
+: <a class="el" href="group__crypto__types.html#ga6d490d0904e0698f6c1268a89d72ff31">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_STREAM_CIPHER
+: <a class="el" href="group__crypto__types.html#gacfec68e0c6175e02e1b2ebc97df383c0">crypto.h</a>
+</li>
+<li>PSA_ALG_RSA_OAEP
+: <a class="el" href="group__crypto__types.html#gaa1235dc3fdd9839c6c1b1a9857344c76">crypto.h</a>
+</li>
+<li>PSA_ALG_RSA_PKCS1V15_CRYPT
+: <a class="el" href="group__crypto__types.html#ga4c540d3abe43fb9abcb94f2bc51acef9">crypto.h</a>
+</li>
+<li>PSA_ALG_RSA_PKCS1V15_SIGN
+: <a class="el" href="group__crypto__types.html#ga702ff75385a6ae7d4247033f479439af">crypto.h</a>
+</li>
+<li>PSA_ALG_RSA_PKCS1V15_SIGN_RAW
+: <a class="el" href="group__crypto__types.html#ga4215e2a78dcf834e9a625927faa2a817">crypto.h</a>
+</li>
+<li>PSA_ALG_RSA_PSS
+: <a class="el" href="group__crypto__types.html#ga62152bf4cb4bf6aace5e1be8f143564d">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA3_224
+: <a class="el" href="group__crypto__types.html#ga16f5fe34ccce68c2fada1224c054a999">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA3_256
+: <a class="el" href="group__crypto__types.html#gaace70d9515489bbe3c5e7ac1b7d9155b">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA3_384
+: <a class="el" href="group__crypto__types.html#gab0f079257ea75e2acfe2fc3b38c78cd8">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA3_512
+: <a class="el" href="group__crypto__types.html#ga37e5dbe936dddb155e76f2997de27188">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_224
+: <a class="el" href="group__crypto__types.html#ga25d6a3244d10a7148fe6b026d1979f7b">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_256
+: <a class="el" href="group__crypto__types.html#ga619471f978e13cdd0a1e37145e4bf341">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_384
+: <a class="el" href="group__crypto__types.html#ga58af64dd9a86a287e8da9ed7739eead4">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_512
+: <a class="el" href="group__crypto__types.html#gafba3ae409f46d3dd7f37a0910660c3e9">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_512_224
+: <a class="el" href="group__crypto__types.html#ga3fe2d7c3c80e3186ca78d16a35d5d931">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_512_256
+: <a class="el" href="group__crypto__types.html#ga5910b3964c14e9613e8643a45b09c2d4">crypto.h</a>
+</li>
+<li>PSA_ALG_SIGN_GET_HASH
+: <a class="el" href="group__crypto__types.html#ga24cf6d7bcd2b9aeeeff86f07b6c674e3">crypto.h</a>
+</li>
+<li>psa_algorithm_t
+: <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">crypto.h</a>
+</li>
+<li>psa_asymmetric_decrypt()
+: <a class="el" href="group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6">crypto.h</a>
+</li>
+<li>PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a61a246f3eac41989821d982e56fea6c1">crypto_sizes.h</a>
+</li>
+<li>psa_asymmetric_encrypt()
+: <a class="el" href="group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2">crypto.h</a>
+</li>
+<li>PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a66ba3bd93e5ec52870ccc3848778bad8">crypto_sizes.h</a>
+</li>
+<li>psa_asymmetric_sign()
+: <a class="el" href="group__asymmetric.html#ga48091460d1ead078d93caa3611aec976">crypto.h</a>
+</li>
+<li>PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a77565b9b4fe6d8730fd2120f4c8378ab">crypto_sizes.h</a>
+</li>
+<li>PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE
+: <a class="el" href="crypto__sizes_8h.html#ad755101764dba14589e5919ee41be7ca">crypto_sizes.h</a>
+</li>
+<li>psa_asymmetric_verify()
+: <a class="el" href="group__asymmetric.html#gaee3e92946c1c4b3dfa90879e2f7d1321">crypto.h</a>
+</li>
+<li>PSA_BLOCK_CIPHER_BLOCK_SIZE
+: <a class="el" href="group__crypto__types.html#gacaa366bdeb0413e63e87a667c5457b2e">crypto.h</a>
+</li>
+<li>psa_cipher_abort()
+: <a class="el" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">crypto.h</a>
+</li>
+<li>psa_cipher_decrypt_setup()
+: <a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">crypto.h</a>
+</li>
+<li>psa_cipher_encrypt_setup()
+: <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">crypto.h</a>
+</li>
+<li>psa_cipher_finish()
+: <a class="el" href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">crypto.h</a>
+</li>
+<li>psa_cipher_generate_iv()
+: <a class="el" href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">crypto.h</a>
+</li>
+<li>psa_cipher_operation_t
+: <a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">crypto.h</a>
+</li>
+<li>psa_cipher_set_iv()
+: <a class="el" href="group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42">crypto.h</a>
+</li>
+<li>psa_cipher_update()
+: <a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">crypto.h</a>
+</li>
+<li>PSA_CRYPTO_GENERATOR_INIT
+: <a class="el" href="group__generators.html#ga4788b471385fc667876fbd8a0d3fe062">crypto.h</a>
+</li>
+<li>psa_crypto_generator_t
+: <a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">crypto.h</a>
+</li>
+<li>psa_crypto_init()
+: <a class="el" href="group__basic.html#ga2de150803fc2f7dc6101d5af7e921dd9">crypto.h</a>
+</li>
+<li>psa_destroy_key()
+: <a class="el" href="group__key__management.html#ga2e9a60a9525ce6b3082a72df2080f0c5">crypto.h</a>
+</li>
+<li>psa_ecc_curve_t
+: <a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">crypto.h</a>
+</li>
+<li>PSA_ECDSA_SIGNATURE_SIZE
+: <a class="el" href="group__asymmetric.html#ga10c472a35f04051add6b20cc228ffc11">crypto.h</a>
+</li>
+<li>PSA_ERROR_BAD_STATE
+: <a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">crypto.h</a>
+</li>
+<li>PSA_ERROR_BUFFER_TOO_SMALL
+: <a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">crypto.h</a>
+</li>
+<li>PSA_ERROR_COMMUNICATION_FAILURE
+: <a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">crypto.h</a>
+</li>
+<li>PSA_ERROR_EMPTY_SLOT
+: <a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">crypto.h</a>
+</li>
+<li>PSA_ERROR_HARDWARE_FAILURE
+: <a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">crypto.h</a>
+</li>
+<li>PSA_ERROR_INSUFFICIENT_CAPACITY
+: <a class="el" href="group__basic.html#gaf1fa61f72e9e5b4a848c991bea495767">crypto.h</a>
+</li>
+<li>PSA_ERROR_INSUFFICIENT_ENTROPY
+: <a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">crypto.h</a>
+</li>
+<li>PSA_ERROR_INSUFFICIENT_MEMORY
+: <a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">crypto.h</a>
+</li>
+<li>PSA_ERROR_INSUFFICIENT_STORAGE
+: <a class="el" href="group__basic.html#ga897a45eb206a6f6b7be7ffbe36f0d766">crypto.h</a>
+</li>
+<li>PSA_ERROR_INVALID_ARGUMENT
+: <a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">crypto.h</a>
+</li>
+<li>PSA_ERROR_INVALID_PADDING
+: <a class="el" href="group__basic.html#gabe29594edbfb152cf153975b0597ac48">crypto.h</a>
+</li>
+<li>PSA_ERROR_INVALID_SIGNATURE
+: <a class="el" href="group__basic.html#ga35927f755d232c4766de600f2c49e9f2">crypto.h</a>
+</li>
+<li>PSA_ERROR_NOT_PERMITTED
+: <a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">crypto.h</a>
+</li>
+<li>PSA_ERROR_NOT_SUPPORTED
+: <a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">crypto.h</a>
+</li>
+<li>PSA_ERROR_OCCUPIED_SLOT
+: <a class="el" href="group__basic.html#gac2fee3a51249fbea45360aaa911f3e58">crypto.h</a>
+</li>
+<li>PSA_ERROR_STORAGE_FAILURE
+: <a class="el" href="group__basic.html#gadd169a1af2707862b95fb9df91dfc37d">crypto.h</a>
+</li>
+<li>PSA_ERROR_TAMPERING_DETECTED
+: <a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">crypto.h</a>
+</li>
+<li>PSA_ERROR_UNKNOWN_ERROR
+: <a class="el" href="group__basic.html#ga24d5fdcdd759f846f79d9e581c63a83f">crypto.h</a>
+</li>
+<li>psa_export_key()
+: <a class="el" href="group__key__management.html#gaa67bc459b20028b268f3d75a05afe022">crypto.h</a>
+</li>
+<li>psa_export_public_key()
+: <a class="el" href="group__key__management.html#ga7355b38f8eb9330db2786604f4a83a3b">crypto.h</a>
+</li>
+<li>psa_generate_key()
+: <a class="el" href="group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10">crypto.h</a>
+</li>
+<li>psa_generate_random()
+: <a class="el" href="group__random.html#ga1985eae417dfbccedf50d5fff54ea8c5">crypto.h</a>
+</li>
+<li>psa_generator_abort()
+: <a class="el" href="group__generators.html#ga563ca64537d90368899286b36d8cf7f3">crypto.h</a>
+</li>
+<li>psa_generator_import_key()
+: <a class="el" href="group__generators.html#ga06c1ba3d989827d909b4b01ffe983beb">crypto.h</a>
+</li>
+<li>psa_generator_read()
+: <a class="el" href="group__generators.html#gab5712ad29b78c2b170e64cc5bcfc1bce">crypto.h</a>
+</li>
+<li>psa_get_generator_capacity()
+: <a class="el" href="group__generators.html#ga7453491e3b440193be2c5dccc2040fd2">crypto.h</a>
+</li>
+<li>psa_get_key_information()
+: <a class="el" href="group__key__management.html#gaf105167657ab1d484cb4a51f93413717">crypto.h</a>
+</li>
+<li>psa_get_key_lifetime()
+: <a class="el" href="group__persistence.html#gaf0daaa1dba14dc324ca83dfe1495a5e2">crypto.h</a>
+</li>
+<li>psa_get_key_policy()
+: <a class="el" href="group__policy.html#ga613f28712124f9149bd640614376ab5a">crypto.h</a>
+</li>
+<li>psa_hash_abort()
+: <a class="el" href="group__hash.html#gab0b4d5f9912a615559497a467b532928">crypto.h</a>
+</li>
+<li>psa_hash_finish()
+: <a class="el" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">crypto.h</a>
+</li>
+<li>PSA_HASH_MAX_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a6ce1014efbbc0bcca286ef7f9a72cb29">crypto_sizes.h</a>
+</li>
+<li>psa_hash_operation_t
+: <a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">crypto.h</a>
+</li>
+<li>psa_hash_setup()
+: <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">crypto.h</a>
+</li>
+<li>PSA_HASH_SIZE
+: <a class="el" href="group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99">crypto.h</a>
+</li>
+<li>psa_hash_update()
+: <a class="el" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">crypto.h</a>
+</li>
+<li>psa_hash_verify()
+: <a class="el" href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">crypto.h</a>
+</li>
+<li>psa_import_key()
+: <a class="el" href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5">crypto.h</a>
+</li>
+<li>psa_key_derivation()
+: <a class="el" href="group__derivation.html#ga1b6429f443a45e5f3209043abbbe8315">crypto.h</a>
+</li>
+<li>PSA_KEY_LIFETIME_PERSISTENT
+: <a class="el" href="group__persistence.html#ga3713a01c5fcd5f7eae46ff22ceaf6d02">crypto.h</a>
+</li>
+<li>psa_key_lifetime_t
+: <a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">crypto.h</a>
+</li>
+<li>PSA_KEY_LIFETIME_VOLATILE
+: <a class="el" href="group__persistence.html#ga8b438870ba69489b685730d346455108">crypto.h</a>
+</li>
+<li>PSA_KEY_LIFETIME_WRITE_ONCE
+: <a class="el" href="group__persistence.html#gae6b8443238ef1900cf132550d7df557f">crypto.h</a>
+</li>
+<li>psa_key_policy_get_algorithm()
+: <a class="el" href="group__policy.html#gaadf16b89ace53e1d2cb5bcb0aef24c86">crypto.h</a>
+</li>
+<li>psa_key_policy_get_usage()
+: <a class="el" href="group__policy.html#ga7746662b7503e484774d0ecb5d8ac2ab">crypto.h</a>
+</li>
+<li>psa_key_policy_init()
+: <a class="el" href="group__policy.html#gad49eb85e3fcbe70f763f511ac83e762e">crypto.h</a>
+</li>
+<li>psa_key_policy_set_usage()
+: <a class="el" href="group__policy.html#gac16792fd6d375a5f76d372090df40607">crypto.h</a>
+</li>
+<li>psa_key_policy_t
+: <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">crypto.h</a>
+</li>
+<li>psa_key_slot_t
+: <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_AES
+: <a class="el" href="group__crypto__types.html#ga6ee54579dcf278c677eda4bb1a29575e">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_ARC4
+: <a class="el" href="group__crypto__types.html#gae4d46e83f910dcaa126000a8ed03cde9">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_CAMELLIA
+: <a class="el" href="group__crypto__types.html#gad8e5da742343fd5519f9d8a630c2ed81">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_DERIVE
+: <a class="el" href="group__crypto__types.html#gae871b2357b8593f33bfd51abbf93ebb1">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_DES
+: <a class="el" href="group__crypto__types.html#ga577562bfbbc691c820d55ec308333138">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_DSA_KEYPAIR
+: <a class="el" href="group__crypto__types.html#ga011010ee28c20388f3d89fb27088ed62">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_DSA_PUBLIC_KEY
+: <a class="el" href="group__crypto__types.html#ga5e7439c2905136366c3a876e62e5ddfc">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_ECC_KEYPAIR
+: <a class="el" href="group__crypto__types.html#gadf3ad65d157bf5282849c954bf3f51af">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_ECC_PUBLIC_KEY
+: <a class="el" href="group__crypto__types.html#gad54c03d3b47020e571a72cd01d978cf2">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_GET_CURVE
+: <a class="el" href="group__crypto__types.html#ga0c567210e6f80aa8f2aa87efa7a3a3f9">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_HMAC
+: <a class="el" href="group__crypto__types.html#ga92d989f4ca64abd00f463defd773a6f8">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_ASYMMETRIC
+: <a class="el" href="group__crypto__types.html#gab138ae2ebf2905dfbaf4154db2620939">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_ECC
+: <a class="el" href="group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_KEYPAIR
+: <a class="el" href="group__crypto__types.html#gac14c6d6e1b2b7f4a92a7b757465cff29">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_PUBLIC_KEY
+: <a class="el" href="group__crypto__types.html#gac674a0f059bc0cb72b47f0c517b4f45b">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_RSA
+: <a class="el" href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_VENDOR_DEFINED
+: <a class="el" href="group__crypto__types.html#gadbe4c086a6562aefe344bc79e51bdfd3">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY
+: <a class="el" href="group__crypto__types.html#gaf09f1ca1de6a7e7cff0fe516f3f6c91d">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_NONE
+: <a class="el" href="group__crypto__types.html#gafce7ab2b54ce97ea5bff73f13a9f3e5b">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR
+: <a class="el" href="group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_RAW_DATA
+: <a class="el" href="group__crypto__types.html#gaa97f92025533102616b32d571c940d80">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_RSA_KEYPAIR
+: <a class="el" href="group__crypto__types.html#ga581f50687f5d650456925278948f2799">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_RSA_PUBLIC_KEY
+: <a class="el" href="group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b">crypto.h</a>
+</li>
+<li>psa_key_type_t
+: <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_VENDOR_FLAG
+: <a class="el" href="group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_DECRYPT
+: <a class="el" href="group__policy.html#gac3f2d2e5983db1edde9f142ca9bf8e6a">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_DERIVE
+: <a class="el" href="group__policy.html#gaf19022acc5ef23cf12477f632b48a0b2">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_ENCRYPT
+: <a class="el" href="group__policy.html#ga75153b296d045d529d97203a6a995dad">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_EXPORT
+: <a class="el" href="group__policy.html#ga7dddccdd1303176e87a4d20c87b589ed">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_SIGN
+: <a class="el" href="group__policy.html#ga99b9f456cf59efc4b5579465407aef5a">crypto.h</a>
+</li>
+<li>psa_key_usage_t
+: <a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_VERIFY
+: <a class="el" href="group__policy.html#ga39b54ffd5958b69634607924fa53cea6">crypto.h</a>
+</li>
+<li>psa_mac_abort()
+: <a class="el" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">crypto.h</a>
+</li>
+<li>PSA_MAC_FINAL_SIZE
+: <a class="el" href="crypto__sizes_8h.html#aa84c5fb384ac7cb1bfc52adde96588ee">crypto_sizes.h</a>
+</li>
+<li>PSA_MAC_MAX_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a4681cc4f6226883a2160122c562ca682">crypto_sizes.h</a>
+</li>
+<li>psa_mac_operation_t
+: <a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">crypto.h</a>
+</li>
+<li>psa_mac_sign_finish()
+: <a class="el" href="group__MAC.html#gac22bc0125580c96724a09226cfbc97f2">crypto.h</a>
+</li>
+<li>psa_mac_sign_setup()
+: <a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">crypto.h</a>
+</li>
+<li>psa_mac_update()
+: <a class="el" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">crypto.h</a>
+</li>
+<li>psa_mac_verify_finish()
+: <a class="el" href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">crypto.h</a>
+</li>
+<li>psa_mac_verify_setup()
+: <a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">crypto.h</a>
+</li>
+<li>psa_set_key_lifetime()
+: <a class="el" href="group__persistence.html#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8">crypto.h</a>
+</li>
+<li>psa_set_key_policy()
+: <a class="el" href="group__policy.html#gad7faa7e64aa771f7441c44ceff21af19">crypto.h</a>
+</li>
+<li>psa_status_t
+: <a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">crypto.h</a>
+</li>
+<li>PSA_SUCCESS
+: <a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">crypto.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/globals_defs.html b/docs/html/globals_defs.html
new file mode 100644
index 0000000..871d56d
--- /dev/null
+++ b/docs/html/globals_defs.html
@@ -0,0 +1,389 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+ 
+
+<h3><a id="index_p"></a>- p -</h3><ul>
+<li>PSA_AEAD_DECRYPT_OUTPUT_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a1d057796166c16eb673ad1997e48a60b">crypto_sizes.h</a>
+</li>
+<li>PSA_AEAD_ENCRYPT_OUTPUT_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a85667d47a7aa6c7b99a80e5273671266">crypto_sizes.h</a>
+</li>
+<li>PSA_AEAD_TAG_SIZE
+: <a class="el" href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4">crypto.h</a>
+</li>
+<li>PSA_ALG_ARC4
+: <a class="el" href="group__crypto__types.html#gab6a5284decb0e5e1b5b8740a41ef3c5e">crypto.h</a>
+</li>
+<li>PSA_ALG_BLOCK_CIPHER_PAD_NONE
+: <a class="el" href="group__crypto__types.html#ga0992d26a02a2a7dc316cd5abc5254966">crypto.h</a>
+</li>
+<li>PSA_ALG_CBC_BASE
+: <a class="el" href="group__crypto__types.html#ga931f31d4f05c3dab9fd5d7fdcd3715f2">crypto.h</a>
+</li>
+<li>PSA_ALG_CTR
+: <a class="el" href="group__crypto__types.html#gad318309706a769cffdc64e4c7e06b2e9">crypto.h</a>
+</li>
+<li>PSA_ALG_DETERMINISTIC_ECDSA
+: <a class="el" href="group__crypto__types.html#ga11da566bcd341661c8de921e2ca5ed03">crypto.h</a>
+</li>
+<li>PSA_ALG_DSA
+: <a class="el" href="group__crypto__types.html#ga9a68efdddff5ae95f104a1416b12742e">crypto.h</a>
+</li>
+<li>PSA_ALG_ECDSA
+: <a class="el" href="group__crypto__types.html#ga7e3ce9f514a227d5ba5d8318870452e3">crypto.h</a>
+</li>
+<li>PSA_ALG_ECDSA_ANY
+: <a class="el" href="group__crypto__types.html#ga51d6b6044a62e33cae0cf64bfc3b22a4">crypto.h</a>
+</li>
+<li>PSA_ALG_HKDF
+: <a class="el" href="group__crypto__types.html#ga32a888fb360e6e25cab8a343772c4a82">crypto.h</a>
+</li>
+<li>PSA_ALG_HMAC
+: <a class="el" href="group__crypto__types.html#ga70f397425684b3efcde1e0e34c28261f">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_AEAD
+: <a class="el" href="group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_ASYMMETRIC_ENCRYPTION
+: <a class="el" href="group__crypto__types.html#ga41d2ee937d54efd76bd54a97b2ebc08a">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_BLOCK_CIPHER
+: <a class="el" href="group__crypto__types.html#ga02e787d79c0cd666efcd090569d5b31c">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_CIPHER
+: <a class="el" href="group__crypto__types.html#ga1d1a5a402ad89a2e68f12bfb535490eb">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_CIPHER_MAC
+: <a class="el" href="group__crypto__types.html#ga8986360ff97dbd91f220edf9202e375d">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_HASH
+: <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_HKDF
+: <a class="el" href="group__crypto__types.html#ga1979d0a76fcee6164cf2e65960f38db2">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_HMAC
+: <a class="el" href="group__crypto__types.html#ga4a050c3c3cbc6eb96418f18847601c8a">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_KEY_AGREEMENT
+: <a class="el" href="group__crypto__types.html#ga59753742cb06553bd22751bbef472b6f">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_KEY_DERIVATION
+: <a class="el" href="group__crypto__types.html#gaf8b90c648aa53dbd06c236695e300cd0">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_MAC
+: <a class="el" href="group__crypto__types.html#gaca7aee4c9dde316b3b1a150a26eab776">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_SIGN
+: <a class="el" href="group__crypto__types.html#ga6d490d0904e0698f6c1268a89d72ff31">crypto.h</a>
+</li>
+<li>PSA_ALG_IS_STREAM_CIPHER
+: <a class="el" href="group__crypto__types.html#gacfec68e0c6175e02e1b2ebc97df383c0">crypto.h</a>
+</li>
+<li>PSA_ALG_RSA_OAEP
+: <a class="el" href="group__crypto__types.html#gaa1235dc3fdd9839c6c1b1a9857344c76">crypto.h</a>
+</li>
+<li>PSA_ALG_RSA_PKCS1V15_CRYPT
+: <a class="el" href="group__crypto__types.html#ga4c540d3abe43fb9abcb94f2bc51acef9">crypto.h</a>
+</li>
+<li>PSA_ALG_RSA_PKCS1V15_SIGN
+: <a class="el" href="group__crypto__types.html#ga702ff75385a6ae7d4247033f479439af">crypto.h</a>
+</li>
+<li>PSA_ALG_RSA_PKCS1V15_SIGN_RAW
+: <a class="el" href="group__crypto__types.html#ga4215e2a78dcf834e9a625927faa2a817">crypto.h</a>
+</li>
+<li>PSA_ALG_RSA_PSS
+: <a class="el" href="group__crypto__types.html#ga62152bf4cb4bf6aace5e1be8f143564d">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA3_224
+: <a class="el" href="group__crypto__types.html#ga16f5fe34ccce68c2fada1224c054a999">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA3_256
+: <a class="el" href="group__crypto__types.html#gaace70d9515489bbe3c5e7ac1b7d9155b">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA3_384
+: <a class="el" href="group__crypto__types.html#gab0f079257ea75e2acfe2fc3b38c78cd8">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA3_512
+: <a class="el" href="group__crypto__types.html#ga37e5dbe936dddb155e76f2997de27188">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_224
+: <a class="el" href="group__crypto__types.html#ga25d6a3244d10a7148fe6b026d1979f7b">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_256
+: <a class="el" href="group__crypto__types.html#ga619471f978e13cdd0a1e37145e4bf341">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_384
+: <a class="el" href="group__crypto__types.html#ga58af64dd9a86a287e8da9ed7739eead4">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_512
+: <a class="el" href="group__crypto__types.html#gafba3ae409f46d3dd7f37a0910660c3e9">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_512_224
+: <a class="el" href="group__crypto__types.html#ga3fe2d7c3c80e3186ca78d16a35d5d931">crypto.h</a>
+</li>
+<li>PSA_ALG_SHA_512_256
+: <a class="el" href="group__crypto__types.html#ga5910b3964c14e9613e8643a45b09c2d4">crypto.h</a>
+</li>
+<li>PSA_ALG_SIGN_GET_HASH
+: <a class="el" href="group__crypto__types.html#ga24cf6d7bcd2b9aeeeff86f07b6c674e3">crypto.h</a>
+</li>
+<li>PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a61a246f3eac41989821d982e56fea6c1">crypto_sizes.h</a>
+</li>
+<li>PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a66ba3bd93e5ec52870ccc3848778bad8">crypto_sizes.h</a>
+</li>
+<li>PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a77565b9b4fe6d8730fd2120f4c8378ab">crypto_sizes.h</a>
+</li>
+<li>PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE
+: <a class="el" href="crypto__sizes_8h.html#ad755101764dba14589e5919ee41be7ca">crypto_sizes.h</a>
+</li>
+<li>PSA_BLOCK_CIPHER_BLOCK_SIZE
+: <a class="el" href="group__crypto__types.html#gacaa366bdeb0413e63e87a667c5457b2e">crypto.h</a>
+</li>
+<li>PSA_CRYPTO_GENERATOR_INIT
+: <a class="el" href="group__generators.html#ga4788b471385fc667876fbd8a0d3fe062">crypto.h</a>
+</li>
+<li>PSA_ECDSA_SIGNATURE_SIZE
+: <a class="el" href="group__asymmetric.html#ga10c472a35f04051add6b20cc228ffc11">crypto.h</a>
+</li>
+<li>PSA_ERROR_BAD_STATE
+: <a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">crypto.h</a>
+</li>
+<li>PSA_ERROR_BUFFER_TOO_SMALL
+: <a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">crypto.h</a>
+</li>
+<li>PSA_ERROR_COMMUNICATION_FAILURE
+: <a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">crypto.h</a>
+</li>
+<li>PSA_ERROR_EMPTY_SLOT
+: <a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">crypto.h</a>
+</li>
+<li>PSA_ERROR_HARDWARE_FAILURE
+: <a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">crypto.h</a>
+</li>
+<li>PSA_ERROR_INSUFFICIENT_CAPACITY
+: <a class="el" href="group__basic.html#gaf1fa61f72e9e5b4a848c991bea495767">crypto.h</a>
+</li>
+<li>PSA_ERROR_INSUFFICIENT_ENTROPY
+: <a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">crypto.h</a>
+</li>
+<li>PSA_ERROR_INSUFFICIENT_MEMORY
+: <a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">crypto.h</a>
+</li>
+<li>PSA_ERROR_INSUFFICIENT_STORAGE
+: <a class="el" href="group__basic.html#ga897a45eb206a6f6b7be7ffbe36f0d766">crypto.h</a>
+</li>
+<li>PSA_ERROR_INVALID_ARGUMENT
+: <a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">crypto.h</a>
+</li>
+<li>PSA_ERROR_INVALID_PADDING
+: <a class="el" href="group__basic.html#gabe29594edbfb152cf153975b0597ac48">crypto.h</a>
+</li>
+<li>PSA_ERROR_INVALID_SIGNATURE
+: <a class="el" href="group__basic.html#ga35927f755d232c4766de600f2c49e9f2">crypto.h</a>
+</li>
+<li>PSA_ERROR_NOT_PERMITTED
+: <a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">crypto.h</a>
+</li>
+<li>PSA_ERROR_NOT_SUPPORTED
+: <a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">crypto.h</a>
+</li>
+<li>PSA_ERROR_OCCUPIED_SLOT
+: <a class="el" href="group__basic.html#gac2fee3a51249fbea45360aaa911f3e58">crypto.h</a>
+</li>
+<li>PSA_ERROR_STORAGE_FAILURE
+: <a class="el" href="group__basic.html#gadd169a1af2707862b95fb9df91dfc37d">crypto.h</a>
+</li>
+<li>PSA_ERROR_TAMPERING_DETECTED
+: <a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">crypto.h</a>
+</li>
+<li>PSA_ERROR_UNKNOWN_ERROR
+: <a class="el" href="group__basic.html#ga24d5fdcdd759f846f79d9e581c63a83f">crypto.h</a>
+</li>
+<li>PSA_HASH_MAX_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a6ce1014efbbc0bcca286ef7f9a72cb29">crypto_sizes.h</a>
+</li>
+<li>PSA_HASH_SIZE
+: <a class="el" href="group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99">crypto.h</a>
+</li>
+<li>PSA_KEY_LIFETIME_PERSISTENT
+: <a class="el" href="group__persistence.html#ga3713a01c5fcd5f7eae46ff22ceaf6d02">crypto.h</a>
+</li>
+<li>PSA_KEY_LIFETIME_VOLATILE
+: <a class="el" href="group__persistence.html#ga8b438870ba69489b685730d346455108">crypto.h</a>
+</li>
+<li>PSA_KEY_LIFETIME_WRITE_ONCE
+: <a class="el" href="group__persistence.html#gae6b8443238ef1900cf132550d7df557f">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_AES
+: <a class="el" href="group__crypto__types.html#ga6ee54579dcf278c677eda4bb1a29575e">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_ARC4
+: <a class="el" href="group__crypto__types.html#gae4d46e83f910dcaa126000a8ed03cde9">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_CAMELLIA
+: <a class="el" href="group__crypto__types.html#gad8e5da742343fd5519f9d8a630c2ed81">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_DERIVE
+: <a class="el" href="group__crypto__types.html#gae871b2357b8593f33bfd51abbf93ebb1">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_DES
+: <a class="el" href="group__crypto__types.html#ga577562bfbbc691c820d55ec308333138">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_DSA_KEYPAIR
+: <a class="el" href="group__crypto__types.html#ga011010ee28c20388f3d89fb27088ed62">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_DSA_PUBLIC_KEY
+: <a class="el" href="group__crypto__types.html#ga5e7439c2905136366c3a876e62e5ddfc">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_ECC_KEYPAIR
+: <a class="el" href="group__crypto__types.html#gadf3ad65d157bf5282849c954bf3f51af">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_ECC_PUBLIC_KEY
+: <a class="el" href="group__crypto__types.html#gad54c03d3b47020e571a72cd01d978cf2">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_GET_CURVE
+: <a class="el" href="group__crypto__types.html#ga0c567210e6f80aa8f2aa87efa7a3a3f9">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_HMAC
+: <a class="el" href="group__crypto__types.html#ga92d989f4ca64abd00f463defd773a6f8">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_ASYMMETRIC
+: <a class="el" href="group__crypto__types.html#gab138ae2ebf2905dfbaf4154db2620939">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_ECC
+: <a class="el" href="group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_KEYPAIR
+: <a class="el" href="group__crypto__types.html#gac14c6d6e1b2b7f4a92a7b757465cff29">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_PUBLIC_KEY
+: <a class="el" href="group__crypto__types.html#gac674a0f059bc0cb72b47f0c517b4f45b">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_RSA
+: <a class="el" href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_IS_VENDOR_DEFINED
+: <a class="el" href="group__crypto__types.html#gadbe4c086a6562aefe344bc79e51bdfd3">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY
+: <a class="el" href="group__crypto__types.html#gaf09f1ca1de6a7e7cff0fe516f3f6c91d">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_NONE
+: <a class="el" href="group__crypto__types.html#gafce7ab2b54ce97ea5bff73f13a9f3e5b">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR
+: <a class="el" href="group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_RAW_DATA
+: <a class="el" href="group__crypto__types.html#gaa97f92025533102616b32d571c940d80">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_RSA_KEYPAIR
+: <a class="el" href="group__crypto__types.html#ga581f50687f5d650456925278948f2799">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_RSA_PUBLIC_KEY
+: <a class="el" href="group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b">crypto.h</a>
+</li>
+<li>PSA_KEY_TYPE_VENDOR_FLAG
+: <a class="el" href="group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_DECRYPT
+: <a class="el" href="group__policy.html#gac3f2d2e5983db1edde9f142ca9bf8e6a">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_DERIVE
+: <a class="el" href="group__policy.html#gaf19022acc5ef23cf12477f632b48a0b2">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_ENCRYPT
+: <a class="el" href="group__policy.html#ga75153b296d045d529d97203a6a995dad">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_EXPORT
+: <a class="el" href="group__policy.html#ga7dddccdd1303176e87a4d20c87b589ed">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_SIGN
+: <a class="el" href="group__policy.html#ga99b9f456cf59efc4b5579465407aef5a">crypto.h</a>
+</li>
+<li>PSA_KEY_USAGE_VERIFY
+: <a class="el" href="group__policy.html#ga39b54ffd5958b69634607924fa53cea6">crypto.h</a>
+</li>
+<li>PSA_MAC_FINAL_SIZE
+: <a class="el" href="crypto__sizes_8h.html#aa84c5fb384ac7cb1bfc52adde96588ee">crypto_sizes.h</a>
+</li>
+<li>PSA_MAC_MAX_SIZE
+: <a class="el" href="crypto__sizes_8h.html#a4681cc4f6226883a2160122c562ca682">crypto_sizes.h</a>
+</li>
+<li>PSA_SUCCESS
+: <a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">crypto.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/globals_func.html b/docs/html/globals_func.html
new file mode 100644
index 0000000..f5a367e
--- /dev/null
+++ b/docs/html/globals_func.html
@@ -0,0 +1,209 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+ 
+
+<h3><a id="index_p"></a>- p -</h3><ul>
+<li>psa_aead_decrypt()
+: <a class="el" href="group__aead.html#ga5b88ad2cfbf2e98039858416fa3ebd7a">crypto.h</a>
+</li>
+<li>psa_aead_encrypt()
+: <a class="el" href="group__aead.html#ga14e4068a3d328515a4884f3037904d54">crypto.h</a>
+</li>
+<li>psa_asymmetric_decrypt()
+: <a class="el" href="group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6">crypto.h</a>
+</li>
+<li>psa_asymmetric_encrypt()
+: <a class="el" href="group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2">crypto.h</a>
+</li>
+<li>psa_asymmetric_sign()
+: <a class="el" href="group__asymmetric.html#ga48091460d1ead078d93caa3611aec976">crypto.h</a>
+</li>
+<li>psa_asymmetric_verify()
+: <a class="el" href="group__asymmetric.html#gaee3e92946c1c4b3dfa90879e2f7d1321">crypto.h</a>
+</li>
+<li>psa_cipher_abort()
+: <a class="el" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">crypto.h</a>
+</li>
+<li>psa_cipher_decrypt_setup()
+: <a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">crypto.h</a>
+</li>
+<li>psa_cipher_encrypt_setup()
+: <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">crypto.h</a>
+</li>
+<li>psa_cipher_finish()
+: <a class="el" href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">crypto.h</a>
+</li>
+<li>psa_cipher_generate_iv()
+: <a class="el" href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">crypto.h</a>
+</li>
+<li>psa_cipher_set_iv()
+: <a class="el" href="group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42">crypto.h</a>
+</li>
+<li>psa_cipher_update()
+: <a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">crypto.h</a>
+</li>
+<li>psa_crypto_init()
+: <a class="el" href="group__basic.html#ga2de150803fc2f7dc6101d5af7e921dd9">crypto.h</a>
+</li>
+<li>psa_destroy_key()
+: <a class="el" href="group__key__management.html#ga2e9a60a9525ce6b3082a72df2080f0c5">crypto.h</a>
+</li>
+<li>psa_export_key()
+: <a class="el" href="group__key__management.html#gaa67bc459b20028b268f3d75a05afe022">crypto.h</a>
+</li>
+<li>psa_export_public_key()
+: <a class="el" href="group__key__management.html#ga7355b38f8eb9330db2786604f4a83a3b">crypto.h</a>
+</li>
+<li>psa_generate_key()
+: <a class="el" href="group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10">crypto.h</a>
+</li>
+<li>psa_generate_random()
+: <a class="el" href="group__random.html#ga1985eae417dfbccedf50d5fff54ea8c5">crypto.h</a>
+</li>
+<li>psa_generator_abort()
+: <a class="el" href="group__generators.html#ga563ca64537d90368899286b36d8cf7f3">crypto.h</a>
+</li>
+<li>psa_generator_import_key()
+: <a class="el" href="group__generators.html#ga06c1ba3d989827d909b4b01ffe983beb">crypto.h</a>
+</li>
+<li>psa_generator_read()
+: <a class="el" href="group__generators.html#gab5712ad29b78c2b170e64cc5bcfc1bce">crypto.h</a>
+</li>
+<li>psa_get_generator_capacity()
+: <a class="el" href="group__generators.html#ga7453491e3b440193be2c5dccc2040fd2">crypto.h</a>
+</li>
+<li>psa_get_key_information()
+: <a class="el" href="group__key__management.html#gaf105167657ab1d484cb4a51f93413717">crypto.h</a>
+</li>
+<li>psa_get_key_lifetime()
+: <a class="el" href="group__persistence.html#gaf0daaa1dba14dc324ca83dfe1495a5e2">crypto.h</a>
+</li>
+<li>psa_get_key_policy()
+: <a class="el" href="group__policy.html#ga613f28712124f9149bd640614376ab5a">crypto.h</a>
+</li>
+<li>psa_hash_abort()
+: <a class="el" href="group__hash.html#gab0b4d5f9912a615559497a467b532928">crypto.h</a>
+</li>
+<li>psa_hash_finish()
+: <a class="el" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">crypto.h</a>
+</li>
+<li>psa_hash_setup()
+: <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">crypto.h</a>
+</li>
+<li>psa_hash_update()
+: <a class="el" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">crypto.h</a>
+</li>
+<li>psa_hash_verify()
+: <a class="el" href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">crypto.h</a>
+</li>
+<li>psa_import_key()
+: <a class="el" href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5">crypto.h</a>
+</li>
+<li>psa_key_derivation()
+: <a class="el" href="group__derivation.html#ga1b6429f443a45e5f3209043abbbe8315">crypto.h</a>
+</li>
+<li>psa_key_policy_get_algorithm()
+: <a class="el" href="group__policy.html#gaadf16b89ace53e1d2cb5bcb0aef24c86">crypto.h</a>
+</li>
+<li>psa_key_policy_get_usage()
+: <a class="el" href="group__policy.html#ga7746662b7503e484774d0ecb5d8ac2ab">crypto.h</a>
+</li>
+<li>psa_key_policy_init()
+: <a class="el" href="group__policy.html#gad49eb85e3fcbe70f763f511ac83e762e">crypto.h</a>
+</li>
+<li>psa_key_policy_set_usage()
+: <a class="el" href="group__policy.html#gac16792fd6d375a5f76d372090df40607">crypto.h</a>
+</li>
+<li>psa_mac_abort()
+: <a class="el" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">crypto.h</a>
+</li>
+<li>psa_mac_sign_finish()
+: <a class="el" href="group__MAC.html#gac22bc0125580c96724a09226cfbc97f2">crypto.h</a>
+</li>
+<li>psa_mac_sign_setup()
+: <a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">crypto.h</a>
+</li>
+<li>psa_mac_update()
+: <a class="el" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">crypto.h</a>
+</li>
+<li>psa_mac_verify_finish()
+: <a class="el" href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">crypto.h</a>
+</li>
+<li>psa_mac_verify_setup()
+: <a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">crypto.h</a>
+</li>
+<li>psa_set_key_lifetime()
+: <a class="el" href="group__persistence.html#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8">crypto.h</a>
+</li>
+<li>psa_set_key_policy()
+: <a class="el" href="group__policy.html#gad7faa7e64aa771f7441c44ceff21af19">crypto.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/globals_type.html b/docs/html/globals_type.html
new file mode 100644
index 0000000..baf1afa
--- /dev/null
+++ b/docs/html/globals_type.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+ <ul>
+<li>psa_algorithm_t
+: <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">crypto.h</a>
+</li>
+<li>psa_cipher_operation_t
+: <a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">crypto.h</a>
+</li>
+<li>psa_crypto_generator_t
+: <a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">crypto.h</a>
+</li>
+<li>psa_ecc_curve_t
+: <a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">crypto.h</a>
+</li>
+<li>psa_hash_operation_t
+: <a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">crypto.h</a>
+</li>
+<li>psa_key_lifetime_t
+: <a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">crypto.h</a>
+</li>
+<li>psa_key_policy_t
+: <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">crypto.h</a>
+</li>
+<li>psa_key_slot_t
+: <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">crypto.h</a>
+</li>
+<li>psa_key_type_t
+: <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">crypto.h</a>
+</li>
+<li>psa_key_usage_t
+: <a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">crypto.h</a>
+</li>
+<li>psa_mac_operation_t
+: <a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">crypto.h</a>
+</li>
+<li>psa_status_t
+: <a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">crypto.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/graph_legend.html b/docs/html/graph_legend.html
new file mode 100644
index 0000000..1efcfdc
--- /dev/null
+++ b/docs/html/graph_legend.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Graph Legend</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">Graph Legend</div> </div>
+</div><!--header-->
+<div class="contents">
+<p>This page explains how to interpret the graphs that are generated by doxygen.</p>
+<p>Consider the following example: </p><div class="fragment"><div class="line">/*! Invisible class because of truncation */</div><div class="line">class Invisible { };</div><div class="line"></div><div class="line">/*! Truncated class, inheritance relation is hidden */</div><div class="line">class Truncated : public Invisible { };</div><div class="line"></div><div class="line">/* Class not documented with doxygen comments */</div><div class="line">class Undocumented { };</div><div class="line"></div><div class="line">/*! Class that is inherited using public inheritance */</div><div class="line">class PublicBase : public Truncated { };</div><div class="line"></div><div class="line">/*! A template class */</div><div class="line">template<class T> class Templ { };</div><div class="line"></div><div class="line">/*! Class that is inherited using protected inheritance */</div><div class="line">class ProtectedBase { };</div><div class="line"></div><div class="line">/*! Class that is inherited using private inheritance */</div><div class="line">class PrivateBase { };</div><div class="line"></div><div class="line">/*! Class that is used by the Inherited class */</div><div class="line">class Used { };</div><div class="line"></div><div class="line">/*! Super class that inherits a number of other classes */</div><div class="line">class Inherited : public PublicBase,</div><div class="line"> protected ProtectedBase,</div><div class="line"> private PrivateBase,</div><div class="line"> public Undocumented,</div><div class="line"> public Templ<int></div><div class="line">{</div><div class="line"> private:</div><div class="line"> Used *m_usedClass;</div><div class="line">};</div></div><!-- fragment --><p> This will result in the following graph:</p>
+<center><div class="image">
+<img src="graph_legend.png"/>
+</div>
+</center><p>The boxes in the above graph have the following meaning: </p>
+<ul>
+<li>
+A filled gray box represents the struct or class for which the graph is generated. </li>
+<li>
+A box with a black border denotes a documented struct or class. </li>
+<li>
+A box with a gray border denotes an undocumented struct or class. </li>
+<li>
+A box with a red border denotes a documented struct or class forwhich not all inheritance/containment relations are shown. A graph is truncated if it does not fit within the specified boundaries. </li>
+</ul>
+<p>The arrows have the following meaning: </p>
+<ul>
+<li>
+A dark blue arrow is used to visualize a public inheritance relation between two classes. </li>
+<li>
+A dark green arrow is used for protected inheritance. </li>
+<li>
+A dark red arrow is used for private inheritance. </li>
+<li>
+A purple dashed arrow is used if a class is contained or used by another class. The arrow is labelled with the variable(s) through which the pointed class or struct is accessible. </li>
+<li>
+A yellow dashed arrow denotes a relation between a template instance and the template class it was instantiated from. The arrow is labelled with the template parameters of the instance. </li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/graph_legend.md5 b/docs/html/graph_legend.md5
new file mode 100644
index 0000000..a06ed05
--- /dev/null
+++ b/docs/html/graph_legend.md5
@@ -0,0 +1 @@
+387ff8eb65306fa251338d3c9bd7bfff
\ No newline at end of file
diff --git a/docs/html/graph_legend.png b/docs/html/graph_legend.png
new file mode 100644
index 0000000..81788d8
--- /dev/null
+++ b/docs/html/graph_legend.png
Binary files differ
diff --git a/docs/html/group__MAC.html b/docs/html/group__MAC.html
new file mode 100644
index 0000000..beecdc5
--- /dev/null
+++ b/docs/html/group__MAC.html
@@ -0,0 +1,476 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Message authentication codes</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Message authentication codes</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ga78f0838b0c4e3db28b26355624d4bd37"><td class="memItemLeft" align="right" valign="top">typedef struct psa_mac_operation_s </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a></td></tr>
+<tr class="separator:ga78f0838b0c4e3db28b26355624d4bd37"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga68ac2ad3253e9e27fcfbc788a4df8177"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation, <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="separator:ga68ac2ad3253e9e27fcfbc788a4df8177"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac7d1c3d075ce1604a54cbbc9933fa39d"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation, <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="separator:gac7d1c3d075ce1604a54cbbc9933fa39d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5560af371497babefe03c9da4e8a1c05"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">psa_mac_update</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation, const uint8_t *input, size_t input_length)</td></tr>
+<tr class="separator:ga5560af371497babefe03c9da4e8a1c05"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac22bc0125580c96724a09226cfbc97f2"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#gac22bc0125580c96724a09226cfbc97f2">psa_mac_sign_finish</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation, uint8_t *mac, size_t mac_size, size_t *mac_length)</td></tr>
+<tr class="separator:gac22bc0125580c96724a09226cfbc97f2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac92b2930d6728e1be4d011c05d485822"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">psa_mac_verify_finish</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation, const uint8_t *mac, size_t mac_length)</td></tr>
+<tr class="separator:gac92b2930d6728e1be4d011c05d485822"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gacd8dd54855ba1bc0a03f104f252884fd"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">psa_mac_abort</a> (<a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> *operation)</td></tr>
+<tr class="separator:gacd8dd54855ba1bc0a03f104f252884fd"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="ga78f0838b0c4e3db28b26355624d4bd37"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga78f0838b0c4e3db28b26355624d4bd37">◆ </a></span>psa_mac_operation_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef struct psa_mac_operation_s <a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The type of the state data structure for multipart MAC operations.</p>
+<p>This is an implementation-defined <code>struct</code>. Applications should not make any assumptions about the content of this structure except as directed by the documentation of a specific implementation. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="gacd8dd54855ba1bc0a03f104f252884fd"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gacd8dd54855ba1bc0a03f104f252884fd">◆ </a></span>psa_mac_abort()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_mac_abort </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Abort a MAC operation.</p>
+<p>Aborting an operation frees all associated resources except for the <code>operation</code> structure itself. Once aborted, the operation object can be reused for another operation by calling <a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup()</a> or <a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup()</a> again.</p>
+<p>You may call this function any time after the operation object has been initialized by any of the following methods:</p><ul>
+<li>A call to <a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup()</a> or <a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup()</a>, whether it succeeds or not.</li>
+<li>Initializing the <code>struct</code> to all-bits-zero.</li>
+<li>Initializing the <code>struct</code> to logical zeros, e.g. <code>psa_mac_operation_t operation = {0}</code>.</li>
+</ul>
+<p>In particular, calling <a class="el" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">psa_mac_abort()</a> after the operation has been terminated by a call to <a class="el" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">psa_mac_abort()</a>, <a class="el" href="group__MAC.html#gac22bc0125580c96724a09226cfbc97f2">psa_mac_sign_finish()</a> or <a class="el" href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">psa_mac_verify_finish()</a> is safe and has no effect.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Initialized MAC operation.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td><code>operation</code> is not an active MAC operation. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gac22bc0125580c96724a09226cfbc97f2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac22bc0125580c96724a09226cfbc97f2">◆ </a></span>psa_mac_sign_finish()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_mac_sign_finish </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>mac</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>mac_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>mac_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Finish the calculation of the MAC of a message.</p>
+<p>The application must call <a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup()</a> before calling this function. This function calculates the MAC of the message formed by concatenating the inputs passed to preceding calls to <a class="el" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">psa_mac_update()</a>.</p>
+<p>When this function returns, the operation becomes inactive.</p>
+<dl class="section warning"><dt>Warning</dt><dd>Applications should not call this function if they expect a specific value for the MAC. Call <a class="el" href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">psa_mac_verify_finish()</a> instead. Beware that comparing integrity or authenticity data such as MAC values with a function such as <code>memcmp</code> is risky because the time taken by the comparison may leak information about the MAC value which could allow an attacker to guess a valid MAC and thereby bypass security controls.</dd></dl>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Active MAC operation. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">mac</td><td>Buffer where the MAC value is to be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">mac_size</td><td>Size of the <code>mac</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">mac_length</td><td>On success, the number of bytes that make up the MAC value. This is always <a class="el" href="crypto__sizes_8h.html#aa84c5fb384ac7cb1bfc52adde96588ee">PSA_MAC_FINAL_SIZE</a>(<code>key_type</code>, <code>key_bits</code>, <code>alg</code>) where <code>key_type</code> and <code>key_bits</code> are the type and bit-size respectively of the key and <code>alg</code> is the MAC algorithm that is calculated.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td>The operation state is not valid (not started, or already completed). </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a></td><td>The size of the <code>mac</code> buffer is too small. You can determine a sufficient buffer size by calling <a class="el" href="crypto__sizes_8h.html#aa84c5fb384ac7cb1bfc52adde96588ee">PSA_MAC_FINAL_SIZE()</a>. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga68ac2ad3253e9e27fcfbc788a4df8177"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga68ac2ad3253e9e27fcfbc788a4df8177">◆ </a></span>psa_mac_sign_setup()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_mac_sign_setup </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Start a multipart MAC calculation operation.</p>
+<p>This function sets up the calculation of the MAC (message authentication code) of a byte string. To verify the MAC of a message against an expected value, use <a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup()</a> instead.</p>
+<p>The sequence of operations to calculate a MAC is as follows:</p><ol type="1">
+<li>Allocate an operation object which will be passed to all the functions listed here.</li>
+<li>Call <a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup()</a> to specify the algorithm and key. The key remains associated with the operation even if the content of the key slot changes.</li>
+<li>Call <a class="el" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">psa_mac_update()</a> zero, one or more times, passing a fragment of the message each time. The MAC that is calculated is the MAC of the concatenation of these messages in order.</li>
+<li>At the end of the message, call <a class="el" href="group__MAC.html#gac22bc0125580c96724a09226cfbc97f2">psa_mac_sign_finish()</a> to finish calculating the MAC value and retrieve it.</li>
+</ol>
+<p>The application may call <a class="el" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">psa_mac_abort()</a> at any time after the operation has been initialized with <a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup()</a>.</p>
+<p>After a successful call to <a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup()</a>, the application must eventually terminate the operation through one of the following methods:</p><ul>
+<li>A failed call to <a class="el" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">psa_mac_update()</a>.</li>
+<li>A call to <a class="el" href="group__MAC.html#gac22bc0125580c96724a09226cfbc97f2">psa_mac_sign_finish()</a> or <a class="el" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">psa_mac_abort()</a>.</li>
+</ul>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[out]</td><td class="paramname">operation</td><td>The operation object to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot containing the key to use for the operation. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>The MAC algorithm to compute (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gaca7aee4c9dde316b3b1a150a26eab776">PSA_ALG_IS_MAC(alg)</a> is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td><code>key</code> is not compatible with <code>alg</code>. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td><code>alg</code> is not supported or is not a MAC algorithm. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga5560af371497babefe03c9da4e8a1c05"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga5560af371497babefe03c9da4e8a1c05">◆ </a></span>psa_mac_update()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_mac_update </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>input</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>input_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Add a message fragment to a multipart MAC operation.</p>
+<p>The application must call <a class="el" href="group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177">psa_mac_sign_setup()</a> or <a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup()</a> before calling this function.</p>
+<p>If this function returns an error status, the operation becomes inactive.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Active MAC operation. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">input</td><td>Buffer containing the message fragment to add to the MAC calculation. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">input_length</td><td>Size of the <code>input</code> buffer in bytes.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td>The operation state is not valid (not started, or already completed). </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gac92b2930d6728e1be4d011c05d485822"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac92b2930d6728e1be4d011c05d485822">◆ </a></span>psa_mac_verify_finish()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_mac_verify_finish </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>mac</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>mac_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Finish the calculation of the MAC of a message and compare it with an expected value.</p>
+<p>The application must call <a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup()</a> before calling this function. This function calculates the MAC of the message formed by concatenating the inputs passed to preceding calls to <a class="el" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">psa_mac_update()</a>. It then compares the calculated MAC with the expected MAC passed as a parameter to this function.</p>
+<p>When this function returns, the operation becomes inactive.</p>
+<dl class="section note"><dt>Note</dt><dd>Implementations shall make the best effort to ensure that the comparison between the actual MAC and the expected MAC is performed in constant time.</dd></dl>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Active MAC operation. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">mac</td><td>Buffer containing the expected MAC value. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">mac_length</td><td>Size of the <code>mac</code> buffer in bytes.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>The expected MAC is identical to the actual MAC of the message. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga35927f755d232c4766de600f2c49e9f2">PSA_ERROR_INVALID_SIGNATURE</a></td><td>The MAC of the message was calculated successfully, but it differs from the expected MAC. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td>The operation state is not valid (not started, or already completed). </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gac7d1c3d075ce1604a54cbbc9933fa39d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac7d1c3d075ce1604a54cbbc9933fa39d">◆ </a></span>psa_mac_verify_setup()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_mac_verify_setup </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37">psa_mac_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Start a multipart MAC verification operation.</p>
+<p>This function sets up the verification of the MAC (message authentication code) of a byte string against an expected value.</p>
+<p>The sequence of operations to verify a MAC is as follows:</p><ol type="1">
+<li>Allocate an operation object which will be passed to all the functions listed here.</li>
+<li>Call <a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup()</a> to specify the algorithm and key. The key remains associated with the operation even if the content of the key slot changes.</li>
+<li>Call <a class="el" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">psa_mac_update()</a> zero, one or more times, passing a fragment of the message each time. The MAC that is calculated is the MAC of the concatenation of these messages in order.</li>
+<li>At the end of the message, call <a class="el" href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">psa_mac_verify_finish()</a> to finish calculating the actual MAC of the message and verify it against the expected value.</li>
+</ol>
+<p>The application may call <a class="el" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">psa_mac_abort()</a> at any time after the operation has been initialized with <a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup()</a>.</p>
+<p>After a successful call to <a class="el" href="group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d">psa_mac_verify_setup()</a>, the application must eventually terminate the operation through one of the following methods:</p><ul>
+<li>A failed call to <a class="el" href="group__MAC.html#ga5560af371497babefe03c9da4e8a1c05">psa_mac_update()</a>.</li>
+<li>A call to <a class="el" href="group__MAC.html#gac92b2930d6728e1be4d011c05d485822">psa_mac_verify_finish()</a> or <a class="el" href="group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd">psa_mac_abort()</a>.</li>
+</ul>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[out]</td><td class="paramname">operation</td><td>The operation object to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot containing the key to use for the operation. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>The MAC algorithm to compute (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gaca7aee4c9dde316b3b1a150a26eab776">PSA_ALG_IS_MAC</a>(<code>alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td><code>key</code> is not compatible with <code>alg</code>. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td><code>alg</code> is not supported or is not a MAC algorithm. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__aead.html b/docs/html/group__aead.html
new file mode 100644
index 0000000..487b5e6
--- /dev/null
+++ b/docs/html/group__aead.html
@@ -0,0 +1,346 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Authenticated encryption with associated data (AEAD)</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#define-members">Macros</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Authenticated encryption with associated data (AEAD)</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ga337ef01fe3c9f71d62ccced33e8917f4"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4">PSA_AEAD_TAG_SIZE</a>(alg)</td></tr>
+<tr class="separator:ga337ef01fe3c9f71d62ccced33e8917f4"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga14e4068a3d328515a4884f3037904d54"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__aead.html#ga14e4068a3d328515a4884f3037904d54">psa_aead_encrypt</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)</td></tr>
+<tr class="separator:ga14e4068a3d328515a4884f3037904d54"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5b88ad2cfbf2e98039858416fa3ebd7a"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__aead.html#ga5b88ad2cfbf2e98039858416fa3ebd7a">psa_aead_decrypt</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)</td></tr>
+<tr class="separator:ga5b88ad2cfbf2e98039858416fa3ebd7a"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="ga337ef01fe3c9f71d62ccced33e8917f4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga337ef01fe3c9f71d62ccced33e8917f4">◆ </a></span>PSA_AEAD_TAG_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_AEAD_TAG_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">((alg) == PSA_ALG_GCM ? 16 : \</div><div class="line"> (alg) == PSA_ALG_CCM ? 16 : \</div><div class="line"> 0)</div></div><!-- fragment --><p>The tag size for an AEAD algorithm, in bytes.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An AEAD algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8">PSA_ALG_IS_AEAD</a>(<code>alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The tag size for the specified algorithm. If the AEAD algorithm does not have an identified tag that can be distinguished from the rest of the ciphertext, return 0. If the AEAD algorithm is not recognized, return 0. An implementation may return either 0 or a correct size for an AEAD algorithm that it recognizes, but does not support. </dd></dl>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga5b88ad2cfbf2e98039858416fa3ebd7a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga5b88ad2cfbf2e98039858416fa3ebd7a">◆ </a></span>psa_aead_decrypt()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_aead_decrypt </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>nonce</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>nonce_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>additional_data</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>additional_data_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>ciphertext</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>ciphertext_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>plaintext</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>plaintext_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>plaintext_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Process an authenticated decryption operation.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot containing the key to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>The AEAD algorithm to compute (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8">PSA_ALG_IS_AEAD</a>(<code>alg</code>) is true). </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">nonce</td><td>Nonce or IV to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">nonce_length</td><td>Size of the <code>nonce</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">additional_data</td><td>Additional data that has been authenticated but not encrypted. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">additional_data_length</td><td>Size of <code>additional_data</code> in bytes. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">ciphertext</td><td>Data that has been authenticated and encrypted. For algorithms where the encrypted data and the authentication tag are defined as separate inputs, the buffer must contain the encrypted data followed by the authentication tag. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">ciphertext_length</td><td>Size of <code>ciphertext</code> in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">plaintext</td><td>Output buffer for the decrypted data. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">plaintext_size</td><td>Size of the <code>plaintext</code> buffer in bytes. This must be at least <a class="el" href="crypto__sizes_8h.html#a1d057796166c16eb673ad1997e48a60b">PSA_AEAD_DECRYPT_OUTPUT_SIZE</a>(<code>alg</code>, <code>ciphertext_length</code>). </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">plaintext_length</td><td>On success, the size of the output in the <b>plaintext</b> buffer.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga35927f755d232c4766de600f2c49e9f2">PSA_ERROR_INVALID_SIGNATURE</a></td><td>The ciphertext is not authentic. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td><code>key</code> is not compatible with <code>alg</code>. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td><code>alg</code> is not supported or is not an AEAD algorithm. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga14e4068a3d328515a4884f3037904d54"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga14e4068a3d328515a4884f3037904d54">◆ </a></span>psa_aead_encrypt()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_aead_encrypt </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>nonce</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>nonce_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>additional_data</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>additional_data_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>plaintext</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>plaintext_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>ciphertext</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>ciphertext_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>ciphertext_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Process an authenticated encryption operation.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot containing the key to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>The AEAD algorithm to compute (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8">PSA_ALG_IS_AEAD</a>(<code>alg</code>) is true). </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">nonce</td><td>Nonce or IV to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">nonce_length</td><td>Size of the <code>nonce</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">additional_data</td><td>Additional data that will be authenticated but not encrypted. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">additional_data_length</td><td>Size of <code>additional_data</code> in bytes. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">plaintext</td><td>Data that will be authenticated and encrypted. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">plaintext_length</td><td>Size of <code>plaintext</code> in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">ciphertext</td><td>Output buffer for the authenticated and encrypted data. The additional data is not part of this output. For algorithms where the encrypted data and the authentication tag are defined as separate outputs, the authentication tag is appended to the encrypted data. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">ciphertext_size</td><td>Size of the <code>ciphertext</code> buffer in bytes. This must be at least <a class="el" href="crypto__sizes_8h.html#a85667d47a7aa6c7b99a80e5273671266">PSA_AEAD_ENCRYPT_OUTPUT_SIZE</a>(<code>alg</code>, <code>plaintext_length</code>). </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">ciphertext_length</td><td>On success, the size of the output in the <b>ciphertext</b> buffer.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td><code>key</code> is not compatible with <code>alg</code>. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td><code>alg</code> is not supported or is not an AEAD algorithm. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__asymmetric.html b/docs/html/group__asymmetric.html
new file mode 100644
index 0000000..858d7b1
--- /dev/null
+++ b/docs/html/group__asymmetric.html
@@ -0,0 +1,533 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Asymmetric cryptography</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#define-members">Macros</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Asymmetric cryptography</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ga10c472a35f04051add6b20cc228ffc11"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__asymmetric.html#ga10c472a35f04051add6b20cc228ffc11">PSA_ECDSA_SIGNATURE_SIZE</a>(curve_bits)   (PSA_BITS_TO_BYTES(curve_bits) * 2)</td></tr>
+<tr class="memdesc:ga10c472a35f04051add6b20cc228ffc11"><td class="mdescLeft"> </td><td class="mdescRight">ECDSA signature size for a given curve bit size. <a href="#ga10c472a35f04051add6b20cc228ffc11">More...</a><br /></td></tr>
+<tr class="separator:ga10c472a35f04051add6b20cc228ffc11"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaec0bcba60e7514b83f967b171d494ed3"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_RSA_MINIMUM_PADDING_SIZE</b>(alg)</td></tr>
+<tr class="separator:gaec0bcba60e7514b83f967b171d494ed3"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga48091460d1ead078d93caa3611aec976"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__asymmetric.html#ga48091460d1ead078d93caa3611aec976">psa_asymmetric_sign</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length)</td></tr>
+<tr class="memdesc:ga48091460d1ead078d93caa3611aec976"><td class="mdescLeft"> </td><td class="mdescRight">Sign a hash or short message with a private key. <a href="#ga48091460d1ead078d93caa3611aec976">More...</a><br /></td></tr>
+<tr class="separator:ga48091460d1ead078d93caa3611aec976"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaee3e92946c1c4b3dfa90879e2f7d1321"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__asymmetric.html#gaee3e92946c1c4b3dfa90879e2f7d1321">psa_asymmetric_verify</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length)</td></tr>
+<tr class="memdesc:gaee3e92946c1c4b3dfa90879e2f7d1321"><td class="mdescLeft"> </td><td class="mdescRight">Verify the signature a hash or short message using a public key. <a href="#gaee3e92946c1c4b3dfa90879e2f7d1321">More...</a><br /></td></tr>
+<tr class="separator:gaee3e92946c1c4b3dfa90879e2f7d1321"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3c0ba402bac217d623dba8320c2240c2"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2">psa_asymmetric_encrypt</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length)</td></tr>
+<tr class="memdesc:ga3c0ba402bac217d623dba8320c2240c2"><td class="mdescLeft"> </td><td class="mdescRight">Encrypt a short message with a public key. <a href="#ga3c0ba402bac217d623dba8320c2240c2">More...</a><br /></td></tr>
+<tr class="separator:ga3c0ba402bac217d623dba8320c2240c2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3094be979f37aa2865c283167ba907e6"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6">psa_asymmetric_decrypt</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length)</td></tr>
+<tr class="memdesc:ga3094be979f37aa2865c283167ba907e6"><td class="mdescLeft"> </td><td class="mdescRight">Decrypt a short message with a private key. <a href="#ga3094be979f37aa2865c283167ba907e6">More...</a><br /></td></tr>
+<tr class="separator:ga3094be979f37aa2865c283167ba907e6"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="ga10c472a35f04051add6b20cc228ffc11"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga10c472a35f04051add6b20cc228ffc11">◆ </a></span>PSA_ECDSA_SIGNATURE_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ECDSA_SIGNATURE_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">curve_bits</td><td>)</td>
+ <td>   (PSA_BITS_TO_BYTES(curve_bits) * 2)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>ECDSA signature size for a given curve bit size. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">curve_bits</td><td>Curve size in bits. </td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>Signature size in bytes.</dd></dl>
+<dl class="section note"><dt>Note</dt><dd>This macro returns a compile-time constant if its argument is one. </dd></dl>
+
+</div>
+</div>
+<a id="gaec0bcba60e7514b83f967b171d494ed3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaec0bcba60e7514b83f967b171d494ed3">◆ </a></span>PSA_RSA_MINIMUM_PADDING_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_RSA_MINIMUM_PADDING_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(PSA_ALG_IS_RSA_OAEP(alg) ? \</div><div class="line"> 2 * PSA_HASH_FINAL_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \</div><div class="line"> 11 <span class="comment">/*PKCS#1v1.5*/</span>)</div></div><!-- fragment -->
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga3094be979f37aa2865c283167ba907e6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3094be979f37aa2865c283167ba907e6">◆ </a></span>psa_asymmetric_decrypt()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_asymmetric_decrypt </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>input</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>input_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>salt</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>salt_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>output</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>output_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>output_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Decrypt a short message with a private key. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Key slot containing an asymmetric key pair. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>An asymmetric encryption algorithm that is compatible with the type of <code>key</code>. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">input</td><td>The message to decrypt. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">input_length</td><td>Size of the <code>input</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">salt</td><td>A salt or label, if supported by the encryption algorithm. If the algorithm does not support a salt, pass <code>NULL</code>. If the algorithm supports an optional salt and you do not want to pass a salt, pass <code>NULL</code>.</td></tr>
+ </table>
+ </dd>
+</dl>
+<ul>
+<li>For <a class="el" href="group__crypto__types.html#ga4c540d3abe43fb9abcb94f2bc51acef9">PSA_ALG_RSA_PKCS1V15_CRYPT</a>, no salt is supported. <dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">salt_length</td><td>Size of the <code>salt</code> buffer in bytes. If <code>salt</code> is <code>NULL</code>, pass 0. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">output</td><td>Buffer where the decrypted message is to be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">output_size</td><td>Size of the <code>output</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">output_length</td><td>On success, the number of bytes that make up the returned output.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a></td><td>The size of the <code>output</code> buffer is too small. You can determine a sufficient buffer size by calling <a class="el" href="crypto__sizes_8h.html#a61a246f3eac41989821d982e56fea6c1">PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE</a>(<code>key_type</code>, <code>key_bits</code>, <code>alg</code>) where <code>key_type</code> and <code>key_bits</code> are the type and bit-size respectively of <code>key</code>. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">PSA_ERROR_INSUFFICIENT_ENTROPY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gabe29594edbfb152cf153975b0597ac48">PSA_ERROR_INVALID_PADDING</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+</li>
+</ul>
+
+</div>
+</div>
+<a id="ga3c0ba402bac217d623dba8320c2240c2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3c0ba402bac217d623dba8320c2240c2">◆ </a></span>psa_asymmetric_encrypt()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_asymmetric_encrypt </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>input</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>input_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>salt</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>salt_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>output</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>output_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>output_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Encrypt a short message with a public key. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Key slot containing a public key or an asymmetric key pair. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>An asymmetric encryption algorithm that is compatible with the type of <code>key</code>. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">input</td><td>The message to encrypt. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">input_length</td><td>Size of the <code>input</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">salt</td><td>A salt or label, if supported by the encryption algorithm. If the algorithm does not support a salt, pass <code>NULL</code>. If the algorithm supports an optional salt and you do not want to pass a salt, pass <code>NULL</code>.</td></tr>
+ </table>
+ </dd>
+</dl>
+<ul>
+<li>For <a class="el" href="group__crypto__types.html#ga4c540d3abe43fb9abcb94f2bc51acef9">PSA_ALG_RSA_PKCS1V15_CRYPT</a>, no salt is supported. <dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">salt_length</td><td>Size of the <code>salt</code> buffer in bytes. If <code>salt</code> is <code>NULL</code>, pass 0. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">output</td><td>Buffer where the encrypted message is to be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">output_size</td><td>Size of the <code>output</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">output_length</td><td>On success, the number of bytes that make up the returned output.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a></td><td>The size of the <code>output</code> buffer is too small. You can determine a sufficient buffer size by calling <a class="el" href="crypto__sizes_8h.html#a66ba3bd93e5ec52870ccc3848778bad8">PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE</a>(<code>key_type</code>, <code>key_bits</code>, <code>alg</code>) where <code>key_type</code> and <code>key_bits</code> are the type and bit-size respectively of <code>key</code>. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">PSA_ERROR_INSUFFICIENT_ENTROPY</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+</li>
+</ul>
+
+</div>
+</div>
+<a id="ga48091460d1ead078d93caa3611aec976"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga48091460d1ead078d93caa3611aec976">◆ </a></span>psa_asymmetric_sign()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_asymmetric_sign </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>hash</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>hash_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>signature</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>signature_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>signature_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Sign a hash or short message with a private key. </p>
+<p>Note that to perform a hash-and-sign signature algorithm, you must first calculate the hash by calling <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup()</a>, <a class="el" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">psa_hash_update()</a> and <a class="el" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">psa_hash_finish()</a>. Then pass the resulting hash as the <code>hash</code> parameter to this function. You can use <a class="el" href="group__crypto__types.html#ga24cf6d7bcd2b9aeeeff86f07b6c674e3">PSA_ALG_SIGN_GET_HASH</a>(<code>alg</code>) to determine the hash algorithm to use.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Key slot containing an asymmetric key pair. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>A signature algorithm that is compatible with the type of <code>key</code>. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">hash</td><td>The hash or message to sign. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">hash_length</td><td>Size of the <code>hash</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">signature</td><td>Buffer where the signature is to be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">signature_size</td><td>Size of the <code>signature</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">signature_length</td><td>On success, the number of bytes that make up the returned signature value.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a></td><td>The size of the <code>signature</code> buffer is too small. You can determine a sufficient buffer size by calling <a class="el" href="crypto__sizes_8h.html#a77565b9b4fe6d8730fd2120f4c8378ab">PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE</a>(<code>key_type</code>, <code>key_bits</code>, <code>alg</code>) where <code>key_type</code> and <code>key_bits</code> are the type and bit-size respectively of <code>key</code>. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">PSA_ERROR_INSUFFICIENT_ENTROPY</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gaee3e92946c1c4b3dfa90879e2f7d1321"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaee3e92946c1c4b3dfa90879e2f7d1321">◆ </a></span>psa_asymmetric_verify()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_asymmetric_verify </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>hash</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>hash_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>signature</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>signature_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Verify the signature a hash or short message using a public key. </p>
+<p>Note that to perform a hash-and-sign signature algorithm, you must first calculate the hash by calling <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup()</a>, <a class="el" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">psa_hash_update()</a> and <a class="el" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">psa_hash_finish()</a>. Then pass the resulting hash as the <code>hash</code> parameter to this function. You can use <a class="el" href="group__crypto__types.html#ga24cf6d7bcd2b9aeeeff86f07b6c674e3">PSA_ALG_SIGN_GET_HASH</a>(<code>alg</code>) to determine the hash algorithm to use.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Key slot containing a public key or an asymmetric key pair. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>A signature algorithm that is compatible with the type of <code>key</code>. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">hash</td><td>The hash or message whose signature is to be verified. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">hash_length</td><td>Size of the <code>hash</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">signature</td><td>Buffer containing the signature to verify. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">signature_length</td><td>Size of the <code>signature</code> buffer in bytes.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>The signature is valid. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga35927f755d232c4766de600f2c49e9f2">PSA_ERROR_INVALID_SIGNATURE</a></td><td>The calculation was perfomed successfully, but the passed signature is not a valid signature. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__basic.html b/docs/html/group__basic.html
new file mode 100644
index 0000000..6c49260
--- /dev/null
+++ b/docs/html/group__basic.html
@@ -0,0 +1,509 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Basic definitions</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#define-members">Macros</a> |
+<a href="#typedef-members">Typedefs</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Basic definitions</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ga4cc859e2c66ca381c7418db3527a65e1"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)0)</td></tr>
+<tr class="separator:ga4cc859e2c66ca381c7418db3527a65e1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga24d5fdcdd759f846f79d9e581c63a83f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga24d5fdcdd759f846f79d9e581c63a83f">PSA_ERROR_UNKNOWN_ERROR</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)1)</td></tr>
+<tr class="separator:ga24d5fdcdd759f846f79d9e581c63a83f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1dcc6d130633ed5db8942257581b55dd"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)2)</td></tr>
+<tr class="separator:ga1dcc6d130633ed5db8942257581b55dd"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4d1b8dd8526177a15a210b7afc1accb1"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)3)</td></tr>
+<tr class="separator:ga4d1b8dd8526177a15a210b7afc1accb1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga695025f4ec11249aee7ea3d0f65e01c8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)4)</td></tr>
+<tr class="separator:ga695025f4ec11249aee7ea3d0f65e01c8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac2fee3a51249fbea45360aaa911f3e58"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#gac2fee3a51249fbea45360aaa911f3e58">PSA_ERROR_OCCUPIED_SLOT</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)5)</td></tr>
+<tr class="separator:gac2fee3a51249fbea45360aaa911f3e58"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaba00e3e6ceb2b12965a81e5ac02ae040"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)6)</td></tr>
+<tr class="separator:gaba00e3e6ceb2b12965a81e5ac02ae040"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga933d40fa2a591004f2e93aa91e11db84"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)7)</td></tr>
+<tr class="separator:ga933d40fa2a591004f2e93aa91e11db84"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga798df25a505ebf931f7bec1f80f1f85f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)8)</td></tr>
+<tr class="separator:ga798df25a505ebf931f7bec1f80f1f85f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga91b2ad8a867517a2651f1b076c5216e5"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)9)</td></tr>
+<tr class="separator:ga91b2ad8a867517a2651f1b076c5216e5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga897a45eb206a6f6b7be7ffbe36f0d766"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga897a45eb206a6f6b7be7ffbe36f0d766">PSA_ERROR_INSUFFICIENT_STORAGE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)10)</td></tr>
+<tr class="separator:ga897a45eb206a6f6b7be7ffbe36f0d766"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5cdb6948371d49e916106249020ea3f7"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)11)</td></tr>
+<tr class="separator:ga5cdb6948371d49e916106249020ea3f7"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gadd169a1af2707862b95fb9df91dfc37d"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#gadd169a1af2707862b95fb9df91dfc37d">PSA_ERROR_STORAGE_FAILURE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)12)</td></tr>
+<tr class="separator:gadd169a1af2707862b95fb9df91dfc37d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga08b10e70fa5ff0b05c631d9f8f6b2c6b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)13)</td></tr>
+<tr class="separator:ga08b10e70fa5ff0b05c631d9f8f6b2c6b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2c5dda1485cb54f2385cb9c1279a7004"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)14)</td></tr>
+<tr class="separator:ga2c5dda1485cb54f2385cb9c1279a7004"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4deb59fec02297ec5d8b42178323f675"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">PSA_ERROR_INSUFFICIENT_ENTROPY</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)15)</td></tr>
+<tr class="separator:ga4deb59fec02297ec5d8b42178323f675"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga35927f755d232c4766de600f2c49e9f2"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga35927f755d232c4766de600f2c49e9f2">PSA_ERROR_INVALID_SIGNATURE</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)16)</td></tr>
+<tr class="separator:ga35927f755d232c4766de600f2c49e9f2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gabe29594edbfb152cf153975b0597ac48"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#gabe29594edbfb152cf153975b0597ac48">PSA_ERROR_INVALID_PADDING</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)17)</td></tr>
+<tr class="separator:gabe29594edbfb152cf153975b0597ac48"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf1fa61f72e9e5b4a848c991bea495767"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#gaf1fa61f72e9e5b4a848c991bea495767">PSA_ERROR_INSUFFICIENT_CAPACITY</a>   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)18)</td></tr>
+<tr class="separator:gaf1fa61f72e9e5b4a848c991bea495767"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf2edfe992db358f8eefd4bc82d069592"><td class="memItemLeft" align="right" valign="top"><a id="gaf2edfe992db358f8eefd4bc82d069592"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_BITS_TO_BYTES</b>(bits)   (((bits) + 7) / 8)</td></tr>
+<tr class="separator:gaf2edfe992db358f8eefd4bc82d069592"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga997f71feb68cca794f7ed676600e06db"><td class="memItemLeft" align="right" valign="top"><a id="ga997f71feb68cca794f7ed676600e06db"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_BYTES_TO_BITS</b>(bytes)   ((bytes) * 8)</td></tr>
+<tr class="separator:ga997f71feb68cca794f7ed676600e06db"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ga05676e70ba5c6a7565aff3c36677c1f9"><td class="memItemLeft" align="right" valign="top">typedef int32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a></td></tr>
+<tr class="memdesc:ga05676e70ba5c6a7565aff3c36677c1f9"><td class="mdescLeft"> </td><td class="mdescRight">Function return status. <a href="#ga05676e70ba5c6a7565aff3c36677c1f9">More...</a><br /></td></tr>
+<tr class="separator:ga05676e70ba5c6a7565aff3c36677c1f9"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga2de150803fc2f7dc6101d5af7e921dd9"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__basic.html#ga2de150803fc2f7dc6101d5af7e921dd9">psa_crypto_init</a> (void)</td></tr>
+<tr class="memdesc:ga2de150803fc2f7dc6101d5af7e921dd9"><td class="mdescLeft"> </td><td class="mdescRight">Library initialization. <a href="#ga2de150803fc2f7dc6101d5af7e921dd9">More...</a><br /></td></tr>
+<tr class="separator:ga2de150803fc2f7dc6101d5af7e921dd9"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="ga933d40fa2a591004f2e93aa91e11db84"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga933d40fa2a591004f2e93aa91e11db84">◆ </a></span>PSA_ERROR_BAD_STATE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_BAD_STATE   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)7)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The requested action cannot be performed in the current state.</p>
+<p>Multipart operations return this error when one of the functions is called out of sequence. Refer to the function descriptions for permitted sequencing of functions.</p>
+<p>Implementations shall not return this error code to indicate that a key slot is occupied when it needs to be free or vice versa, but shall return <a class="el" href="group__basic.html#gac2fee3a51249fbea45360aaa911f3e58">PSA_ERROR_OCCUPIED_SLOT</a> or <a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a> as applicable. </p>
+
+</div>
+</div>
+<a id="ga695025f4ec11249aee7ea3d0f65e01c8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga695025f4ec11249aee7ea3d0f65e01c8">◆ </a></span>PSA_ERROR_BUFFER_TOO_SMALL</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_BUFFER_TOO_SMALL   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)4)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>An output buffer is too small.</p>
+<p>Applications can call the <code>PSA_xxx_SIZE</code> macro listed in the function description to determine a sufficient buffer size.</p>
+<p>Implementations should preferably return this error code only in cases when performing the operation with a larger output buffer would succeed. However implementations may return this error if a function has invalid or unsupported parameters in addition to the parameters that determine the necessary output buffer size. </p>
+
+</div>
+</div>
+<a id="ga5cdb6948371d49e916106249020ea3f7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga5cdb6948371d49e916106249020ea3f7">◆ </a></span>PSA_ERROR_COMMUNICATION_FAILURE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_COMMUNICATION_FAILURE   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)11)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>There was a communication failure inside the implementation.</p>
+<p>This can indicate a communication failure between the application and an external cryptoprocessor or between the cryptoprocessor and an external volatile or persistent memory. A communication failure may be transient or permanent depending on the cause.</p>
+<dl class="section warning"><dt>Warning</dt><dd>If a function returns this error, it is undetermined whether the requested action has completed or not. Implementations should return <a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a> on successful completion whenver possible, however functions may return <a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a> if the requested action was completed successfully in an external cryptoprocessor but there was a breakdown of communication before the cryptoprocessor could report the status to the application. </dd></dl>
+
+</div>
+</div>
+<a id="gaba00e3e6ceb2b12965a81e5ac02ae040"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaba00e3e6ceb2b12965a81e5ac02ae040">◆ </a></span>PSA_ERROR_EMPTY_SLOT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_EMPTY_SLOT   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)6)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>A slot is empty, but must be occupied to carry out the requested action.</p>
+<p>If the slot number is invalid (i.e. the requested action could not be performed even after creating appropriate content in the slot), implementations shall return <a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a> instead. </p>
+
+</div>
+</div>
+<a id="ga08b10e70fa5ff0b05c631d9f8f6b2c6b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">◆ </a></span>PSA_ERROR_HARDWARE_FAILURE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_HARDWARE_FAILURE   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)13)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>A hardware failure was detected.</p>
+<p>A hardware failure may be transient or permanent depending on the cause. </p>
+
+</div>
+</div>
+<a id="gaf1fa61f72e9e5b4a848c991bea495767"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf1fa61f72e9e5b4a848c991bea495767">◆ </a></span>PSA_ERROR_INSUFFICIENT_CAPACITY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_INSUFFICIENT_CAPACITY   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)18)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The generator has insufficient capacity left.</p>
+<p>Once a function returns this error, attempts to read from the generator will always return this error. </p>
+
+</div>
+</div>
+<a id="ga4deb59fec02297ec5d8b42178323f675"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4deb59fec02297ec5d8b42178323f675">◆ </a></span>PSA_ERROR_INSUFFICIENT_ENTROPY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_INSUFFICIENT_ENTROPY   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)15)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>There is not enough entropy to generate random data needed for the requested action.</p>
+<p>This error indicates a failure of a hardware random generator. Application writers should note that this error can be returned not only by functions whose purpose is to generate random data, such as key, IV or nonce generation, but also by functions that execute an algorithm with a randomized result, as well as functions that use randomization of intermediate computations as a countermeasure to certain attacks.</p>
+<p>Implementations should avoid returning this error after <a class="el" href="group__basic.html#ga2de150803fc2f7dc6101d5af7e921dd9" title="Library initialization. ">psa_crypto_init()</a> has succeeded. Implementations should generate sufficient entropy during initialization and subsequently use a cryptographically secure pseudorandom generator (PRNG). However implementations may return this error at any time if a policy requires the PRNG to be reseeded during normal operation. </p>
+
+</div>
+</div>
+<a id="ga91b2ad8a867517a2651f1b076c5216e5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga91b2ad8a867517a2651f1b076c5216e5">◆ </a></span>PSA_ERROR_INSUFFICIENT_MEMORY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_INSUFFICIENT_MEMORY   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)9)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>There is not enough runtime memory.</p>
+<p>If the action is carried out across multiple security realms, this error can refer to available memory in any of the security realms. </p>
+
+</div>
+</div>
+<a id="ga897a45eb206a6f6b7be7ffbe36f0d766"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga897a45eb206a6f6b7be7ffbe36f0d766">◆ </a></span>PSA_ERROR_INSUFFICIENT_STORAGE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_INSUFFICIENT_STORAGE   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)10)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>There is not enough persistent storage.</p>
+<p>Functions that modify the key storage return this error code if there is insufficient storage space on the host media. In addition, many functions that do not otherwise access storage may return this error code if the implementation requires a mandatory log entry for the requested action and the log storage space is full. </p>
+
+</div>
+</div>
+<a id="ga798df25a505ebf931f7bec1f80f1f85f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga798df25a505ebf931f7bec1f80f1f85f">◆ </a></span>PSA_ERROR_INVALID_ARGUMENT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_INVALID_ARGUMENT   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)8)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The parameters passed to the function are invalid.</p>
+<p>Implementations may return this error any time a parameter or combination of parameters are recognized as invalid.</p>
+<p>Implementations shall not return this error code to indicate that a key slot is occupied when it needs to be free or vice versa, but shall return <a class="el" href="group__basic.html#gac2fee3a51249fbea45360aaa911f3e58">PSA_ERROR_OCCUPIED_SLOT</a> or <a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a> as applicable. </p>
+
+</div>
+</div>
+<a id="gabe29594edbfb152cf153975b0597ac48"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gabe29594edbfb152cf153975b0597ac48">◆ </a></span>PSA_ERROR_INVALID_PADDING</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_INVALID_PADDING   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)17)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The decrypted padding is incorrect.</p>
+<dl class="section warning"><dt>Warning</dt><dd>In some protocols, when decrypting data, it is essential that the behavior of the application does not depend on whether the padding is correct, down to precise timing. Applications should prefer protocols that use authenticated encryption rather than plain encryption. If the application must perform a decryption of unauthenticated data, the application writer should take care not to reveal whether the padding is invalid.</dd></dl>
+<p>Implementations should strive to make valid and invalid padding as close as possible to indistinguishable to an external observer. In particular, the timing of a decryption operation should not depend on the validity of the padding. </p>
+
+</div>
+</div>
+<a id="ga35927f755d232c4766de600f2c49e9f2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga35927f755d232c4766de600f2c49e9f2">◆ </a></span>PSA_ERROR_INVALID_SIGNATURE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_INVALID_SIGNATURE   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)16)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The signature, MAC or hash is incorrect.</p>
+<p>Verification functions return this error if the verification calculations completed successfully, and the value to be verified was determined to be incorrect.</p>
+<p>If the value to verify has an invalid size, implementations may return either <a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a> or <a class="el" href="group__basic.html#ga35927f755d232c4766de600f2c49e9f2">PSA_ERROR_INVALID_SIGNATURE</a>. </p>
+
+</div>
+</div>
+<a id="ga4d1b8dd8526177a15a210b7afc1accb1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4d1b8dd8526177a15a210b7afc1accb1">◆ </a></span>PSA_ERROR_NOT_PERMITTED</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_NOT_PERMITTED   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)3)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The requested action is denied by a policy.</p>
+<p>Implementations should return this error code when the parameters are recognized as valid and supported, and a policy explicitly denies the requested operation.</p>
+<p>If a subset of the parameters of a function call identify a forbidden operation, and another subset of the parameters are not valid or not supported, it is unspecified whether the function returns <a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a>, <a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a> or <a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a>. </p>
+
+</div>
+</div>
+<a id="ga1dcc6d130633ed5db8942257581b55dd"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1dcc6d130633ed5db8942257581b55dd">◆ </a></span>PSA_ERROR_NOT_SUPPORTED</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_NOT_SUPPORTED   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)2)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The requested operation or a parameter is not supported by this implementation.</p>
+<p>Implementations should return this error code when an enumeration parameter such as a key type, algorithm, etc. is not recognized. If a combination of parameters is recognized and identified as not valid, return <a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a> instead. </p>
+
+</div>
+</div>
+<a id="gac2fee3a51249fbea45360aaa911f3e58"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac2fee3a51249fbea45360aaa911f3e58">◆ </a></span>PSA_ERROR_OCCUPIED_SLOT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_OCCUPIED_SLOT   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)5)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>A slot is occupied, but must be empty to carry out the requested action.</p>
+<p>If the slot number is invalid (i.e. the requested action could not be performed even after erasing the slot's content), implementations shall return <a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a> instead. </p>
+
+</div>
+</div>
+<a id="gadd169a1af2707862b95fb9df91dfc37d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gadd169a1af2707862b95fb9df91dfc37d">◆ </a></span>PSA_ERROR_STORAGE_FAILURE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_STORAGE_FAILURE   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)12)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>There was a storage failure that may have led to data loss.</p>
+<p>This error indicates that some persistent storage is corrupted. It should not be used for a corruption of volatile memory (use <a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a>), for a communication error between the cryptoprocessor and its external storage (use <a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a>), or when the storage is in a valid state but is full (use <a class="el" href="group__basic.html#ga897a45eb206a6f6b7be7ffbe36f0d766">PSA_ERROR_INSUFFICIENT_STORAGE</a>).</p>
+<p>Note that a storage failure does not indicate that any data that was previously read is invalid. However this previously read data may no longer be readable from storage.</p>
+<p>When a storage failure occurs, it is no longer possible to ensure the global integrity of the keystore. Depending on the global integrity guarantees offered by the implementation, access to other data may or may not fail even if the data is still readable but its integrity canont be guaranteed.</p>
+<p>Implementations should only use this error code to report a permanent storage corruption. However application writers should keep in mind that transient errors while reading the storage may be reported using this error code. </p>
+
+</div>
+</div>
+<a id="ga2c5dda1485cb54f2385cb9c1279a7004"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga2c5dda1485cb54f2385cb9c1279a7004">◆ </a></span>PSA_ERROR_TAMPERING_DETECTED</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_TAMPERING_DETECTED   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)14)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>A tampering attempt was detected.</p>
+<p>If an application receives this error code, there is no guarantee that previously accessed or computed data was correct and remains confidential. Applications should not perform any security function and should enter a safe failure state.</p>
+<p>Implementations may return this error code if they detect an invalid state that cannot happen during normal operation and that indicates that the implementation's security guarantees no longer hold. Depending on the implementation architecture and on its security and safety goals, the implementation may forcibly terminate the application.</p>
+<p>This error code is intended as a last resort when a security breach is detected and it is unsure whether the keystore data is still protected. Implementations shall only return this error code to report an alarm from a tampering detector, to indicate that the confidentiality of stored data can no longer be guaranteed, or to indicate that the integrity of previously returned data is now considered compromised. Implementations shall not use this error code to indicate a hardware failure that merely makes it impossible to perform the requested operation (use <a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a>, <a class="el" href="group__basic.html#gadd169a1af2707862b95fb9df91dfc37d">PSA_ERROR_STORAGE_FAILURE</a>, <a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a>, <a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">PSA_ERROR_INSUFFICIENT_ENTROPY</a> or other applicable error code instead).</p>
+<p>This error indicates an attack against the application. Implementations shall not return this error code as a consequence of the behavior of the application itself. </p>
+
+</div>
+</div>
+<a id="ga24d5fdcdd759f846f79d9e581c63a83f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga24d5fdcdd759f846f79d9e581c63a83f">◆ </a></span>PSA_ERROR_UNKNOWN_ERROR</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ERROR_UNKNOWN_ERROR   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)1)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>An error occurred that does not correspond to any defined failure cause.</p>
+<p>Implementations may use this error code if none of the other standard error codes are applicable. </p>
+
+</div>
+</div>
+<a id="ga4cc859e2c66ca381c7418db3527a65e1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4cc859e2c66ca381c7418db3527a65e1">◆ </a></span>PSA_SUCCESS</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_SUCCESS   ((<a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a>)0)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The action was completed successfully. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="ga05676e70ba5c6a7565aff3c36677c1f9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga05676e70ba5c6a7565aff3c36677c1f9">◆ </a></span>psa_status_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef int32_t <a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Function return status. </p>
+<p>This is either <a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a> (which is zero), indicating success, or a nonzero value indicating that an error occurred. Errors are encoded as one of the <code>PSA_ERROR_xxx</code> values defined here. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga2de150803fc2f7dc6101d5af7e921dd9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga2de150803fc2f7dc6101d5af7e921dd9">◆ </a></span>psa_crypto_init()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_crypto_init </td>
+ <td>(</td>
+ <td class="paramtype">void </td>
+ <td class="paramname"></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Library initialization. </p>
+<p>Applications must call this function before calling any other function in this module.</p>
+<p>Applications may call this function more than once. Once a call succeeds, subsequent calls are guaranteed to succeed.</p>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">PSA_ERROR_INSUFFICIENT_ENTROPY</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__cipher.html b/docs/html/group__cipher.html
new file mode 100644
index 0000000..4778275
--- /dev/null
+++ b/docs/html/group__cipher.html
@@ -0,0 +1,569 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Symmetric ciphers</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Symmetric ciphers</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ga1399de29db657e3737bb09927aae51fa"><td class="memItemLeft" align="right" valign="top">typedef struct psa_cipher_operation_s </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a></td></tr>
+<tr class="separator:ga1399de29db657e3737bb09927aae51fa"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga735c9d51b820e1d4cb45f2406ebfae98"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="separator:ga735c9d51b820e1d4cb45f2406ebfae98"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8ce1efaa648d7e0dd00e878d655d2950"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="separator:ga8ce1efaa648d7e0dd00e878d655d2950"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga44857cf5e0c3d134a3c560f8ff5b50aa"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">psa_cipher_generate_iv</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, unsigned char *iv, size_t iv_size, size_t *iv_length)</td></tr>
+<tr class="separator:ga44857cf5e0c3d134a3c560f8ff5b50aa"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1359b2101f31637496ce7cc36c6e3d42"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42">psa_cipher_set_iv</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, const unsigned char *iv, size_t iv_length)</td></tr>
+<tr class="separator:ga1359b2101f31637496ce7cc36c6e3d42"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafd0caea99cf1052527e4089d37f5ab91"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, const uint8_t *input, size_t input_length, unsigned char *output, size_t output_size, size_t *output_length)</td></tr>
+<tr class="separator:gafd0caea99cf1052527e4089d37f5ab91"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1dcb58b8befe23f8a4d7a1d49c99249b"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">psa_cipher_finish</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation, uint8_t *output, size_t output_size, size_t *output_length)</td></tr>
+<tr class="separator:ga1dcb58b8befe23f8a4d7a1d49c99249b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaad482cdca2098bca0620596aaa02eaa4"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">psa_cipher_abort</a> (<a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> *operation)</td></tr>
+<tr class="separator:gaad482cdca2098bca0620596aaa02eaa4"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="ga1399de29db657e3737bb09927aae51fa"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1399de29db657e3737bb09927aae51fa">◆ </a></span>psa_cipher_operation_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef struct psa_cipher_operation_s <a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The type of the state data structure for multipart cipher operations.</p>
+<p>This is an implementation-defined <code>struct</code>. Applications should not make any assumptions about the content of this structure except as directed by the documentation of a specific implementation. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="gaad482cdca2098bca0620596aaa02eaa4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaad482cdca2098bca0620596aaa02eaa4">◆ </a></span>psa_cipher_abort()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_cipher_abort </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Abort a cipher operation.</p>
+<p>Aborting an operation frees all associated resources except for the <code>operation</code> structure itself. Once aborted, the operation object can be reused for another operation by calling <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup()</a> or <a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup()</a> again.</p>
+<p>You may call this function any time after the operation object has been initialized by any of the following methods:</p><ul>
+<li>A call to <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup()</a> or <a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup()</a>, whether it succeeds or not.</li>
+<li>Initializing the <code>struct</code> to all-bits-zero.</li>
+<li>Initializing the <code>struct</code> to logical zeros, e.g. <code>psa_cipher_operation_t operation = {0}</code>.</li>
+</ul>
+<p>In particular, calling <a class="el" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">psa_cipher_abort()</a> after the operation has been terminated by a call to <a class="el" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">psa_cipher_abort()</a> or <a class="el" href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">psa_cipher_finish()</a> is safe and has no effect.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Initialized cipher operation.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td><code>operation</code> is not an active cipher operation. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga8ce1efaa648d7e0dd00e878d655d2950"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga8ce1efaa648d7e0dd00e878d655d2950">◆ </a></span>psa_cipher_decrypt_setup()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_cipher_decrypt_setup </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Set the key for a multipart symmetric decryption operation.</p>
+<p>The sequence of operations to decrypt a message with a symmetric cipher is as follows:</p><ol type="1">
+<li>Allocate an operation object which will be passed to all the functions listed here.</li>
+<li>Call <a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup()</a> to specify the algorithm and key. The key remains associated with the operation even if the content of the key slot changes.</li>
+<li>Call <a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update()</a> with the IV (initialization vector) for the decryption. If the IV is prepended to the ciphertext, you can call <a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update()</a> on a buffer containing the IV followed by the beginning of the message.</li>
+<li>Call <a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update()</a> zero, one or more times, passing a fragment of the message each time.</li>
+<li>Call <a class="el" href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">psa_cipher_finish()</a>.</li>
+</ol>
+<p>The application may call <a class="el" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">psa_cipher_abort()</a> at any time after the operation has been initialized with <a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup()</a>.</p>
+<p>After a successful call to <a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup()</a>, the application must eventually terminate the operation. The following events terminate an operation:</p><ul>
+<li>A failed call to <a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update()</a>.</li>
+<li>A call to <a class="el" href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">psa_cipher_finish()</a> or <a class="el" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">psa_cipher_abort()</a>.</li>
+</ul>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[out]</td><td class="paramname">operation</td><td>The operation object to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot containing the key to use for the operation. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>The cipher algorithm to compute (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#ga1d1a5a402ad89a2e68f12bfb535490eb">PSA_ALG_IS_CIPHER</a>(<code>alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td><code>key</code> is not compatible with <code>alg</code>. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td><code>alg</code> is not supported or is not a cipher algorithm. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga735c9d51b820e1d4cb45f2406ebfae98"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga735c9d51b820e1d4cb45f2406ebfae98">◆ </a></span>psa_cipher_encrypt_setup()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_cipher_encrypt_setup </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Set the key for a multipart symmetric encryption operation.</p>
+<p>The sequence of operations to encrypt a message with a symmetric cipher is as follows:</p><ol type="1">
+<li>Allocate an operation object which will be passed to all the functions listed here.</li>
+<li>Call <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup()</a> to specify the algorithm and key. The key remains associated with the operation even if the content of the key slot changes.</li>
+<li>Call either <a class="el" href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">psa_cipher_generate_iv()</a> or <a class="el" href="group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42">psa_cipher_set_iv()</a> to generate or set the IV (initialization vector). You should use <a class="el" href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">psa_cipher_generate_iv()</a> unless the protocol you are implementing requires a specific IV value.</li>
+<li>Call <a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update()</a> zero, one or more times, passing a fragment of the message each time.</li>
+<li>Call <a class="el" href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">psa_cipher_finish()</a>.</li>
+</ol>
+<p>The application may call <a class="el" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">psa_cipher_abort()</a> at any time after the operation has been initialized with <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup()</a>.</p>
+<p>After a successful call to <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup()</a>, the application must eventually terminate the operation. The following events terminate an operation:</p><ul>
+<li>A failed call to <a class="el" href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">psa_cipher_generate_iv()</a>, <a class="el" href="group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42">psa_cipher_set_iv()</a> or <a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update()</a>.</li>
+<li>A call to <a class="el" href="group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b">psa_cipher_finish()</a> or <a class="el" href="group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4">psa_cipher_abort()</a>.</li>
+</ul>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[out]</td><td class="paramname">operation</td><td>The operation object to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot containing the key to use for the operation. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>The cipher algorithm to compute (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#ga1d1a5a402ad89a2e68f12bfb535490eb">PSA_ALG_IS_CIPHER</a>(<code>alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td><code>key</code> is not compatible with <code>alg</code>. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td><code>alg</code> is not supported or is not a cipher algorithm. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga1dcb58b8befe23f8a4d7a1d49c99249b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1dcb58b8befe23f8a4d7a1d49c99249b">◆ </a></span>psa_cipher_finish()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_cipher_finish </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>output</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>output_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>output_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Finish encrypting or decrypting a message in a cipher operation.</p>
+<p>The application must call <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup()</a> or <a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup()</a> before calling this function. The choice of setup function determines whether this function encrypts or decrypts its input.</p>
+<p>This function finishes the encryption or decryption of the message formed by concatenating the inputs passed to preceding calls to <a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update()</a>.</p>
+<p>When this function returns, the operation becomes inactive.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Active cipher operation. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">output</td><td>Buffer where the output is to be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">output_size</td><td>Size of the <code>output</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">output_length</td><td>On success, the number of bytes that make up the returned output.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td>The operation state is not valid (not started, IV required but not set, or already completed). </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a></td><td>The size of the <code>output</code> buffer is too small. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga44857cf5e0c3d134a3c560f8ff5b50aa"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga44857cf5e0c3d134a3c560f8ff5b50aa">◆ </a></span>psa_cipher_generate_iv()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_cipher_generate_iv </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">unsigned char * </td>
+ <td class="paramname"><em>iv</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>iv_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>iv_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Generate an IV for a symmetric encryption operation.</p>
+<p>This function generates a random IV (initialization vector), nonce or initial counter value for the encryption operation as appropriate for the chosen algorithm, key type and key size.</p>
+<p>The application must call <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup()</a> before calling this function.</p>
+<p>If this function returns an error status, the operation becomes inactive.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Active cipher operation. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">iv</td><td>Buffer where the generated IV is to be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">iv_size</td><td>Size of the <code>iv</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">iv_length</td><td>On success, the number of bytes of the generated IV.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td>The operation state is not valid (not started, or IV already set). </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a></td><td>The size of the <code>iv</code> buffer is too small. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga1359b2101f31637496ce7cc36c6e3d42"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1359b2101f31637496ce7cc36c6e3d42">◆ </a></span>psa_cipher_set_iv()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_cipher_set_iv </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const unsigned char * </td>
+ <td class="paramname"><em>iv</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>iv_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Set the IV for a symmetric encryption or decryption operation.</p>
+<p>This function sets the random IV (initialization vector), nonce or initial counter value for the encryption or decryption operation.</p>
+<p>The application must call <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup()</a> before calling this function.</p>
+<p>If this function returns an error status, the operation becomes inactive.</p>
+<dl class="section note"><dt>Note</dt><dd>When encrypting, applications should use <a class="el" href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">psa_cipher_generate_iv()</a> instead of this function, unless implementing a protocol that requires a non-random IV.</dd></dl>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Active cipher operation. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">iv</td><td>Buffer containing the IV to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">iv_length</td><td>Size of the IV in bytes.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td>The operation state is not valid (not started, or IV already set). </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td>The size of <code>iv</code> is not acceptable for the chosen algorithm, or the chosen algorithm does not use an IV. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gafd0caea99cf1052527e4089d37f5ab91"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gafd0caea99cf1052527e4089d37f5ab91">◆ </a></span>psa_cipher_update()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_cipher_update </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__cipher.html#ga1399de29db657e3737bb09927aae51fa">psa_cipher_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>input</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>input_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">unsigned char * </td>
+ <td class="paramname"><em>output</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>output_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>output_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Encrypt or decrypt a message fragment in an active cipher operation.</p>
+<p>Before calling this function, you must:</p><ol type="1">
+<li>Call either <a class="el" href="group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98">psa_cipher_encrypt_setup()</a> or <a class="el" href="group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950">psa_cipher_decrypt_setup()</a>. The choice of setup function determines whether this function encrypts or decrypts its input.</li>
+<li>If the algorithm requires an IV, call <a class="el" href="group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa">psa_cipher_generate_iv()</a> (recommended when encrypting) or <a class="el" href="group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42">psa_cipher_set_iv()</a>.</li>
+</ol>
+<p>If this function returns an error status, the operation becomes inactive.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Active cipher operation. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">input</td><td>Buffer containing the message fragment to encrypt or decrypt. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">input_length</td><td>Size of the <code>input</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">output</td><td>Buffer where the output is to be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">output_size</td><td>Size of the <code>output</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">output_length</td><td>On success, the number of bytes that make up the returned output.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td>The operation state is not valid (not started, IV required but not set, or already completed). </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a></td><td>The size of the <code>output</code> buffer is too small. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__crypto__types.html b/docs/html/group__crypto__types.html
new file mode 100644
index 0000000..355cd94
--- /dev/null
+++ b/docs/html/group__crypto__types.html
@@ -0,0 +1,1966 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Key and algorithm types</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#define-members">Macros</a> |
+<a href="#typedef-members">Typedefs</a> </div>
+ <div class="headertitle">
+<div class="title">Key and algorithm types</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:gafce7ab2b54ce97ea5bff73f13a9f3e5b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gafce7ab2b54ce97ea5bff73f13a9f3e5b">PSA_KEY_TYPE_NONE</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x00000000)</td></tr>
+<tr class="separator:gafce7ab2b54ce97ea5bff73f13a9f3e5b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8dbaed2fdb1ebae8aa127ad3988516f7"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7">PSA_KEY_TYPE_VENDOR_FLAG</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x80000000)</td></tr>
+<tr class="separator:ga8dbaed2fdb1ebae8aa127ad3988516f7"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6eeda1b2a1550050cf68dbcac35ad8ac"><td class="memItemLeft" align="right" valign="top"><a id="ga6eeda1b2a1550050cf68dbcac35ad8ac"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_CATEGORY_MASK</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x7e000000)</td></tr>
+<tr class="separator:ga6eeda1b2a1550050cf68dbcac35ad8ac"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa97f92025533102616b32d571c940d80"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaa97f92025533102616b32d571c940d80">PSA_KEY_TYPE_RAW_DATA</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x02000000)</td></tr>
+<tr class="separator:gaa97f92025533102616b32d571c940d80"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8f214beb04334be08f927f227f097ef1"><td class="memItemLeft" align="right" valign="top"><a id="ga8f214beb04334be08f927f227f097ef1"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_CATEGORY_SYMMETRIC</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000000)</td></tr>
+<tr class="separator:ga8f214beb04334be08f927f227f097ef1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7f4249bf41fc60daa0b4e2901cdcd02d"><td class="memItemLeft" align="right" valign="top"><a id="ga7f4249bf41fc60daa0b4e2901cdcd02d"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_CATEGORY_ASYMMETRIC</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x06000000)</td></tr>
+<tr class="separator:ga7f4249bf41fc60daa0b4e2901cdcd02d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6b686b30cc0193f5a93616097d58934f"><td class="memItemLeft" align="right" valign="top"><a id="ga6b686b30cc0193f5a93616097d58934f"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_PAIR_FLAG</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x01000000)</td></tr>
+<tr class="separator:ga6b686b30cc0193f5a93616097d58934f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga92d989f4ca64abd00f463defd773a6f8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga92d989f4ca64abd00f463defd773a6f8">PSA_KEY_TYPE_HMAC</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x02000001)</td></tr>
+<tr class="separator:ga92d989f4ca64abd00f463defd773a6f8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae871b2357b8593f33bfd51abbf93ebb1"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gae871b2357b8593f33bfd51abbf93ebb1">PSA_KEY_TYPE_DERIVE</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x02000101)</td></tr>
+<tr class="separator:gae871b2357b8593f33bfd51abbf93ebb1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6ee54579dcf278c677eda4bb1a29575e"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga6ee54579dcf278c677eda4bb1a29575e">PSA_KEY_TYPE_AES</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000001)</td></tr>
+<tr class="separator:ga6ee54579dcf278c677eda4bb1a29575e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga577562bfbbc691c820d55ec308333138"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga577562bfbbc691c820d55ec308333138">PSA_KEY_TYPE_DES</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000002)</td></tr>
+<tr class="separator:ga577562bfbbc691c820d55ec308333138"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad8e5da742343fd5519f9d8a630c2ed81"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gad8e5da742343fd5519f9d8a630c2ed81">PSA_KEY_TYPE_CAMELLIA</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000003)</td></tr>
+<tr class="separator:gad8e5da742343fd5519f9d8a630c2ed81"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae4d46e83f910dcaa126000a8ed03cde9"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gae4d46e83f910dcaa126000a8ed03cde9">PSA_KEY_TYPE_ARC4</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000004)</td></tr>
+<tr class="separator:gae4d46e83f910dcaa126000a8ed03cde9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga9ba0878f56c8bcd1995ac017a74f513b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b">PSA_KEY_TYPE_RSA_PUBLIC_KEY</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x06010000)</td></tr>
+<tr class="separator:ga9ba0878f56c8bcd1995ac017a74f513b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga581f50687f5d650456925278948f2799"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga581f50687f5d650456925278948f2799">PSA_KEY_TYPE_RSA_KEYPAIR</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x07010000)</td></tr>
+<tr class="separator:ga581f50687f5d650456925278948f2799"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5e7439c2905136366c3a876e62e5ddfc"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga5e7439c2905136366c3a876e62e5ddfc">PSA_KEY_TYPE_DSA_PUBLIC_KEY</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x06020000)</td></tr>
+<tr class="separator:ga5e7439c2905136366c3a876e62e5ddfc"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga011010ee28c20388f3d89fb27088ed62"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga011010ee28c20388f3d89fb27088ed62">PSA_KEY_TYPE_DSA_KEYPAIR</a>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x07020000)</td></tr>
+<tr class="separator:ga011010ee28c20388f3d89fb27088ed62"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad8d37a32a305dda9fb4af1707aace47c"><td class="memItemLeft" align="right" valign="top"><a id="gad8d37a32a305dda9fb4af1707aace47c"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x06030000)</td></tr>
+<tr class="separator:gad8d37a32a305dda9fb4af1707aace47c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6754658749714c6ac674bdf6d2d40767"><td class="memItemLeft" align="right" valign="top"><a id="ga6754658749714c6ac674bdf6d2d40767"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_ECC_KEYPAIR_BASE</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x07030000)</td></tr>
+<tr class="separator:ga6754658749714c6ac674bdf6d2d40767"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gadc2a3c0041ac1d0a2b6f421d8e089b25"><td class="memItemLeft" align="right" valign="top"><a id="gadc2a3c0041ac1d0a2b6f421d8e089b25"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_ECC_CURVE_MASK</b>   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x0000ffff)</td></tr>
+<tr class="separator:gadc2a3c0041ac1d0a2b6f421d8e089b25"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gadf3ad65d157bf5282849c954bf3f51af"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gadf3ad65d157bf5282849c954bf3f51af">PSA_KEY_TYPE_ECC_KEYPAIR</a>(curve)   (PSA_KEY_TYPE_ECC_KEYPAIR_BASE | (curve))</td></tr>
+<tr class="separator:gadf3ad65d157bf5282849c954bf3f51af"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad54c03d3b47020e571a72cd01d978cf2"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gad54c03d3b47020e571a72cd01d978cf2">PSA_KEY_TYPE_ECC_PUBLIC_KEY</a>(curve)   (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve))</td></tr>
+<tr class="separator:gad54c03d3b47020e571a72cd01d978cf2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gadbe4c086a6562aefe344bc79e51bdfd3"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gadbe4c086a6562aefe344bc79e51bdfd3">PSA_KEY_TYPE_IS_VENDOR_DEFINED</a>(type)   (((type) & <a class="el" href="group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7">PSA_KEY_TYPE_VENDOR_FLAG</a>) != 0)</td></tr>
+<tr class="separator:gadbe4c086a6562aefe344bc79e51bdfd3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab138ae2ebf2905dfbaf4154db2620939"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gab138ae2ebf2905dfbaf4154db2620939">PSA_KEY_TYPE_IS_ASYMMETRIC</a>(type)   (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)</td></tr>
+<tr class="separator:gab138ae2ebf2905dfbaf4154db2620939"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac674a0f059bc0cb72b47f0c517b4f45b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gac674a0f059bc0cb72b47f0c517b4f45b">PSA_KEY_TYPE_IS_PUBLIC_KEY</a>(type)</td></tr>
+<tr class="separator:gac674a0f059bc0cb72b47f0c517b4f45b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac14c6d6e1b2b7f4a92a7b757465cff29"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gac14c6d6e1b2b7f4a92a7b757465cff29">PSA_KEY_TYPE_IS_KEYPAIR</a>(type)</td></tr>
+<tr class="separator:gac14c6d6e1b2b7f4a92a7b757465cff29"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf09f1ca1de6a7e7cff0fe516f3f6c91d"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaf09f1ca1de6a7e7cff0fe516f3f6c91d">PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY</a>(type)   ((type) | PSA_KEY_TYPE_PAIR_FLAG)</td></tr>
+<tr class="separator:gaf09f1ca1de6a7e7cff0fe516f3f6c91d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gace08e46dd7cbf642d50d982a25d02bec"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec">PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR</a>(type)   ((type) & ~PSA_KEY_TYPE_PAIR_FLAG)</td></tr>
+<tr class="separator:gace08e46dd7cbf642d50d982a25d02bec"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga0e1d8f241228e49c9cadadfb4579ef1a"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a">PSA_KEY_TYPE_IS_RSA</a>(type)   (<a class="el" href="group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec">PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR</a>(type) == <a class="el" href="group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b">PSA_KEY_TYPE_RSA_PUBLIC_KEY</a>)</td></tr>
+<tr class="separator:ga0e1d8f241228e49c9cadadfb4579ef1a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga88e01fa06b585654689a99bcc06bbe66"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66">PSA_KEY_TYPE_IS_ECC</a>(type)</td></tr>
+<tr class="separator:ga88e01fa06b585654689a99bcc06bbe66"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7bf101b671e8cf26f4cb08fcb679db4b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_IS_ECC_KEYPAIR</b>(type)</td></tr>
+<tr class="separator:ga7bf101b671e8cf26f4cb08fcb679db4b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5af146a173b0c84d7e737e2fb6a3c0a7"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY</b>(type)</td></tr>
+<tr class="separator:ga5af146a173b0c84d7e737e2fb6a3c0a7"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga0c567210e6f80aa8f2aa87efa7a3a3f9"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga0c567210e6f80aa8f2aa87efa7a3a3f9">PSA_KEY_TYPE_GET_CURVE</a>(type)</td></tr>
+<tr class="separator:ga0c567210e6f80aa8f2aa87efa7a3a3f9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4201013d5947c375fae7311b0f98bac7"><td class="memItemLeft" align="right" valign="top"><a id="ga4201013d5947c375fae7311b0f98bac7"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT163K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0001)</td></tr>
+<tr class="separator:ga4201013d5947c375fae7311b0f98bac7"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaca8816b785f492a8795b5276977d1369"><td class="memItemLeft" align="right" valign="top"><a id="gaca8816b785f492a8795b5276977d1369"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT163R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0002)</td></tr>
+<tr class="separator:gaca8816b785f492a8795b5276977d1369"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4ab7a853ceb3ad0a525ecb571633a1ca"><td class="memItemLeft" align="right" valign="top"><a id="ga4ab7a853ceb3ad0a525ecb571633a1ca"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT163R2</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0003)</td></tr>
+<tr class="separator:ga4ab7a853ceb3ad0a525ecb571633a1ca"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac9fd11da90ca67649a5f51a158afe5f3"><td class="memItemLeft" align="right" valign="top"><a id="gac9fd11da90ca67649a5f51a158afe5f3"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT193R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0004)</td></tr>
+<tr class="separator:gac9fd11da90ca67649a5f51a158afe5f3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7a77f5e385f6439dae5857a7f35756eb"><td class="memItemLeft" align="right" valign="top"><a id="ga7a77f5e385f6439dae5857a7f35756eb"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT193R2</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0005)</td></tr>
+<tr class="separator:ga7a77f5e385f6439dae5857a7f35756eb"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga36e409c36983e41db5db202b1d2095b5"><td class="memItemLeft" align="right" valign="top"><a id="ga36e409c36983e41db5db202b1d2095b5"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT233K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0006)</td></tr>
+<tr class="separator:ga36e409c36983e41db5db202b1d2095b5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga54997a9f8ef752c6d717171e01c31019"><td class="memItemLeft" align="right" valign="top"><a id="ga54997a9f8ef752c6d717171e01c31019"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT233R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0007)</td></tr>
+<tr class="separator:ga54997a9f8ef752c6d717171e01c31019"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaabccf2759188c3e98d82faa5d8dfcd8c"><td class="memItemLeft" align="right" valign="top"><a id="gaabccf2759188c3e98d82faa5d8dfcd8c"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT239K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0008)</td></tr>
+<tr class="separator:gaabccf2759188c3e98d82faa5d8dfcd8c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga28c765d75773b5fe083219e7c0b054f9"><td class="memItemLeft" align="right" valign="top"><a id="ga28c765d75773b5fe083219e7c0b054f9"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT283K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0009)</td></tr>
+<tr class="separator:ga28c765d75773b5fe083219e7c0b054f9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafd8ecacea0d9e7e1a0247c047baf3372"><td class="memItemLeft" align="right" valign="top"><a id="gafd8ecacea0d9e7e1a0247c047baf3372"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT283R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000a)</td></tr>
+<tr class="separator:gafd8ecacea0d9e7e1a0247c047baf3372"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2bf301617cc84a6f2b36a86cc29eaf4d"><td class="memItemLeft" align="right" valign="top"><a id="ga2bf301617cc84a6f2b36a86cc29eaf4d"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT409K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000b)</td></tr>
+<tr class="separator:ga2bf301617cc84a6f2b36a86cc29eaf4d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae41caa1cc16d3c35769b6edcb62c8957"><td class="memItemLeft" align="right" valign="top"><a id="gae41caa1cc16d3c35769b6edcb62c8957"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT409R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000c)</td></tr>
+<tr class="separator:gae41caa1cc16d3c35769b6edcb62c8957"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2043aa519549a6194d132d81816879bc"><td class="memItemLeft" align="right" valign="top"><a id="ga2043aa519549a6194d132d81816879bc"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT571K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000d)</td></tr>
+<tr class="separator:ga2043aa519549a6194d132d81816879bc"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1607d2cb9591b56dbe1295bedc33e19e"><td class="memItemLeft" align="right" valign="top"><a id="ga1607d2cb9591b56dbe1295bedc33e19e"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECT571R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000e)</td></tr>
+<tr class="separator:ga1607d2cb9591b56dbe1295bedc33e19e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2ad14935d244d93ee0e4cfe9b1f218a4"><td class="memItemLeft" align="right" valign="top"><a id="ga2ad14935d244d93ee0e4cfe9b1f218a4"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP160K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x000f)</td></tr>
+<tr class="separator:ga2ad14935d244d93ee0e4cfe9b1f218a4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga35ed41203039e94eb4855cc70f28f7f0"><td class="memItemLeft" align="right" valign="top"><a id="ga35ed41203039e94eb4855cc70f28f7f0"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP160R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0010)</td></tr>
+<tr class="separator:ga35ed41203039e94eb4855cc70f28f7f0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac465f57c34914a01aea8c220a613dfe6"><td class="memItemLeft" align="right" valign="top"><a id="gac465f57c34914a01aea8c220a613dfe6"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP160R2</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0011)</td></tr>
+<tr class="separator:gac465f57c34914a01aea8c220a613dfe6"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga58c806d45ab350287ddc49da833bd558"><td class="memItemLeft" align="right" valign="top"><a id="ga58c806d45ab350287ddc49da833bd558"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP192K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0012)</td></tr>
+<tr class="separator:ga58c806d45ab350287ddc49da833bd558"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5aa3ceff4603fa3fafd8f2286c5d3e4a"><td class="memItemLeft" align="right" valign="top"><a id="ga5aa3ceff4603fa3fafd8f2286c5d3e4a"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP192R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0013)</td></tr>
+<tr class="separator:ga5aa3ceff4603fa3fafd8f2286c5d3e4a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gabfaaab2eaab0ac360e41c1aff6133cdf"><td class="memItemLeft" align="right" valign="top"><a id="gabfaaab2eaab0ac360e41c1aff6133cdf"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP224K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0014)</td></tr>
+<tr class="separator:gabfaaab2eaab0ac360e41c1aff6133cdf"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8d1d21b6b87ba4158235b876ae79031d"><td class="memItemLeft" align="right" valign="top"><a id="ga8d1d21b6b87ba4158235b876ae79031d"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP224R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0015)</td></tr>
+<tr class="separator:ga8d1d21b6b87ba4158235b876ae79031d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaaa61941f815aff976a1debd910b1704c"><td class="memItemLeft" align="right" valign="top"><a id="gaaa61941f815aff976a1debd910b1704c"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP256K1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0016)</td></tr>
+<tr class="separator:gaaa61941f815aff976a1debd910b1704c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga11224270225c2b2dbfa2ab01073a4e93"><td class="memItemLeft" align="right" valign="top"><a id="ga11224270225c2b2dbfa2ab01073a4e93"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP256R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0017)</td></tr>
+<tr class="separator:ga11224270225c2b2dbfa2ab01073a4e93"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3e870a36493143507a01a28c70790fa3"><td class="memItemLeft" align="right" valign="top"><a id="ga3e870a36493143507a01a28c70790fa3"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP384R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0018)</td></tr>
+<tr class="separator:ga3e870a36493143507a01a28c70790fa3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4482ff6155006ff509071c32ce263fdf"><td class="memItemLeft" align="right" valign="top"><a id="ga4482ff6155006ff509071c32ce263fdf"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_SECP521R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0019)</td></tr>
+<tr class="separator:ga4482ff6155006ff509071c32ce263fdf"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa999b69c56af0cc1cebf4596f8578191"><td class="memItemLeft" align="right" valign="top"><a id="gaa999b69c56af0cc1cebf4596f8578191"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_BRAINPOOL_P256R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x001a)</td></tr>
+<tr class="separator:gaa999b69c56af0cc1cebf4596f8578191"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga79f95ed8050f2dc7750cbac212c6e687"><td class="memItemLeft" align="right" valign="top"><a id="ga79f95ed8050f2dc7750cbac212c6e687"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_BRAINPOOL_P384R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x001b)</td></tr>
+<tr class="separator:ga79f95ed8050f2dc7750cbac212c6e687"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa03a2dc6096f336be3d68a1f7405e86c"><td class="memItemLeft" align="right" valign="top"><a id="gaa03a2dc6096f336be3d68a1f7405e86c"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_BRAINPOOL_P512R1</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x001c)</td></tr>
+<tr class="separator:gaa03a2dc6096f336be3d68a1f7405e86c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac94faf3b8d9884221541f51f26b11c7a"><td class="memItemLeft" align="right" valign="top"><a id="gac94faf3b8d9884221541f51f26b11c7a"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_CURVE25519</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x001d)</td></tr>
+<tr class="separator:gac94faf3b8d9884221541f51f26b11c7a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga902b0e91eff920873b3b59c740854305"><td class="memItemLeft" align="right" valign="top"><a id="ga902b0e91eff920873b3b59c740854305"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_CURVE448</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x001e)</td></tr>
+<tr class="separator:ga902b0e91eff920873b3b59c740854305"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafef0f861db5bb6cdf025d18cf0fbdbb0"><td class="memItemLeft" align="right" valign="top"><a id="gafef0f861db5bb6cdf025d18cf0fbdbb0"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_FFDHE_2048</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0100)</td></tr>
+<tr class="separator:gafef0f861db5bb6cdf025d18cf0fbdbb0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae69d8c862c26e5aed50e047814e8c27e"><td class="memItemLeft" align="right" valign="top"><a id="gae69d8c862c26e5aed50e047814e8c27e"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_FFDHE_3072</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0101)</td></tr>
+<tr class="separator:gae69d8c862c26e5aed50e047814e8c27e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7d2411ef9ff0f95bd01ca6208368f8e4"><td class="memItemLeft" align="right" valign="top"><a id="ga7d2411ef9ff0f95bd01ca6208368f8e4"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_FFDHE_4096</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0102)</td></tr>
+<tr class="separator:ga7d2411ef9ff0f95bd01ca6208368f8e4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga9380456dc83ac91a5338d3b5cf48c100"><td class="memItemLeft" align="right" valign="top"><a id="ga9380456dc83ac91a5338d3b5cf48c100"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_FFDHE_6144</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0103)</td></tr>
+<tr class="separator:ga9380456dc83ac91a5338d3b5cf48c100"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga847e2f8d9663ff63025a8cd0d1096655"><td class="memItemLeft" align="right" valign="top"><a id="ga847e2f8d9663ff63025a8cd0d1096655"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ECC_CURVE_FFDHE_8192</b>   ((<a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) 0x0104)</td></tr>
+<tr class="separator:ga847e2f8d9663ff63025a8cd0d1096655"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gacaa366bdeb0413e63e87a667c5457b2e"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gacaa366bdeb0413e63e87a667c5457b2e">PSA_BLOCK_CIPHER_BLOCK_SIZE</a>(type)</td></tr>
+<tr class="separator:gacaa366bdeb0413e63e87a667c5457b2e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf5d76750b6cfe3e7f0c8e9eee1162318"><td class="memItemLeft" align="right" valign="top"><a id="gaf5d76750b6cfe3e7f0c8e9eee1162318"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_VENDOR_FLAG</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x80000000)</td></tr>
+<tr class="separator:gaf5d76750b6cfe3e7f0c8e9eee1162318"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga25e918c465b4421dbfaedad6b693d110"><td class="memItemLeft" align="right" valign="top"><a id="ga25e918c465b4421dbfaedad6b693d110"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x7f000000)</td></tr>
+<tr class="separator:ga25e918c465b4421dbfaedad6b693d110"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafd048e1835b80e6daaff7fddce699757"><td class="memItemLeft" align="right" valign="top"><a id="gafd048e1835b80e6daaff7fddce699757"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_HASH</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000000)</td></tr>
+<tr class="separator:gafd048e1835b80e6daaff7fddce699757"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5e6e0039d0b0d18afb3e13e5b9602b3a"><td class="memItemLeft" align="right" valign="top"><a id="ga5e6e0039d0b0d18afb3e13e5b9602b3a"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_MAC</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02000000)</td></tr>
+<tr class="separator:ga5e6e0039d0b0d18afb3e13e5b9602b3a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga68228a619db59eba93fd13e9129dbfe2"><td class="memItemLeft" align="right" valign="top"><a id="ga68228a619db59eba93fd13e9129dbfe2"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_CIPHER</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000000)</td></tr>
+<tr class="separator:ga68228a619db59eba93fd13e9129dbfe2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga37fdd9cac2552f1568f38e091a826549"><td class="memItemLeft" align="right" valign="top"><a id="ga37fdd9cac2552f1568f38e091a826549"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_AEAD</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x06000000)</td></tr>
+<tr class="separator:ga37fdd9cac2552f1568f38e091a826549"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga68a0af1dd89b33fb1e53139f654988f6"><td class="memItemLeft" align="right" valign="top"><a id="ga68a0af1dd89b33fb1e53139f654988f6"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_SIGN</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10000000)</td></tr>
+<tr class="separator:ga68a0af1dd89b33fb1e53139f654988f6"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga72f46c8256b760b174e6db61a61cd608"><td class="memItemLeft" align="right" valign="top"><a id="ga72f46c8256b760b174e6db61a61cd608"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x12000000)</td></tr>
+<tr class="separator:ga72f46c8256b760b174e6db61a61cd608"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga808e397a4891c612df4a5b20eebc2fac"><td class="memItemLeft" align="right" valign="top"><a id="ga808e397a4891c612df4a5b20eebc2fac"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_KEY_AGREEMENT</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x22000000)</td></tr>
+<tr class="separator:ga808e397a4891c612df4a5b20eebc2fac"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac185b2274dd4e5f0b97c43334c2e478f"><td class="memItemLeft" align="right" valign="top"><a id="gac185b2274dd4e5f0b97c43334c2e478f"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CATEGORY_KEY_DERIVATION</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x30000000)</td></tr>
+<tr class="separator:gac185b2274dd4e5f0b97c43334c2e478f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2396d8ba67096b3ebc69bc351a74c78b"><td class="memItemLeft" align="right" valign="top"><a id="ga2396d8ba67096b3ebc69bc351a74c78b"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_VENDOR_DEFINED</b>(alg)   (((alg) & PSA_ALG_VENDOR_FLAG) != 0)</td></tr>
+<tr class="separator:ga2396d8ba67096b3ebc69bc351a74c78b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac9280662bb482590b4b33d1dcd32930f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH)</td></tr>
+<tr class="separator:gac9280662bb482590b4b33d1dcd32930f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaca7aee4c9dde316b3b1a150a26eab776"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaca7aee4c9dde316b3b1a150a26eab776">PSA_ALG_IS_MAC</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC)</td></tr>
+<tr class="separator:gaca7aee4c9dde316b3b1a150a26eab776"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1d1a5a402ad89a2e68f12bfb535490eb"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga1d1a5a402ad89a2e68f12bfb535490eb">PSA_ALG_IS_CIPHER</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER)</td></tr>
+<tr class="separator:ga1d1a5a402ad89a2e68f12bfb535490eb"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1d44829d60065eaa4ac9a703e7d6abc8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8">PSA_ALG_IS_AEAD</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD)</td></tr>
+<tr class="separator:ga1d44829d60065eaa4ac9a703e7d6abc8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6d490d0904e0698f6c1268a89d72ff31"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga6d490d0904e0698f6c1268a89d72ff31">PSA_ALG_IS_SIGN</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN)</td></tr>
+<tr class="separator:ga6d490d0904e0698f6c1268a89d72ff31"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga41d2ee937d54efd76bd54a97b2ebc08a"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga41d2ee937d54efd76bd54a97b2ebc08a">PSA_ALG_IS_ASYMMETRIC_ENCRYPTION</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION)</td></tr>
+<tr class="separator:ga41d2ee937d54efd76bd54a97b2ebc08a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga59753742cb06553bd22751bbef472b6f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga59753742cb06553bd22751bbef472b6f">PSA_ALG_IS_KEY_AGREEMENT</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT)</td></tr>
+<tr class="separator:ga59753742cb06553bd22751bbef472b6f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf8b90c648aa53dbd06c236695e300cd0"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaf8b90c648aa53dbd06c236695e300cd0">PSA_ALG_IS_KEY_DERIVATION</a>(alg)   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)</td></tr>
+<tr class="separator:gaf8b90c648aa53dbd06c236695e300cd0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac41a7077aef55bb20c629c8949d43c57"><td class="memItemLeft" align="right" valign="top"><a id="gac41a7077aef55bb20c629c8949d43c57"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_HASH_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x000000ff)</td></tr>
+<tr class="separator:gac41a7077aef55bb20c629c8949d43c57"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab076ca67238cb4ebd81556db8f3dbac1"><td class="memItemLeft" align="right" valign="top"><a id="gab076ca67238cb4ebd81556db8f3dbac1"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_MD2</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000001)</td></tr>
+<tr class="separator:gab076ca67238cb4ebd81556db8f3dbac1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaac7ab8c28c117ef4ddf01affc8d3ceb2"><td class="memItemLeft" align="right" valign="top"><a id="gaac7ab8c28c117ef4ddf01affc8d3ceb2"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_MD4</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000002)</td></tr>
+<tr class="separator:gaac7ab8c28c117ef4ddf01affc8d3ceb2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gade591d9286d23382eb5cec099c84180d"><td class="memItemLeft" align="right" valign="top"><a id="gade591d9286d23382eb5cec099c84180d"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_MD5</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000003)</td></tr>
+<tr class="separator:gade591d9286d23382eb5cec099c84180d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6c5d3a32cda59086f07b85ef007033dd"><td class="memItemLeft" align="right" valign="top"><a id="ga6c5d3a32cda59086f07b85ef007033dd"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_RIPEMD160</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000004)</td></tr>
+<tr class="separator:ga6c5d3a32cda59086f07b85ef007033dd"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3fca4e9f9ad4a1158817d1850dee82e5"><td class="memItemLeft" align="right" valign="top"><a id="ga3fca4e9f9ad4a1158817d1850dee82e5"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_SHA_1</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000005)</td></tr>
+<tr class="separator:ga3fca4e9f9ad4a1158817d1850dee82e5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga25d6a3244d10a7148fe6b026d1979f7b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga25d6a3244d10a7148fe6b026d1979f7b">PSA_ALG_SHA_224</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000008)</td></tr>
+<tr class="separator:ga25d6a3244d10a7148fe6b026d1979f7b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga619471f978e13cdd0a1e37145e4bf341"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga619471f978e13cdd0a1e37145e4bf341">PSA_ALG_SHA_256</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000009)</td></tr>
+<tr class="separator:ga619471f978e13cdd0a1e37145e4bf341"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga58af64dd9a86a287e8da9ed7739eead4"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga58af64dd9a86a287e8da9ed7739eead4">PSA_ALG_SHA_384</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000a)</td></tr>
+<tr class="separator:ga58af64dd9a86a287e8da9ed7739eead4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafba3ae409f46d3dd7f37a0910660c3e9"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gafba3ae409f46d3dd7f37a0910660c3e9">PSA_ALG_SHA_512</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000b)</td></tr>
+<tr class="separator:gafba3ae409f46d3dd7f37a0910660c3e9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3fe2d7c3c80e3186ca78d16a35d5d931"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga3fe2d7c3c80e3186ca78d16a35d5d931">PSA_ALG_SHA_512_224</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000c)</td></tr>
+<tr class="separator:ga3fe2d7c3c80e3186ca78d16a35d5d931"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5910b3964c14e9613e8643a45b09c2d4"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga5910b3964c14e9613e8643a45b09c2d4">PSA_ALG_SHA_512_256</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000d)</td></tr>
+<tr class="separator:ga5910b3964c14e9613e8643a45b09c2d4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga16f5fe34ccce68c2fada1224c054a999"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga16f5fe34ccce68c2fada1224c054a999">PSA_ALG_SHA3_224</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000010)</td></tr>
+<tr class="separator:ga16f5fe34ccce68c2fada1224c054a999"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaace70d9515489bbe3c5e7ac1b7d9155b"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaace70d9515489bbe3c5e7ac1b7d9155b">PSA_ALG_SHA3_256</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000011)</td></tr>
+<tr class="separator:gaace70d9515489bbe3c5e7ac1b7d9155b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab0f079257ea75e2acfe2fc3b38c78cd8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gab0f079257ea75e2acfe2fc3b38c78cd8">PSA_ALG_SHA3_384</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000012)</td></tr>
+<tr class="separator:gab0f079257ea75e2acfe2fc3b38c78cd8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga37e5dbe936dddb155e76f2997de27188"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga37e5dbe936dddb155e76f2997de27188">PSA_ALG_SHA3_512</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000013)</td></tr>
+<tr class="separator:ga37e5dbe936dddb155e76f2997de27188"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gabba3fcfee55533b0e25350e78a942e07"><td class="memItemLeft" align="right" valign="top"><a id="gabba3fcfee55533b0e25350e78a942e07"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_MAC_SUBCATEGORY_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00c00000)</td></tr>
+<tr class="separator:gabba3fcfee55533b0e25350e78a942e07"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga0675192b82720fb8c9037a95bdeb6c88"><td class="memItemLeft" align="right" valign="top"><a id="ga0675192b82720fb8c9037a95bdeb6c88"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_HMAC_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02800000)</td></tr>
+<tr class="separator:ga0675192b82720fb8c9037a95bdeb6c88"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga70f397425684b3efcde1e0e34c28261f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga70f397425684b3efcde1e0e34c28261f">PSA_ALG_HMAC</a>(hash_alg)   (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga70f397425684b3efcde1e0e34c28261f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6ac4f9564237dfd8d28e988da41bc931"><td class="memItemLeft" align="right" valign="top"><a id="ga6ac4f9564237dfd8d28e988da41bc931"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_HMAC_HASH</b>(hmac_alg)   (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga6ac4f9564237dfd8d28e988da41bc931"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4a050c3c3cbc6eb96418f18847601c8a"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga4a050c3c3cbc6eb96418f18847601c8a">PSA_ALG_IS_HMAC</a>(alg)</td></tr>
+<tr class="separator:ga4a050c3c3cbc6eb96418f18847601c8a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaee0c29980b08305f6d0e7b3fbb588ade"><td class="memItemLeft" align="right" valign="top"><a id="gaee0c29980b08305f6d0e7b3fbb588ade"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CIPHER_MAC_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02c00000)</td></tr>
+<tr class="separator:gaee0c29980b08305f6d0e7b3fbb588ade"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga20bdc755de7b90f6621ccb1e6bb5d9e1"><td class="memItemLeft" align="right" valign="top"><a id="ga20bdc755de7b90f6621ccb1e6bb5d9e1"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CBC_MAC</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02c00001)</td></tr>
+<tr class="separator:ga20bdc755de7b90f6621ccb1e6bb5d9e1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga146328a1e0023a02464e232d6ecefdc2"><td class="memItemLeft" align="right" valign="top"><a id="ga146328a1e0023a02464e232d6ecefdc2"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CMAC</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02c00002)</td></tr>
+<tr class="separator:ga146328a1e0023a02464e232d6ecefdc2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga69a012ce150219a2d97c3ab5582f0004"><td class="memItemLeft" align="right" valign="top"><a id="ga69a012ce150219a2d97c3ab5582f0004"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_GMAC</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x02c00003)</td></tr>
+<tr class="separator:ga69a012ce150219a2d97c3ab5582f0004"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8986360ff97dbd91f220edf9202e375d"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga8986360ff97dbd91f220edf9202e375d">PSA_ALG_IS_CIPHER_MAC</a>(alg)</td></tr>
+<tr class="separator:ga8986360ff97dbd91f220edf9202e375d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga5e09871380b1dd62be19732b4736313b"><td class="memItemLeft" align="right" valign="top"><a id="ga5e09871380b1dd62be19732b4736313b"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CIPHER_SUBCATEGORY_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00c00000)</td></tr>
+<tr class="separator:ga5e09871380b1dd62be19732b4736313b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga8441c6d5dfe158d2d8a7540a9a0ebb39"><td class="memItemLeft" align="right" valign="top"><a id="ga8441c6d5dfe158d2d8a7540a9a0ebb39"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_BLOCK_CIPHER_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000000)</td></tr>
+<tr class="separator:ga8441c6d5dfe158d2d8a7540a9a0ebb39"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6bd5e2da108ecb82ac6fd3eb746424ef"><td class="memItemLeft" align="right" valign="top"><a id="ga6bd5e2da108ecb82ac6fd3eb746424ef"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_BLOCK_CIPHER_MODE_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x000000ff)</td></tr>
+<tr class="separator:ga6bd5e2da108ecb82ac6fd3eb746424ef"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga61c792645f8e5aa42fc8b3392fe53231"><td class="memItemLeft" align="right" valign="top"><a id="ga61c792645f8e5aa42fc8b3392fe53231"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_BLOCK_CIPHER_PADDING_MASK</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x003f0000)</td></tr>
+<tr class="separator:ga61c792645f8e5aa42fc8b3392fe53231"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga0992d26a02a2a7dc316cd5abc5254966"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga0992d26a02a2a7dc316cd5abc5254966">PSA_ALG_BLOCK_CIPHER_PAD_NONE</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00000000)</td></tr>
+<tr class="separator:ga0992d26a02a2a7dc316cd5abc5254966"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga40066e494138ef20dfc8de22825b4057"><td class="memItemLeft" align="right" valign="top"><a id="ga40066e494138ef20dfc8de22825b4057"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_BLOCK_CIPHER_PAD_PKCS7</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00010000)</td></tr>
+<tr class="separator:ga40066e494138ef20dfc8de22825b4057"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga02e787d79c0cd666efcd090569d5b31c"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga02e787d79c0cd666efcd090569d5b31c">PSA_ALG_IS_BLOCK_CIPHER</a>(alg)</td></tr>
+<tr class="separator:ga02e787d79c0cd666efcd090569d5b31c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga931f31d4f05c3dab9fd5d7fdcd3715f2"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga931f31d4f05c3dab9fd5d7fdcd3715f2">PSA_ALG_CBC_BASE</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000001)</td></tr>
+<tr class="separator:ga931f31d4f05c3dab9fd5d7fdcd3715f2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa04cf3217f724b219f2a054b98c554fe"><td class="memItemLeft" align="right" valign="top"><a id="gaa04cf3217f724b219f2a054b98c554fe"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CFB_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000002)</td></tr>
+<tr class="separator:gaa04cf3217f724b219f2a054b98c554fe"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7a1c7906c13a78ad62463c2b68869999"><td class="memItemLeft" align="right" valign="top"><a id="ga7a1c7906c13a78ad62463c2b68869999"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_OFB_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000003)</td></tr>
+<tr class="separator:ga7a1c7906c13a78ad62463c2b68869999"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga914d820b488366067023ba6ed363ee83"><td class="memItemLeft" align="right" valign="top"><a id="ga914d820b488366067023ba6ed363ee83"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_XTS_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000004)</td></tr>
+<tr class="separator:ga914d820b488366067023ba6ed363ee83"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaff1ae6bbbe3898273035c237731a6ed6"><td class="memItemLeft" align="right" valign="top"><a id="gaff1ae6bbbe3898273035c237731a6ed6"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_STREAM_CIPHER_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04800000)</td></tr>
+<tr class="separator:gaff1ae6bbbe3898273035c237731a6ed6"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad318309706a769cffdc64e4c7e06b2e9"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gad318309706a769cffdc64e4c7e06b2e9">PSA_ALG_CTR</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04800001)</td></tr>
+<tr class="separator:gad318309706a769cffdc64e4c7e06b2e9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab6a5284decb0e5e1b5b8740a41ef3c5e"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gab6a5284decb0e5e1b5b8740a41ef3c5e">PSA_ALG_ARC4</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04800002)</td></tr>
+<tr class="separator:gab6a5284decb0e5e1b5b8740a41ef3c5e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gacfec68e0c6175e02e1b2ebc97df383c0"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gacfec68e0c6175e02e1b2ebc97df383c0">PSA_ALG_IS_STREAM_CIPHER</a>(alg)</td></tr>
+<tr class="separator:gacfec68e0c6175e02e1b2ebc97df383c0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac2c0e7d21f1b2df5e76bcb4a8f84273c"><td class="memItemLeft" align="right" valign="top"><a id="gac2c0e7d21f1b2df5e76bcb4a8f84273c"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_CCM</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x06000001)</td></tr>
+<tr class="separator:gac2c0e7d21f1b2df5e76bcb4a8f84273c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga0d7d02b15aaae490d38277d99f1c637c"><td class="memItemLeft" align="right" valign="top"><a id="ga0d7d02b15aaae490d38277d99f1c637c"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_GCM</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x06000002)</td></tr>
+<tr class="separator:ga0d7d02b15aaae490d38277d99f1c637c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga819b23c9899e92e9f867c7b2ae8f264c"><td class="memItemLeft" align="right" valign="top"><a id="ga819b23c9899e92e9f867c7b2ae8f264c"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_RSA_PKCS1V15_SIGN_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10020000)</td></tr>
+<tr class="separator:ga819b23c9899e92e9f867c7b2ae8f264c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga702ff75385a6ae7d4247033f479439af"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga702ff75385a6ae7d4247033f479439af">PSA_ALG_RSA_PKCS1V15_SIGN</a>(hash_alg)   (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga702ff75385a6ae7d4247033f479439af"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4215e2a78dcf834e9a625927faa2a817"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga4215e2a78dcf834e9a625927faa2a817">PSA_ALG_RSA_PKCS1V15_SIGN_RAW</a>   PSA_ALG_RSA_PKCS1V15_SIGN_BASE</td></tr>
+<tr class="separator:ga4215e2a78dcf834e9a625927faa2a817"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga9d545279f23d43b1b2a744d0dd6826d0"><td class="memItemLeft" align="right" valign="top"><a id="ga9d545279f23d43b1b2a744d0dd6826d0"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_RSA_PKCS1V15_SIGN</b>(alg)   (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE)</td></tr>
+<tr class="separator:ga9d545279f23d43b1b2a744d0dd6826d0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga49d39a343790971b7a74644f4faea0c0"><td class="memItemLeft" align="right" valign="top"><a id="ga49d39a343790971b7a74644f4faea0c0"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_RSA_PSS_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10030000)</td></tr>
+<tr class="separator:ga49d39a343790971b7a74644f4faea0c0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga62152bf4cb4bf6aace5e1be8f143564d"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga62152bf4cb4bf6aace5e1be8f143564d">PSA_ALG_RSA_PSS</a>(hash_alg)   (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga62152bf4cb4bf6aace5e1be8f143564d"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafa04fae7393a76d5161558768cb82a78"><td class="memItemLeft" align="right" valign="top"><a id="gafa04fae7393a76d5161558768cb82a78"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_RSA_PSS</b>(alg)   (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE)</td></tr>
+<tr class="separator:gafa04fae7393a76d5161558768cb82a78"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga863284106894476e3a8524805410b55b"><td class="memItemLeft" align="right" valign="top"><a id="ga863284106894476e3a8524805410b55b"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DSA_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10040000)</td></tr>
+<tr class="separator:ga863284106894476e3a8524805410b55b"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga9a68efdddff5ae95f104a1416b12742e"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga9a68efdddff5ae95f104a1416b12742e">PSA_ALG_DSA</a>(hash_alg)   (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga9a68efdddff5ae95f104a1416b12742e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad3800dafc62d6a17bcae4bce98402e68"><td class="memItemLeft" align="right" valign="top"><a id="gad3800dafc62d6a17bcae4bce98402e68"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DETERMINISTIC_DSA_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10050000)</td></tr>
+<tr class="separator:gad3800dafc62d6a17bcae4bce98402e68"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1d2a96f788cce4f8fc156d13342e70de"><td class="memItemLeft" align="right" valign="top"><a id="ga1d2a96f788cce4f8fc156d13342e70de"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DSA_DETERMINISTIC_FLAG</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00010000)</td></tr>
+<tr class="separator:ga1d2a96f788cce4f8fc156d13342e70de"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab8eb98fb6d2e094e47f3b44dfe128f94"><td class="memItemLeft" align="right" valign="top"><a id="gab8eb98fb6d2e094e47f3b44dfe128f94"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DETERMINISTIC_DSA</b>(hash_alg)   (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:gab8eb98fb6d2e094e47f3b44dfe128f94"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gacfc3cd50ef0c4bf694cf936079bcbaee"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_DSA</b>(alg)</td></tr>
+<tr class="separator:gacfc3cd50ef0c4bf694cf936079bcbaee"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae01ae792228c16eac05102f8e900efd1"><td class="memItemLeft" align="right" valign="top"><a id="gae01ae792228c16eac05102f8e900efd1"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DSA_IS_DETERMINISTIC</b>(alg)   (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)</td></tr>
+<tr class="separator:gae01ae792228c16eac05102f8e900efd1"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga11f7d6fe7a4441143ed398420b7d1980"><td class="memItemLeft" align="right" valign="top"><a id="ga11f7d6fe7a4441143ed398420b7d1980"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_DETERMINISTIC_DSA</b>(alg)   (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg))</td></tr>
+<tr class="separator:ga11f7d6fe7a4441143ed398420b7d1980"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga474c0582c4726d0c0274e470f4199cf9"><td class="memItemLeft" align="right" valign="top"><a id="ga474c0582c4726d0c0274e470f4199cf9"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_RANDOMIZED_DSA</b>(alg)   (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg))</td></tr>
+<tr class="separator:ga474c0582c4726d0c0274e470f4199cf9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafd9800fdbe6ea881e0ac0ce03d145928"><td class="memItemLeft" align="right" valign="top"><a id="gafd9800fdbe6ea881e0ac0ce03d145928"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_ECDSA_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10060000)</td></tr>
+<tr class="separator:gafd9800fdbe6ea881e0ac0ce03d145928"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7e3ce9f514a227d5ba5d8318870452e3"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga7e3ce9f514a227d5ba5d8318870452e3">PSA_ALG_ECDSA</a>(hash_alg)   (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga7e3ce9f514a227d5ba5d8318870452e3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga51d6b6044a62e33cae0cf64bfc3b22a4"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga51d6b6044a62e33cae0cf64bfc3b22a4">PSA_ALG_ECDSA_ANY</a>   PSA_ALG_ECDSA_BASE</td></tr>
+<tr class="separator:ga51d6b6044a62e33cae0cf64bfc3b22a4"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga6c08b65200140aeb46ee9db9c8ed878c"><td class="memItemLeft" align="right" valign="top"><a id="ga6c08b65200140aeb46ee9db9c8ed878c"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_DETERMINISTIC_ECDSA_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x10070000)</td></tr>
+<tr class="separator:ga6c08b65200140aeb46ee9db9c8ed878c"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga11da566bcd341661c8de921e2ca5ed03"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga11da566bcd341661c8de921e2ca5ed03">PSA_ALG_DETERMINISTIC_ECDSA</a>(hash_alg)   (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga11da566bcd341661c8de921e2ca5ed03"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gafb92dc138c9d2388033ff5fc1dab7b48"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_ECDSA</b>(alg)</td></tr>
+<tr class="separator:gafb92dc138c9d2388033ff5fc1dab7b48"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaced29d8e3a1740aaec01e9ef8211df4f"><td class="memItemLeft" align="right" valign="top"><a id="gaced29d8e3a1740aaec01e9ef8211df4f"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_ECDSA_IS_DETERMINISTIC</b>(alg)   (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)</td></tr>
+<tr class="separator:gaced29d8e3a1740aaec01e9ef8211df4f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gacd8766fe0fb8c1e2d32644e0d092c43a"><td class="memItemLeft" align="right" valign="top"><a id="gacd8766fe0fb8c1e2d32644e0d092c43a"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_DETERMINISTIC_ECDSA</b>(alg)   (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))</td></tr>
+<tr class="separator:gacd8766fe0fb8c1e2d32644e0d092c43a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae7b0fafebd139f6f815285b7cad622ea"><td class="memItemLeft" align="right" valign="top"><a id="gae7b0fafebd139f6f815285b7cad622ea"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_RANDOMIZED_ECDSA</b>(alg)   (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))</td></tr>
+<tr class="separator:gae7b0fafebd139f6f815285b7cad622ea"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga24cf6d7bcd2b9aeeeff86f07b6c674e3"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga24cf6d7bcd2b9aeeeff86f07b6c674e3">PSA_ALG_SIGN_GET_HASH</a>(alg)</td></tr>
+<tr class="separator:ga24cf6d7bcd2b9aeeeff86f07b6c674e3"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4c540d3abe43fb9abcb94f2bc51acef9"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga4c540d3abe43fb9abcb94f2bc51acef9">PSA_ALG_RSA_PKCS1V15_CRYPT</a>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x12020000)</td></tr>
+<tr class="separator:ga4c540d3abe43fb9abcb94f2bc51acef9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga67ba62fbd154f5d3098866ae68ba66eb"><td class="memItemLeft" align="right" valign="top"><a id="ga67ba62fbd154f5d3098866ae68ba66eb"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_RSA_OAEP_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x12030000)</td></tr>
+<tr class="separator:ga67ba62fbd154f5d3098866ae68ba66eb"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa1235dc3fdd9839c6c1b1a9857344c76"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gaa1235dc3fdd9839c6c1b1a9857344c76">PSA_ALG_RSA_OAEP</a>(hash_alg)   (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:gaa1235dc3fdd9839c6c1b1a9857344c76"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga9a85c05fd5c39ca63bbc47fb0755da39"><td class="memItemLeft" align="right" valign="top"><a id="ga9a85c05fd5c39ca63bbc47fb0755da39"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_IS_RSA_OAEP</b>(alg)   (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE)</td></tr>
+<tr class="separator:ga9a85c05fd5c39ca63bbc47fb0755da39"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae6b0b87aabe82a1b3113824f022c52e8"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_RSA_OAEP_GET_HASH</b>(alg)</td></tr>
+<tr class="separator:gae6b0b87aabe82a1b3113824f022c52e8"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga85fe668f95a1e65b573dc5acb798be6f"><td class="memItemLeft" align="right" valign="top"><a id="ga85fe668f95a1e65b573dc5acb798be6f"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_HKDF_BASE</b>   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x30000100)</td></tr>
+<tr class="separator:ga85fe668f95a1e65b573dc5acb798be6f"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga32a888fb360e6e25cab8a343772c4a82"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga32a888fb360e6e25cab8a343772c4a82">PSA_ALG_HKDF</a>(hash_alg)   (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga32a888fb360e6e25cab8a343772c4a82"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1979d0a76fcee6164cf2e65960f38db2"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga1979d0a76fcee6164cf2e65960f38db2">PSA_ALG_IS_HKDF</a>(alg)   (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE)</td></tr>
+<tr class="separator:ga1979d0a76fcee6164cf2e65960f38db2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga643df48b529b176995927b697ff07a4c"><td class="memItemLeft" align="right" valign="top"><a id="ga643df48b529b176995927b697ff07a4c"></a>
+#define </td><td class="memItemRight" valign="bottom"><b>PSA_ALG_HKDF_GET_HASH</b>(hkdf_alg)   (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK))</td></tr>
+<tr class="separator:ga643df48b529b176995927b697ff07a4c"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ga578159487dfc7096cb191b0d2befe628"><td class="memItemLeft" align="right" valign="top"><a id="ga578159487dfc7096cb191b0d2befe628"></a>
+typedef uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a></td></tr>
+<tr class="memdesc:ga578159487dfc7096cb191b0d2befe628"><td class="mdescLeft"> </td><td class="mdescRight">Encoding of a key type. <br /></td></tr>
+<tr class="separator:ga578159487dfc7096cb191b0d2befe628"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4e8977c145cce5077c4bce7fec890ad9"><td class="memItemLeft" align="right" valign="top">typedef uint16_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a></td></tr>
+<tr class="separator:ga4e8977c145cce5077c4bce7fec890ad9"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac2e4d47f1300d73c2f829a6d99252d69"><td class="memItemLeft" align="right" valign="top">typedef uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a></td></tr>
+<tr class="memdesc:gac2e4d47f1300d73c2f829a6d99252d69"><td class="mdescLeft"> </td><td class="mdescRight">Encoding of a cryptographic algorithm. <a href="#gac2e4d47f1300d73c2f829a6d99252d69">More...</a><br /></td></tr>
+<tr class="separator:gac2e4d47f1300d73c2f829a6d99252d69"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="gab6a5284decb0e5e1b5b8740a41ef3c5e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gab6a5284decb0e5e1b5b8740a41ef3c5e">◆ </a></span>PSA_ALG_ARC4</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_ARC4   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04800002)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The ARC4 stream cipher algorithm. </p>
+
+</div>
+</div>
+<a id="ga0992d26a02a2a7dc316cd5abc5254966"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga0992d26a02a2a7dc316cd5abc5254966">◆ </a></span>PSA_ALG_BLOCK_CIPHER_PAD_NONE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_BLOCK_CIPHER_PAD_NONE   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x00000000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Use a block cipher mode without padding.</p>
+<p>This padding mode may only be used with messages whose lengths are a whole number of blocks for the chosen block cipher. </p>
+
+</div>
+</div>
+<a id="ga931f31d4f05c3dab9fd5d7fdcd3715f2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga931f31d4f05c3dab9fd5d7fdcd3715f2">◆ </a></span>PSA_ALG_CBC_BASE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_CBC_BASE   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04000001)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The CBC block cipher mode. </p>
+
+</div>
+</div>
+<a id="gad318309706a769cffdc64e4c7e06b2e9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gad318309706a769cffdc64e4c7e06b2e9">◆ </a></span>PSA_ALG_CTR</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_CTR   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x04800001)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The CTR stream cipher mode.</p>
+<p>CTR is a stream cipher which is built from a block cipher. The underlying block cipher is determined by the key type. For example, to use AES-128-CTR, use this algorithm with a key of type <a class="el" href="group__crypto__types.html#ga6ee54579dcf278c677eda4bb1a29575e">PSA_KEY_TYPE_AES</a> and a length of 128 bits (16 bytes). </p>
+
+</div>
+</div>
+<a id="ga11da566bcd341661c8de921e2ca5ed03"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga11da566bcd341661c8de921e2ca5ed03">◆ </a></span>PSA_ALG_DETERMINISTIC_ECDSA</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_DETERMINISTIC_ECDSA</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">hash_alg</td><td>)</td>
+ <td>   (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Deterministic ECDSA signature with hashing.</p>
+<p>This is the deterministic ECDSA signature scheme defined by RFC 6979.</p>
+<p>The representation of a signature is the same as with <a class="el" href="group__crypto__types.html#ga7e3ce9f514a227d5ba5d8318870452e3">PSA_ALG_ECDSA()</a>.</p>
+<p>Note that when this algorithm is used for verification, signatures made with randomized ECDSA (<a class="el" href="group__crypto__types.html#ga7e3ce9f514a227d5ba5d8318870452e3">PSA_ALG_ECDSA</a>(<code>hash_alg</code>)) with the same private key are accepted. In other words, <a class="el" href="group__crypto__types.html#ga11da566bcd341661c8de921e2ca5ed03">PSA_ALG_DETERMINISTIC_ECDSA</a>(<code>hash_alg</code>) differs from <a class="el" href="group__crypto__types.html#ga7e3ce9f514a227d5ba5d8318870452e3">PSA_ALG_ECDSA</a>(<code>hash_alg</code>) only for signature, not for verification.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">hash_alg</td><td>A hash algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(<code>hash_alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The corresponding deterministic ECDSA signature algorithm. </dd>
+<dd>
+Unspecified if <code>alg</code> is not a supported hash algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="ga9a68efdddff5ae95f104a1416b12742e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga9a68efdddff5ae95f104a1416b12742e">◆ </a></span>PSA_ALG_DSA</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_DSA</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">hash_alg</td><td>)</td>
+ <td>   (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>DSA signature with hashing.</p>
+<p>This is the signature scheme defined by FIPS 186-4, with a random per-message secret number (<em>k</em>).</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">hash_alg</td><td>A hash algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(<code>hash_alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The corresponding DSA signature algorithm. </dd>
+<dd>
+Unspecified if <code>alg</code> is not a supported hash algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="ga7e3ce9f514a227d5ba5d8318870452e3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7e3ce9f514a227d5ba5d8318870452e3">◆ </a></span>PSA_ALG_ECDSA</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_ECDSA</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">hash_alg</td><td>)</td>
+ <td>   (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>ECDSA signature with hashing.</p>
+<p>This is the ECDSA signature scheme defined by ANSI X9.62, with a random per-message secret number (<em>k</em>).</p>
+<p>The representation of the signature as a byte string consists of the concatentation of the signature values <em>r</em> and <em>s</em>. Each of <em>r</em> and <em>s</em> is encoded as an <em>N</em>-octet string, where <em>N</em> is the length of the base point of the curve in octets. Each value is represented in big-endian order (most significant octet first).</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">hash_alg</td><td>A hash algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(<code>hash_alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The corresponding ECDSA signature algorithm. </dd>
+<dd>
+Unspecified if <code>alg</code> is not a supported hash algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="ga51d6b6044a62e33cae0cf64bfc3b22a4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga51d6b6044a62e33cae0cf64bfc3b22a4">◆ </a></span>PSA_ALG_ECDSA_ANY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_ECDSA_ANY   PSA_ALG_ECDSA_BASE</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>ECDSA signature without hashing.</p>
+<p>This is the same signature scheme as <a class="el" href="group__crypto__types.html#ga7e3ce9f514a227d5ba5d8318870452e3">PSA_ALG_ECDSA()</a>, but without specifying a hash algorithm. This algorithm may only be used to sign or verify a sequence of bytes that should be an already-calculated hash. Note that the input is padded with zeros on the left or truncated on the left as required to fit the curve size. </p>
+
+</div>
+</div>
+<a id="ga32a888fb360e6e25cab8a343772c4a82"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga32a888fb360e6e25cab8a343772c4a82">◆ </a></span>PSA_ALG_HKDF</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_HKDF</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">hash_alg</td><td>)</td>
+ <td>   (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Macro to build an HKDF algorithm.</p>
+<p>For example, <code><a class="el" href="group__crypto__types.html#ga32a888fb360e6e25cab8a343772c4a82">PSA_ALG_HKDF(PSA_ALG_SHA256)</a></code> is HKDF using HMAC-SHA-256.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">hash_alg</td><td>A hash algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(<code>hash_alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The corresponding HKDF algorithm. </dd>
+<dd>
+Unspecified if <code>alg</code> is not a supported hash algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="ga70f397425684b3efcde1e0e34c28261f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga70f397425684b3efcde1e0e34c28261f">◆ </a></span>PSA_ALG_HMAC</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_HMAC</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">hash_alg</td><td>)</td>
+ <td>   (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Macro to build an HMAC algorithm.</p>
+<p>For example, <a class="el" href="group__crypto__types.html#ga70f397425684b3efcde1e0e34c28261f">PSA_ALG_HMAC</a>(<a class="el" href="group__crypto__types.html#ga619471f978e13cdd0a1e37145e4bf341">PSA_ALG_SHA_256</a>) is HMAC-SHA-256.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">hash_alg</td><td>A hash algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(<code>hash_alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The corresponding HMAC algorithm. </dd>
+<dd>
+Unspecified if <code>alg</code> is not a supported hash algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="ga1d44829d60065eaa4ac9a703e7d6abc8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1d44829d60065eaa4ac9a703e7d6abc8">◆ </a></span>PSA_ALG_IS_AEAD</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_AEAD</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td>   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the specified algorithm is an authenticated encryption with associated data (AEAD) algorithm.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is an AEAD algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="ga41d2ee937d54efd76bd54a97b2ebc08a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga41d2ee937d54efd76bd54a97b2ebc08a">◆ </a></span>PSA_ALG_IS_ASYMMETRIC_ENCRYPTION</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td>   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the specified algorithm is a public-key encryption algorithm.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is a public-key encryption algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="ga02e787d79c0cd666efcd090569d5b31c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga02e787d79c0cd666efcd090569d5b31c">◆ </a></span>PSA_ALG_IS_BLOCK_CIPHER</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_BLOCK_CIPHER</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_SUBCATEGORY_MASK)) == \</div><div class="line"> PSA_ALG_BLOCK_CIPHER_BASE)</div></div><!-- fragment --><p>Whether the specified algorithm is a block cipher.</p>
+<p>A block cipher is a symmetric cipher that encrypts or decrypts messages by chopping them into fixed-size blocks. Processing a message requires applying a <em>padding mode</em> to transform the message into one whose length is a whole number of blocks. To construct an algorithm identifier for a block cipher, apply a bitwise-or between the block cipher mode and the padding mode. For example, CBC with PKCS#7 padding is <code>PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7</code>.</p>
+<p>The transformation applied to each block is determined by the key type. For example, to use AES-128-CBC-PKCS7, use the algorithm above with a key of type <a class="el" href="group__crypto__types.html#ga6ee54579dcf278c677eda4bb1a29575e">PSA_KEY_TYPE_AES</a> and a length of 128 bits (16 bytes).</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is a block cipher algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier or if it is not a symmetric cipher algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="ga1d1a5a402ad89a2e68f12bfb535490eb"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1d1a5a402ad89a2e68f12bfb535490eb">◆ </a></span>PSA_ALG_IS_CIPHER</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_CIPHER</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td>   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the specified algorithm is a symmetric cipher algorithm.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is a symmetric cipher algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="ga8986360ff97dbd91f220edf9202e375d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga8986360ff97dbd91f220edf9202e375d">◆ </a></span>PSA_ALG_IS_CIPHER_MAC</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_CIPHER_MAC</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \</div><div class="line"> PSA_ALG_CIPHER_MAC_BASE)</div></div><!-- fragment --><p>Whether the specified algorithm is a MAC algorithm based on a block cipher.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is a MAC algorithm based on a block cipher, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="gacfc3cd50ef0c4bf694cf936079bcbaee"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gacfc3cd50ef0c4bf694cf936079bcbaee">◆ </a></span>PSA_ALG_IS_DSA</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_DSA</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \</div><div class="line"> PSA_ALG_DSA_BASE)</div></div><!-- fragment -->
+</div>
+</div>
+<a id="gafb92dc138c9d2388033ff5fc1dab7b48"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gafb92dc138c9d2388033ff5fc1dab7b48">◆ </a></span>PSA_ALG_IS_ECDSA</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_ECDSA</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \</div><div class="line"> PSA_ALG_ECDSA_BASE)</div></div><!-- fragment -->
+</div>
+</div>
+<a id="gac9280662bb482590b4b33d1dcd32930f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac9280662bb482590b4b33d1dcd32930f">◆ </a></span>PSA_ALG_IS_HASH</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_HASH</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td>   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the specified algorithm is a hash algorithm.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is a hash algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="ga1979d0a76fcee6164cf2e65960f38db2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1979d0a76fcee6164cf2e65960f38db2">◆ </a></span>PSA_ALG_IS_HKDF</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_HKDF</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td>   (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the specified algorithm is an HKDF algorithm.</p>
+<p>HKDF is a family of key derivation algorithms that are based on a hash function and the HMAC construction.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is an HKDF algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported key derivation algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="ga4a050c3c3cbc6eb96418f18847601c8a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4a050c3c3cbc6eb96418f18847601c8a">◆ </a></span>PSA_ALG_IS_HMAC</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_HMAC</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \</div><div class="line"> PSA_ALG_HMAC_BASE)</div></div><!-- fragment --><p>Whether the specified algorithm is an HMAC algorithm.</p>
+<p>HMAC is a family of MAC algorithms that are based on a hash function.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is an HMAC algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="ga59753742cb06553bd22751bbef472b6f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga59753742cb06553bd22751bbef472b6f">◆ </a></span>PSA_ALG_IS_KEY_AGREEMENT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_KEY_AGREEMENT</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td>   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the specified algorithm is a key agreement algorithm.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is a key agreement algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="gaf8b90c648aa53dbd06c236695e300cd0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf8b90c648aa53dbd06c236695e300cd0">◆ </a></span>PSA_ALG_IS_KEY_DERIVATION</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_KEY_DERIVATION</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td>   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the specified algorithm is a key derivation algorithm.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is a key derivation algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="gaca7aee4c9dde316b3b1a150a26eab776"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaca7aee4c9dde316b3b1a150a26eab776">◆ </a></span>PSA_ALG_IS_MAC</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_MAC</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td>   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the specified algorithm is a MAC algorithm.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is a MAC algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="ga6d490d0904e0698f6c1268a89d72ff31"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga6d490d0904e0698f6c1268a89d72ff31">◆ </a></span>PSA_ALG_IS_SIGN</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_SIGN</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td>   (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the specified algorithm is a public-key signature algorithm.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is a public-key signature algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier. </dd></dl>
+
+</div>
+</div>
+<a id="gacfec68e0c6175e02e1b2ebc97df383c0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gacfec68e0c6175e02e1b2ebc97df383c0">◆ </a></span>PSA_ALG_IS_STREAM_CIPHER</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_IS_STREAM_CIPHER</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_SUBCATEGORY_MASK)) == \</div><div class="line"> PSA_ALG_STREAM_CIPHER_BASE)</div></div><!-- fragment --><p>Whether the specified algorithm is a stream cipher.</p>
+<p>A stream cipher is a symmetric cipher that encrypts or decrypts messages by applying a bitwise-xor with a stream of bytes that is generated from a key.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>An algorithm identifier (value of type <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>1 if <code>alg</code> is a stream cipher algorithm, 0 otherwise. This macro may return either 0 or 1 if <code>alg</code> is not a supported algorithm identifier or if it is not a symmetric cipher algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="gaa1235dc3fdd9839c6c1b1a9857344c76"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaa1235dc3fdd9839c6c1b1a9857344c76">◆ </a></span>PSA_ALG_RSA_OAEP</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_RSA_OAEP</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">hash_alg</td><td>)</td>
+ <td>   (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>RSA OAEP encryption.</p>
+<p>This is the encryption scheme defined by RFC 8017 (PKCS#1: RSA Cryptography Specifications) under the name RSAES-OAEP, with the message generation function MGF1.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">hash_alg</td><td>The hash algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(<code>hash_alg</code>) is true) to use for MGF1.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The corresponding RSA OAEP signature algorithm. </dd>
+<dd>
+Unspecified if <code>alg</code> is not a supported hash algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="gae6b0b87aabe82a1b3113824f022c52e8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gae6b0b87aabe82a1b3113824f022c52e8">◆ </a></span>PSA_ALG_RSA_OAEP_GET_HASH</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_RSA_OAEP_GET_HASH</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(PSA_ALG_IS_RSA_OAEP(alg) ? \</div><div class="line"> ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \</div><div class="line"> 0)</div></div><!-- fragment -->
+</div>
+</div>
+<a id="ga4c540d3abe43fb9abcb94f2bc51acef9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4c540d3abe43fb9abcb94f2bc51acef9">◆ </a></span>PSA_ALG_RSA_PKCS1V15_CRYPT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_RSA_PKCS1V15_CRYPT   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x12020000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>RSA PKCS#1 v1.5 encryption. </p>
+
+</div>
+</div>
+<a id="ga702ff75385a6ae7d4247033f479439af"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga702ff75385a6ae7d4247033f479439af">◆ </a></span>PSA_ALG_RSA_PKCS1V15_SIGN</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_RSA_PKCS1V15_SIGN</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">hash_alg</td><td>)</td>
+ <td>   (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>RSA PKCS#1 v1.5 signature with hashing.</p>
+<p>This is the signature scheme defined by RFC 8017 (PKCS#1: RSA Cryptography Specifications) under the name RSASSA-PKCS1-v1_5.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">hash_alg</td><td>A hash algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(<code>hash_alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The corresponding RSA PKCS#1 v1.5 signature algorithm. </dd>
+<dd>
+Unspecified if <code>alg</code> is not a supported hash algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="ga4215e2a78dcf834e9a625927faa2a817"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4215e2a78dcf834e9a625927faa2a817">◆ </a></span>PSA_ALG_RSA_PKCS1V15_SIGN_RAW</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW   PSA_ALG_RSA_PKCS1V15_SIGN_BASE</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Raw PKCS#1 v1.5 signature.</p>
+<p>The input to this algorithm is the DigestInfo structure used by RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 steps 3–6. </p>
+
+</div>
+</div>
+<a id="ga62152bf4cb4bf6aace5e1be8f143564d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga62152bf4cb4bf6aace5e1be8f143564d">◆ </a></span>PSA_ALG_RSA_PSS</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_RSA_PSS</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">hash_alg</td><td>)</td>
+ <td>   (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>RSA PSS signature with hashing.</p>
+<p>This is the signature scheme defined by RFC 8017 (PKCS#1: RSA Cryptography Specifications) under the name RSASSA-PSS, with the message generation function MGF1, and with a salt length equal to the length of the hash. The specified hash algorithm is used to hash the input message, to create the salted hash, and for the mask generation.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">hash_alg</td><td>A hash algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(<code>hash_alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The corresponding RSA PSS signature algorithm. </dd>
+<dd>
+Unspecified if <code>alg</code> is not a supported hash algorithm. </dd></dl>
+
+</div>
+</div>
+<a id="ga16f5fe34ccce68c2fada1224c054a999"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga16f5fe34ccce68c2fada1224c054a999">◆ </a></span>PSA_ALG_SHA3_224</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SHA3_224   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000010)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>SHA3-224 </p>
+
+</div>
+</div>
+<a id="gaace70d9515489bbe3c5e7ac1b7d9155b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaace70d9515489bbe3c5e7ac1b7d9155b">◆ </a></span>PSA_ALG_SHA3_256</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SHA3_256   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000011)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>SHA3-256 </p>
+
+</div>
+</div>
+<a id="gab0f079257ea75e2acfe2fc3b38c78cd8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gab0f079257ea75e2acfe2fc3b38c78cd8">◆ </a></span>PSA_ALG_SHA3_384</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SHA3_384   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000012)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>SHA3-384 </p>
+
+</div>
+</div>
+<a id="ga37e5dbe936dddb155e76f2997de27188"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga37e5dbe936dddb155e76f2997de27188">◆ </a></span>PSA_ALG_SHA3_512</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SHA3_512   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000013)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>SHA3-512 </p>
+
+</div>
+</div>
+<a id="ga25d6a3244d10a7148fe6b026d1979f7b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga25d6a3244d10a7148fe6b026d1979f7b">◆ </a></span>PSA_ALG_SHA_224</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SHA_224   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000008)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>SHA2-224 </p>
+
+</div>
+</div>
+<a id="ga619471f978e13cdd0a1e37145e4bf341"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga619471f978e13cdd0a1e37145e4bf341">◆ </a></span>PSA_ALG_SHA_256</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SHA_256   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x01000009)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>SHA2-256 </p>
+
+</div>
+</div>
+<a id="ga58af64dd9a86a287e8da9ed7739eead4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga58af64dd9a86a287e8da9ed7739eead4">◆ </a></span>PSA_ALG_SHA_384</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SHA_384   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000a)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>SHA2-384 </p>
+
+</div>
+</div>
+<a id="gafba3ae409f46d3dd7f37a0910660c3e9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gafba3ae409f46d3dd7f37a0910660c3e9">◆ </a></span>PSA_ALG_SHA_512</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SHA_512   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000b)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>SHA2-512 </p>
+
+</div>
+</div>
+<a id="ga3fe2d7c3c80e3186ca78d16a35d5d931"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3fe2d7c3c80e3186ca78d16a35d5d931">◆ </a></span>PSA_ALG_SHA_512_224</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SHA_512_224   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000c)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>SHA2-512/224 </p>
+
+</div>
+</div>
+<a id="ga5910b3964c14e9613e8643a45b09c2d4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga5910b3964c14e9613e8643a45b09c2d4">◆ </a></span>PSA_ALG_SHA_512_256</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SHA_512_256   ((<a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a>)0x0100000d)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>SHA2-512/256 </p>
+
+</div>
+</div>
+<a id="ga24cf6d7bcd2b9aeeeff86f07b6c674e3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga24cf6d7bcd2b9aeeeff86f07b6c674e3">◆ </a></span>PSA_ALG_SIGN_GET_HASH</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_ALG_SIGN_GET_HASH</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \</div><div class="line"> PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg) ? \</div><div class="line"> ((alg) & PSA_ALG_HASH_MASK) == 0 ? <span class="comment">/*"raw" algorithm*/</span> 0 : \</div><div class="line"> ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \</div><div class="line"> 0)</div></div><!-- fragment --><p>Get the hash used by a hash-and-sign signature algorithm.</p>
+<p>A hash-and-sign algorithm is a signature algorithm which is composed of two phases: first a hashing phase which does not use the key and produces a hash of the input message, then a signing phase which only uses the hash and the key and not the message itself.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>A signature algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#ga6d490d0904e0698f6c1268a89d72ff31">PSA_ALG_IS_SIGN</a>(<code>alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The underlying hash algorithm if <code>alg</code> is a hash-and-sign algorithm. </dd>
+<dd>
+0 if <code>alg</code> is a signature algorithm that does not follow the hash-and-sign structure. </dd>
+<dd>
+Unspecified if <code>alg</code> is not a signature algorithm or if it is not supported by the implementation. </dd></dl>
+
+</div>
+</div>
+<a id="gacaa366bdeb0413e63e87a667c5457b2e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gacaa366bdeb0413e63e87a667c5457b2e">◆ </a></span>PSA_BLOCK_CIPHER_BLOCK_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_BLOCK_CIPHER_BLOCK_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">( \</div><div class="line"> (type) == <a class="code" href="group__crypto__types.html#ga6ee54579dcf278c677eda4bb1a29575e">PSA_KEY_TYPE_AES</a> ? 16 : \</div><div class="line"> (type) == <a class="code" href="group__crypto__types.html#ga577562bfbbc691c820d55ec308333138">PSA_KEY_TYPE_DES</a> ? 8 : \</div><div class="line"> (type) == <a class="code" href="group__crypto__types.html#gad8e5da742343fd5519f9d8a630c2ed81">PSA_KEY_TYPE_CAMELLIA</a> ? 16 : \</div><div class="line"> (type) == <a class="code" href="group__crypto__types.html#gae4d46e83f910dcaa126000a8ed03cde9">PSA_KEY_TYPE_ARC4</a> ? 1 : \</div><div class="line"> 0)</div><div class="ttc" id="group__crypto__types_html_ga577562bfbbc691c820d55ec308333138"><div class="ttname"><a href="group__crypto__types.html#ga577562bfbbc691c820d55ec308333138">PSA_KEY_TYPE_DES</a></div><div class="ttdeci">#define PSA_KEY_TYPE_DES</div><div class="ttdef"><b>Definition:</b> crypto.h:408</div></div>
+<div class="ttc" id="group__crypto__types_html_gad8e5da742343fd5519f9d8a630c2ed81"><div class="ttname"><a href="group__crypto__types.html#gad8e5da742343fd5519f9d8a630c2ed81">PSA_KEY_TYPE_CAMELLIA</a></div><div class="ttdeci">#define PSA_KEY_TYPE_CAMELLIA</div><div class="ttdef"><b>Definition:</b> crypto.h:412</div></div>
+<div class="ttc" id="group__crypto__types_html_ga6ee54579dcf278c677eda4bb1a29575e"><div class="ttname"><a href="group__crypto__types.html#ga6ee54579dcf278c677eda4bb1a29575e">PSA_KEY_TYPE_AES</a></div><div class="ttdeci">#define PSA_KEY_TYPE_AES</div><div class="ttdef"><b>Definition:</b> crypto.h:397</div></div>
+<div class="ttc" id="group__crypto__types_html_gae4d46e83f910dcaa126000a8ed03cde9"><div class="ttname"><a href="group__crypto__types.html#gae4d46e83f910dcaa126000a8ed03cde9">PSA_KEY_TYPE_ARC4</a></div><div class="ttdeci">#define PSA_KEY_TYPE_ARC4</div><div class="ttdef"><b>Definition:</b> crypto.h:418</div></div>
+</div><!-- fragment --><p>The block size of a block cipher.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">type</td><td>A cipher key type (value of type <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628" title="Encoding of a key type. ">psa_key_type_t</a>).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The block size for a block cipher, or 1 for a stream cipher. The return value is undefined if <code>type</code> is not a supported cipher key type.</dd></dl>
+<dl class="section note"><dt>Note</dt><dd>It is possible to build stream cipher algorithms on top of a block cipher, for example CTR mode (<a class="el" href="group__crypto__types.html#gad318309706a769cffdc64e4c7e06b2e9">PSA_ALG_CTR</a>). This macro only takes the key type into account, so it cannot be used to determine the size of the data that <a class="el" href="group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91">psa_cipher_update()</a> might buffer for future processing in general.</dd>
+<dd>
+This macro returns a compile-time constant if its argument is one.</dd></dl>
+<dl class="section warning"><dt>Warning</dt><dd>This macro may evaluate its argument multiple times. </dd></dl>
+
+</div>
+</div>
+<a id="ga6ee54579dcf278c677eda4bb1a29575e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga6ee54579dcf278c677eda4bb1a29575e">◆ </a></span>PSA_KEY_TYPE_AES</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_AES   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000001)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Key for an cipher, AEAD or MAC algorithm based on the AES block cipher.</p>
+<p>The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or 32 bytes (AES-256). </p>
+
+</div>
+</div>
+<a id="gae4d46e83f910dcaa126000a8ed03cde9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gae4d46e83f910dcaa126000a8ed03cde9">◆ </a></span>PSA_KEY_TYPE_ARC4</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_ARC4   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000004)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Key for the RC4 stream cipher.</p>
+<p>Note that RC4 is weak and deprecated and should only be used in legacy protocols. </p>
+
+</div>
+</div>
+<a id="gad8e5da742343fd5519f9d8a630c2ed81"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gad8e5da742343fd5519f9d8a630c2ed81">◆ </a></span>PSA_KEY_TYPE_CAMELLIA</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_CAMELLIA   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000003)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Key for an cipher, AEAD or MAC algorithm based on the Camellia block cipher. </p>
+
+</div>
+</div>
+<a id="gae871b2357b8593f33bfd51abbf93ebb1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gae871b2357b8593f33bfd51abbf93ebb1">◆ </a></span>PSA_KEY_TYPE_DERIVE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_DERIVE   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x02000101)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>A secret for key derivation.</p>
+<p>The key policy determines which key derivation algorithm the key can be used for. </p>
+
+</div>
+</div>
+<a id="ga577562bfbbc691c820d55ec308333138"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga577562bfbbc691c820d55ec308333138">◆ </a></span>PSA_KEY_TYPE_DES</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_DES   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x04000002)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES).</p>
+<p>The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or 24 bytes (3-key 3DES).</p>
+<p>Note that single DES and 2-key 3DES are weak and strongly deprecated and should only be used to decrypt legacy data. 3-key 3DES is weak and deprecated and should only be used in legacy protocols. </p>
+
+</div>
+</div>
+<a id="ga011010ee28c20388f3d89fb27088ed62"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga011010ee28c20388f3d89fb27088ed62">◆ </a></span>PSA_KEY_TYPE_DSA_KEYPAIR</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_DSA_KEYPAIR   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x07020000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>DSA key pair (private and public key). </p>
+
+</div>
+</div>
+<a id="ga5e7439c2905136366c3a876e62e5ddfc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga5e7439c2905136366c3a876e62e5ddfc">◆ </a></span>PSA_KEY_TYPE_DSA_PUBLIC_KEY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_DSA_PUBLIC_KEY   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x06020000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>DSA public key. </p>
+
+</div>
+</div>
+<a id="gadf3ad65d157bf5282849c954bf3f51af"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gadf3ad65d157bf5282849c954bf3f51af">◆ </a></span>PSA_KEY_TYPE_ECC_KEYPAIR</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_ECC_KEYPAIR</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">curve</td><td>)</td>
+ <td>   (PSA_KEY_TYPE_ECC_KEYPAIR_BASE | (curve))</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Elliptic curve key pair. </p>
+
+</div>
+</div>
+<a id="gad54c03d3b47020e571a72cd01d978cf2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gad54c03d3b47020e571a72cd01d978cf2">◆ </a></span>PSA_KEY_TYPE_ECC_PUBLIC_KEY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_ECC_PUBLIC_KEY</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">curve</td><td>)</td>
+ <td>   (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve))</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Elliptic curve public key. </p>
+
+</div>
+</div>
+<a id="ga0c567210e6f80aa8f2aa87efa7a3a3f9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga0c567210e6f80aa8f2aa87efa7a3a3f9">◆ </a></span>PSA_KEY_TYPE_GET_CURVE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_GET_CURVE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">((<a class="code" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a>) (<a class="code" href="group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66">PSA_KEY_TYPE_IS_ECC</a>(type) ? \</div><div class="line"> ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \</div><div class="line"> 0))</div><div class="ttc" id="group__crypto__types_html_ga4e8977c145cce5077c4bce7fec890ad9"><div class="ttname"><a href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a></div><div class="ttdeci">uint16_t psa_ecc_curve_t</div><div class="ttdef"><b>Definition:</b> crypto.h:478</div></div>
+<div class="ttc" id="group__crypto__types_html_ga88e01fa06b585654689a99bcc06bbe66"><div class="ttname"><a href="group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66">PSA_KEY_TYPE_IS_ECC</a></div><div class="ttdeci">#define PSA_KEY_TYPE_IS_ECC(type)</div><div class="ttdef"><b>Definition:</b> crypto.h:467</div></div>
+</div><!-- fragment --><p>Extract the curve from an elliptic curve key type. </p>
+
+</div>
+</div>
+<a id="ga92d989f4ca64abd00f463defd773a6f8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga92d989f4ca64abd00f463defd773a6f8">◆ </a></span>PSA_KEY_TYPE_HMAC</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_HMAC   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x02000001)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>HMAC key.</p>
+<p>The key policy determines which underlying hash algorithm the key can be used for.</p>
+<p>HMAC keys should generally have the same size as the underlying hash. This size can be calculated with <a class="el" href="group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99">PSA_HASH_SIZE</a>(<code>alg</code>) where <code>alg</code> is the HMAC algorithm or the underlying hash algorithm. </p>
+
+</div>
+</div>
+<a id="gab138ae2ebf2905dfbaf4154db2620939"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gab138ae2ebf2905dfbaf4154db2620939">◆ </a></span>PSA_KEY_TYPE_IS_ASYMMETRIC</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_IS_ASYMMETRIC</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td>   (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether a key type is asymmetric: either a key pair or a public key. </p>
+
+</div>
+</div>
+<a id="ga88e01fa06b585654689a99bcc06bbe66"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga88e01fa06b585654689a99bcc06bbe66">◆ </a></span>PSA_KEY_TYPE_IS_ECC</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_IS_ECC</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">((<a class="code" href="group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec">PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR</a>(type) & \</div><div class="line"> ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE)</div><div class="ttc" id="group__crypto__types_html_gace08e46dd7cbf642d50d982a25d02bec"><div class="ttname"><a href="group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec">PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR</a></div><div class="ttdeci">#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type)</div><div class="ttdef"><b>Definition:</b> crypto.h:460</div></div>
+</div><!-- fragment --><p>Whether a key type is an elliptic curve key (pair or public-only). </p>
+
+</div>
+</div>
+<a id="ga7bf101b671e8cf26f4cb08fcb679db4b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7bf101b671e8cf26f4cb08fcb679db4b">◆ </a></span>PSA_KEY_TYPE_IS_ECC_KEYPAIR</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_IS_ECC_KEYPAIR</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \</div><div class="line"> PSA_KEY_TYPE_ECC_KEYPAIR_BASE)</div></div><!-- fragment -->
+</div>
+</div>
+<a id="ga5af146a173b0c84d7e737e2fb6a3c0a7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga5af146a173b0c84d7e737e2fb6a3c0a7">◆ </a></span>PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \</div><div class="line"> PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE)</div></div><!-- fragment -->
+</div>
+</div>
+<a id="gac14c6d6e1b2b7f4a92a7b757465cff29"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac14c6d6e1b2b7f4a92a7b757465cff29">◆ </a></span>PSA_KEY_TYPE_IS_KEYPAIR</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_IS_KEYPAIR</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(((type) & (PSA_KEY_TYPE_CATEGORY_MASK | PSA_KEY_TYPE_PAIR_FLAG)) == \</div><div class="line"> (PSA_KEY_TYPE_CATEGORY_ASYMMETRIC | PSA_KEY_TYPE_PAIR_FLAG))</div></div><!-- fragment --><p>Whether a key type is a key pair containing a private part and a public part. </p>
+
+</div>
+</div>
+<a id="gac674a0f059bc0cb72b47f0c517b4f45b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac674a0f059bc0cb72b47f0c517b4f45b">◆ </a></span>PSA_KEY_TYPE_IS_PUBLIC_KEY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_IS_PUBLIC_KEY</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">(((type) & (PSA_KEY_TYPE_CATEGORY_MASK | PSA_KEY_TYPE_PAIR_FLAG)) == \</div><div class="line"> PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)</div></div><!-- fragment --><p>Whether a key type is the public part of a key pair. </p>
+
+</div>
+</div>
+<a id="ga0e1d8f241228e49c9cadadfb4579ef1a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga0e1d8f241228e49c9cadadfb4579ef1a">◆ </a></span>PSA_KEY_TYPE_IS_RSA</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_IS_RSA</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td>   (<a class="el" href="group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec">PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR</a>(type) == <a class="el" href="group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b">PSA_KEY_TYPE_RSA_PUBLIC_KEY</a>)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether a key type is an RSA key (pair or public-only). </p>
+
+</div>
+</div>
+<a id="gadbe4c086a6562aefe344bc79e51bdfd3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gadbe4c086a6562aefe344bc79e51bdfd3">◆ </a></span>PSA_KEY_TYPE_IS_VENDOR_DEFINED</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_IS_VENDOR_DEFINED</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td>   (((type) & <a class="el" href="group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7">PSA_KEY_TYPE_VENDOR_FLAG</a>) != 0)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether a key type is vendor-defined. </p>
+
+</div>
+</div>
+<a id="gaf09f1ca1de6a7e7cff0fe516f3f6c91d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf09f1ca1de6a7e7cff0fe516f3f6c91d">◆ </a></span>PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td>   ((type) | PSA_KEY_TYPE_PAIR_FLAG)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The key pair type corresponding to a public key type. </p>
+
+</div>
+</div>
+<a id="gafce7ab2b54ce97ea5bff73f13a9f3e5b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gafce7ab2b54ce97ea5bff73f13a9f3e5b">◆ </a></span>PSA_KEY_TYPE_NONE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_NONE   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x00000000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>An invalid key type value.</p>
+<p>Zero is not the encoding of any key type. </p>
+
+</div>
+</div>
+<a id="gace08e46dd7cbf642d50d982a25d02bec"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gace08e46dd7cbf642d50d982a25d02bec">◆ </a></span>PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">type</td><td>)</td>
+ <td>   ((type) & ~PSA_KEY_TYPE_PAIR_FLAG)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The public key type corresponding to a key pair type. </p>
+
+</div>
+</div>
+<a id="gaa97f92025533102616b32d571c940d80"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaa97f92025533102616b32d571c940d80">◆ </a></span>PSA_KEY_TYPE_RAW_DATA</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_RAW_DATA   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x02000000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Raw data.</p>
+<p>A "key" of this type cannot be used for any cryptographic operation. Applications may use this type to store arbitrary data in the keystore. </p>
+
+</div>
+</div>
+<a id="ga581f50687f5d650456925278948f2799"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga581f50687f5d650456925278948f2799">◆ </a></span>PSA_KEY_TYPE_RSA_KEYPAIR</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_RSA_KEYPAIR   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x07010000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>RSA key pair (private and public key). </p>
+
+</div>
+</div>
+<a id="ga9ba0878f56c8bcd1995ac017a74f513b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga9ba0878f56c8bcd1995ac017a74f513b">◆ </a></span>PSA_KEY_TYPE_RSA_PUBLIC_KEY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_RSA_PUBLIC_KEY   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x06010000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>RSA public key. </p>
+
+</div>
+</div>
+<a id="ga8dbaed2fdb1ebae8aa127ad3988516f7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga8dbaed2fdb1ebae8aa127ad3988516f7">◆ </a></span>PSA_KEY_TYPE_VENDOR_FLAG</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_TYPE_VENDOR_FLAG   ((<a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a>)0x80000000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Vendor-defined flag</p>
+<p>Key types defined by this standard will never have the <a class="el" href="group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7">PSA_KEY_TYPE_VENDOR_FLAG</a> bit set. Vendors who define additional key types must use an encoding with the <a class="el" href="group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7">PSA_KEY_TYPE_VENDOR_FLAG</a> bit set and should respect the bitwise structure used by standard encodings whenever practical. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="gac2e4d47f1300d73c2f829a6d99252d69"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac2e4d47f1300d73c2f829a6d99252d69">◆ </a></span>psa_algorithm_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef uint32_t <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Encoding of a cryptographic algorithm. </p>
+<p>For algorithms that can be applied to multiple key types, this type does not encode the key type. For example, for symmetric ciphers based on a block cipher, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69" title="Encoding of a cryptographic algorithm. ">psa_algorithm_t</a> encodes the block cipher mode and the padding mode while the block cipher itself is encoded via <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628" title="Encoding of a key type. ">psa_key_type_t</a>. </p>
+
+</div>
+</div>
+<a id="ga4e8977c145cce5077c4bce7fec890ad9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4e8977c145cce5077c4bce7fec890ad9">◆ </a></span>psa_ecc_curve_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef uint16_t <a class="el" href="group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9">psa_ecc_curve_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The type of PSA elliptic curve identifiers. </p>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__derivation.html b/docs/html/group__derivation.html
new file mode 100644
index 0000000..dd9ffb8
--- /dev/null
+++ b/docs/html/group__derivation.html
@@ -0,0 +1,180 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Key derivation</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Key derivation</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga1b6429f443a45e5f3209043abbbe8315"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__derivation.html#ga1b6429f443a45e5f3209043abbbe8315">psa_key_derivation</a> (<a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator, <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg, const uint8_t *salt, size_t salt_length, const uint8_t *label, size_t label_length, size_t capacity)</td></tr>
+<tr class="separator:ga1b6429f443a45e5f3209043abbbe8315"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga1b6429f443a45e5f3209043abbbe8315"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1b6429f443a45e5f3209043abbbe8315">◆ </a></span>psa_key_derivation()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_key_derivation </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> * </td>
+ <td class="paramname"><em>generator</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>salt</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>salt_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>label</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>label_length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>capacity</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Set up a key derivation operation.</p>
+<p>A key derivation algorithm takes three inputs: a secret input <code>key</code> and two non-secret inputs <code>label</code> and p salt. The result of this function is a byte generator which can be used to produce keys and other cryptographic material.</p>
+<p>The role of <code>label</code> and <code>salt</code> is as follows:</p><ul>
+<li>For HKDF (<a class="el" href="group__crypto__types.html#ga32a888fb360e6e25cab8a343772c4a82">PSA_ALG_HKDF</a>), <code>salt</code> is the salt used in the "extract" step and <code>label</code> is the info string used in the "expand" step.</li>
+</ul>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">generator</td><td>The generator object to set up. It must have been initialized to . </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot containing the secret key to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>The key derivation algorithm to compute (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gaf8b90c648aa53dbd06c236695e300cd0">PSA_ALG_IS_KEY_DERIVATION</a>(<code>alg</code>) is true). </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">salt</td><td>Salt to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">salt_length</td><td>Size of the <code>salt</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">label</td><td>Label to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">label_length</td><td>Size of the <code>label</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">capacity</td><td>The maximum number of bytes that the generator will be able to provide.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td><code>key</code> is not compatible with <code>alg</code>, or <code>capacity</code> is too large for the specified algorithm and key. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td><code>alg</code> is not supported or is not a key derivation algorithm. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__generators.html b/docs/html/group__generators.html
new file mode 100644
index 0000000..37dff72
--- /dev/null
+++ b/docs/html/group__generators.html
@@ -0,0 +1,348 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Generators</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#define-members">Macros</a> |
+<a href="#typedef-members">Typedefs</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Generators</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ga4788b471385fc667876fbd8a0d3fe062"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#ga4788b471385fc667876fbd8a0d3fe062">PSA_CRYPTO_GENERATOR_INIT</a>   {0}</td></tr>
+<tr class="separator:ga4788b471385fc667876fbd8a0d3fe062"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ga1f894c4fba202ef8e307d72caf489e3b"><td class="memItemLeft" align="right" valign="top">typedef struct psa_crypto_generator_s </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a></td></tr>
+<tr class="separator:ga1f894c4fba202ef8e307d72caf489e3b"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga7453491e3b440193be2c5dccc2040fd2"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#ga7453491e3b440193be2c5dccc2040fd2">psa_get_generator_capacity</a> (const <a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator, size_t *capacity)</td></tr>
+<tr class="separator:ga7453491e3b440193be2c5dccc2040fd2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab5712ad29b78c2b170e64cc5bcfc1bce"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#gab5712ad29b78c2b170e64cc5bcfc1bce">psa_generator_read</a> (<a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator, uint8_t *output, size_t output_length)</td></tr>
+<tr class="separator:gab5712ad29b78c2b170e64cc5bcfc1bce"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga06c1ba3d989827d909b4b01ffe983beb"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#ga06c1ba3d989827d909b4b01ffe983beb">psa_generator_import_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> type, size_t bits, <a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator)</td></tr>
+<tr class="separator:ga06c1ba3d989827d909b4b01ffe983beb"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga563ca64537d90368899286b36d8cf7f3"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__generators.html#ga563ca64537d90368899286b36d8cf7f3">psa_generator_abort</a> (<a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> *generator)</td></tr>
+<tr class="separator:ga563ca64537d90368899286b36d8cf7f3"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="ga4788b471385fc667876fbd8a0d3fe062"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4788b471385fc667876fbd8a0d3fe062">◆ </a></span>PSA_CRYPTO_GENERATOR_INIT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_CRYPTO_GENERATOR_INIT   {0}</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>This macro returns a suitable initializer for a generator object of type <a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a>. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="ga1f894c4fba202ef8e307d72caf489e3b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1f894c4fba202ef8e307d72caf489e3b">◆ </a></span>psa_crypto_generator_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef struct psa_crypto_generator_s <a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The type of the state data structure for generators.</p>
+<p>Before calling any function on a generator, the application must initialize it by any of the following means:</p><ul>
+<li>Set the structure to all-bits-zero, for example: <div class="fragment"><div class="line"><a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> generator;</div><div class="line">memset(&generator, 0, <span class="keyword">sizeof</span>(generator));</div></div><!-- fragment --></li>
+<li>Initialize the structure to logical zero values, for example: <div class="fragment"><div class="line"><a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> generator = {0};</div></div><!-- fragment --></li>
+<li>Initialize the structure to the initializer <a class="el" href="group__generators.html#ga4788b471385fc667876fbd8a0d3fe062">PSA_CRYPTO_GENERATOR_INIT</a>, for example: <div class="fragment"><div class="line"><a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> generator = <a class="code" href="group__generators.html#ga4788b471385fc667876fbd8a0d3fe062">PSA_CRYPTO_GENERATOR_INIT</a>;</div></div><!-- fragment --></li>
+<li>Assign the result of the function psa_crypto_generator_init() to the structure, for example: <div class="fragment"><div class="line"><a class="code" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> generator;</div><div class="line">generator = psa_crypto_generator_init();</div></div><!-- fragment --></li>
+</ul>
+<p>This is an implementation-defined <code>struct</code>. Applications should not make any assumptions about the content of this structure except as directed by the documentation of a specific implementation. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga563ca64537d90368899286b36d8cf7f3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga563ca64537d90368899286b36d8cf7f3">◆ </a></span>psa_generator_abort()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_generator_abort </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> * </td>
+ <td class="paramname"><em>generator</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Abort a generator.</p>
+<p>Once a generator has been aborted, its capacity is zero. Aborting a generator frees all associated resources except for the <code>generator</code> structure itself.</p>
+<p>This function may be called at any time as long as the generator object has been initialized to <a class="el" href="group__generators.html#ga4788b471385fc667876fbd8a0d3fe062">PSA_CRYPTO_GENERATOR_INIT</a>, to psa_crypto_generator_init() or a zero value. In particular, it is valid to call <a class="el" href="group__generators.html#ga563ca64537d90368899286b36d8cf7f3">psa_generator_abort()</a> twice, or to call <a class="el" href="group__generators.html#ga563ca64537d90368899286b36d8cf7f3">psa_generator_abort()</a> on a generator that has not been set up.</p>
+<p>Once aborted, the generator object may be called.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">generator</td><td>The generator to abort.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname">PSA_SUCCESS</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_BAD_STATE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_COMMUNICATION_FAILURE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_HARDWARE_FAILURE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_TAMPERING_DETECTED</td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga06c1ba3d989827d909b4b01ffe983beb"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga06c1ba3d989827d909b4b01ffe983beb">◆ </a></span>psa_generator_import_key()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_generator_import_key </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> </td>
+ <td class="paramname"><em>type</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>bits</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> * </td>
+ <td class="paramname"><em>generator</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Create a symmetric key from data read from a generator.</p>
+<p>This function reads a sequence of bytes from a generator and imports these bytes as a key. The data that is read is discarded from the generator. The generator's capacity is decreased by the number of bytes read.</p>
+<p>This function is equivalent to calling <a class="el" href="group__generators.html#gab5712ad29b78c2b170e64cc5bcfc1bce">psa_generator_read</a> and passing the resulting output to <a class="el" href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5" title="Import a key in binary format. ">psa_import_key</a>, but if the implementation provides an isolation boundary then the key material is not exposed outside the isolation boundary.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot where the key will be stored. This must be a valid slot for a key of the chosen type. It must be unoccupied. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">type</td><td>Key type (a <code>PSA_KEY_TYPE_XXX</code> value). This must be a symmetric key type. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">bits</td><td>Key size in bits. </td></tr>
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">generator</td><td>The generator object to read from.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname">PSA_SUCCESS</td><td>Success. </td></tr>
+ <tr><td class="paramname">PSA_ERROR_INSUFFICIENT_CAPACITY</td><td>There were fewer than <code>output_length</code> bytes in the generator. Note that in this case, no output is written to the output buffer. The generator's capacity is set to 0, thus subsequent calls to this function will not succeed, even with a smaller output buffer. </td></tr>
+ <tr><td class="paramname">PSA_ERROR_NOT_SUPPORTED</td><td>The key type or key size is not supported, either by the implementation in general or in this particular slot. </td></tr>
+ <tr><td class="paramname">PSA_ERROR_BAD_STATE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_INVALID_ARGUMENT</td><td>The key slot is invalid. </td></tr>
+ <tr><td class="paramname">PSA_ERROR_OCCUPIED_SLOT</td><td>There is already a key in the specified slot. </td></tr>
+ <tr><td class="paramname">PSA_ERROR_INSUFFICIENT_MEMORY</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_INSUFFICIENT_STORAGE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_COMMUNICATION_FAILURE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_HARDWARE_FAILURE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_TAMPERING_DETECTED</td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gab5712ad29b78c2b170e64cc5bcfc1bce"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gab5712ad29b78c2b170e64cc5bcfc1bce">◆ </a></span>psa_generator_read()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_generator_read </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> * </td>
+ <td class="paramname"><em>generator</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>output</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>output_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Read some data from a generator.</p>
+<p>This function reads and returns a sequence of bytes from a generator. The data that is read is discarded from the generator. The generator's capacity is decreased by the number of bytes read.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">generator</td><td>The generator object to read from. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">output</td><td>Buffer where the generator output will be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">output_length</td><td>Number of bytes to output.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname">PSA_SUCCESS</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_INSUFFICIENT_CAPACITY</td><td>There were fewer than <code>output_length</code> bytes in the generator. Note that in this case, no output is written to the output buffer. The generator's capacity is set to 0, thus subsequent calls to this function will not succeed, even with a smaller output buffer. </td></tr>
+ <tr><td class="paramname">PSA_ERROR_BAD_STATE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_INSUFFICIENT_MEMORY</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_COMMUNICATION_FAILURE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_HARDWARE_FAILURE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_TAMPERING_DETECTED</td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga7453491e3b440193be2c5dccc2040fd2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7453491e3b440193be2c5dccc2040fd2">◆ </a></span>psa_get_generator_capacity()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_get_generator_capacity </td>
+ <td>(</td>
+ <td class="paramtype">const <a class="el" href="group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b">psa_crypto_generator_t</a> * </td>
+ <td class="paramname"><em>generator</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>capacity</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Retrieve the current capacity of a generator.</p>
+<p>The capacity of a generator is the maximum number of bytes that it can return. Reading <em>N</em> bytes from a generator reduces its capacity by <em>N</em>.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in]</td><td class="paramname">generator</td><td>The generator to query. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">capacity</td><td>On success, the capacity of the generator.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname">PSA_SUCCESS</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_BAD_STATE</td><td></td></tr>
+ <tr><td class="paramname">PSA_ERROR_COMMUNICATION_FAILURE</td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__hash.html b/docs/html/group__hash.html
new file mode 100644
index 0000000..53469be
--- /dev/null
+++ b/docs/html/group__hash.html
@@ -0,0 +1,438 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Message digests</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#define-members">Macros</a> |
+<a href="#typedef-members">Typedefs</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Message digests</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:gaef340331ce3cba2b57e1fc5624bf1f99"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99">PSA_HASH_SIZE</a>(alg)</td></tr>
+<tr class="separator:gaef340331ce3cba2b57e1fc5624bf1f99"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ga3c4205d2ce66c4095fc5c78c25273fab"><td class="memItemLeft" align="right" valign="top">typedef struct psa_hash_operation_s </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a></td></tr>
+<tr class="separator:ga3c4205d2ce66c4095fc5c78c25273fab"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga8d72896cf70fc4d514c5c6b978912515"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup</a> (<a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="separator:ga8d72896cf70fc4d514c5c6b978912515"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga65b16ef97d7f650899b7db4b7d1112ff"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">psa_hash_update</a> (<a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation, const uint8_t *input, size_t input_length)</td></tr>
+<tr class="separator:ga65b16ef97d7f650899b7db4b7d1112ff"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga4795fd06a0067b0adcd92e9627b8c97e"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">psa_hash_finish</a> (<a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation, uint8_t *hash, size_t hash_size, size_t *hash_length)</td></tr>
+<tr class="separator:ga4795fd06a0067b0adcd92e9627b8c97e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7be923c5700c9c70ef77ee9b76d1a5c0"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">psa_hash_verify</a> (<a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation, const uint8_t *hash, size_t hash_length)</td></tr>
+<tr class="separator:ga7be923c5700c9c70ef77ee9b76d1a5c0"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gab0b4d5f9912a615559497a467b532928"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__hash.html#gab0b4d5f9912a615559497a467b532928">psa_hash_abort</a> (<a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> *operation)</td></tr>
+<tr class="separator:gab0b4d5f9912a615559497a467b532928"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="gaef340331ce3cba2b57e1fc5624bf1f99"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaef340331ce3cba2b57e1fc5624bf1f99">◆ </a></span>PSA_HASH_SIZE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_HASH_SIZE</td>
+ <td>(</td>
+ <td class="paramtype"> </td>
+ <td class="paramname">alg</td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<b>Value:</b><div class="fragment"><div class="line">( \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD2 ? 16 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD4 ? 16 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD5 ? 16 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == <a class="code" href="group__crypto__types.html#ga25d6a3244d10a7148fe6b026d1979f7b">PSA_ALG_SHA_224</a> ? 28 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == <a class="code" href="group__crypto__types.html#ga619471f978e13cdd0a1e37145e4bf341">PSA_ALG_SHA_256</a> ? 32 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == <a class="code" href="group__crypto__types.html#ga58af64dd9a86a287e8da9ed7739eead4">PSA_ALG_SHA_384</a> ? 48 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == <a class="code" href="group__crypto__types.html#gafba3ae409f46d3dd7f37a0910660c3e9">PSA_ALG_SHA_512</a> ? 64 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == <a class="code" href="group__crypto__types.html#ga3fe2d7c3c80e3186ca78d16a35d5d931">PSA_ALG_SHA_512_224</a> ? 28 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == <a class="code" href="group__crypto__types.html#ga5910b3964c14e9613e8643a45b09c2d4">PSA_ALG_SHA_512_256</a> ? 32 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == <a class="code" href="group__crypto__types.html#ga16f5fe34ccce68c2fada1224c054a999">PSA_ALG_SHA3_224</a> ? 28 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == <a class="code" href="group__crypto__types.html#gaace70d9515489bbe3c5e7ac1b7d9155b">PSA_ALG_SHA3_256</a> ? 32 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == <a class="code" href="group__crypto__types.html#gab0f079257ea75e2acfe2fc3b38c78cd8">PSA_ALG_SHA3_384</a> ? 48 : \</div><div class="line"> PSA_ALG_HMAC_HASH(alg) == <a class="code" href="group__crypto__types.html#ga37e5dbe936dddb155e76f2997de27188">PSA_ALG_SHA3_512</a> ? 64 : \</div><div class="line"> 0)</div><div class="ttc" id="group__crypto__types_html_gaace70d9515489bbe3c5e7ac1b7d9155b"><div class="ttname"><a href="group__crypto__types.html#gaace70d9515489bbe3c5e7ac1b7d9155b">PSA_ALG_SHA3_256</a></div><div class="ttdeci">#define PSA_ALG_SHA3_256</div><div class="ttdef"><b>Definition:</b> crypto.h:686</div></div>
+<div class="ttc" id="group__crypto__types_html_ga16f5fe34ccce68c2fada1224c054a999"><div class="ttname"><a href="group__crypto__types.html#ga16f5fe34ccce68c2fada1224c054a999">PSA_ALG_SHA3_224</a></div><div class="ttdeci">#define PSA_ALG_SHA3_224</div><div class="ttdef"><b>Definition:</b> crypto.h:684</div></div>
+<div class="ttc" id="group__crypto__types_html_ga37e5dbe936dddb155e76f2997de27188"><div class="ttname"><a href="group__crypto__types.html#ga37e5dbe936dddb155e76f2997de27188">PSA_ALG_SHA3_512</a></div><div class="ttdeci">#define PSA_ALG_SHA3_512</div><div class="ttdef"><b>Definition:</b> crypto.h:690</div></div>
+<div class="ttc" id="group__crypto__types_html_ga619471f978e13cdd0a1e37145e4bf341"><div class="ttname"><a href="group__crypto__types.html#ga619471f978e13cdd0a1e37145e4bf341">PSA_ALG_SHA_256</a></div><div class="ttdeci">#define PSA_ALG_SHA_256</div><div class="ttdef"><b>Definition:</b> crypto.h:674</div></div>
+<div class="ttc" id="group__crypto__types_html_gafba3ae409f46d3dd7f37a0910660c3e9"><div class="ttname"><a href="group__crypto__types.html#gafba3ae409f46d3dd7f37a0910660c3e9">PSA_ALG_SHA_512</a></div><div class="ttdeci">#define PSA_ALG_SHA_512</div><div class="ttdef"><b>Definition:</b> crypto.h:678</div></div>
+<div class="ttc" id="group__crypto__types_html_ga25d6a3244d10a7148fe6b026d1979f7b"><div class="ttname"><a href="group__crypto__types.html#ga25d6a3244d10a7148fe6b026d1979f7b">PSA_ALG_SHA_224</a></div><div class="ttdeci">#define PSA_ALG_SHA_224</div><div class="ttdef"><b>Definition:</b> crypto.h:672</div></div>
+<div class="ttc" id="group__crypto__types_html_ga58af64dd9a86a287e8da9ed7739eead4"><div class="ttname"><a href="group__crypto__types.html#ga58af64dd9a86a287e8da9ed7739eead4">PSA_ALG_SHA_384</a></div><div class="ttdeci">#define PSA_ALG_SHA_384</div><div class="ttdef"><b>Definition:</b> crypto.h:676</div></div>
+<div class="ttc" id="group__crypto__types_html_ga3fe2d7c3c80e3186ca78d16a35d5d931"><div class="ttname"><a href="group__crypto__types.html#ga3fe2d7c3c80e3186ca78d16a35d5d931">PSA_ALG_SHA_512_224</a></div><div class="ttdeci">#define PSA_ALG_SHA_512_224</div><div class="ttdef"><b>Definition:</b> crypto.h:680</div></div>
+<div class="ttc" id="group__crypto__types_html_ga5910b3964c14e9613e8643a45b09c2d4"><div class="ttname"><a href="group__crypto__types.html#ga5910b3964c14e9613e8643a45b09c2d4">PSA_ALG_SHA_512_256</a></div><div class="ttdeci">#define PSA_ALG_SHA_512_256</div><div class="ttdef"><b>Definition:</b> crypto.h:682</div></div>
+<div class="ttc" id="group__crypto__types_html_gab0f079257ea75e2acfe2fc3b38c78cd8"><div class="ttname"><a href="group__crypto__types.html#gab0f079257ea75e2acfe2fc3b38c78cd8">PSA_ALG_SHA3_384</a></div><div class="ttdeci">#define PSA_ALG_SHA3_384</div><div class="ttdef"><b>Definition:</b> crypto.h:688</div></div>
+</div><!-- fragment --><p>The size of the output of <a class="el" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">psa_hash_finish()</a>, in bytes.</p>
+<p>This is also the hash size that <a class="el" href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">psa_hash_verify()</a> expects.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">alg</td><td>A hash algorithm (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(<code>alg</code>) is true), or an HMAC algorithm (<a class="el" href="group__crypto__types.html#ga70f397425684b3efcde1e0e34c28261f">PSA_ALG_HMAC</a>(<code>hash_alg</code>) where <code>hash_alg</code> is a hash algorithm).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The hash size for the specified hash algorithm. If the hash algorithm is not recognized, return 0. An implementation may return either 0 or the correct size for a hash algorithm that it recognizes, but does not support. </dd></dl>
+
+</div>
+</div>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="ga3c4205d2ce66c4095fc5c78c25273fab"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3c4205d2ce66c4095fc5c78c25273fab">◆ </a></span>psa_hash_operation_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef struct psa_hash_operation_s <a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The type of the state data structure for multipart hash operations.</p>
+<p>This is an implementation-defined <code>struct</code>. Applications should not make any assumptions about the content of this structure except as directed by the documentation of a specific implementation. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="gab0b4d5f9912a615559497a467b532928"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gab0b4d5f9912a615559497a467b532928">◆ </a></span>psa_hash_abort()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_hash_abort </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Abort a hash operation.</p>
+<p>Aborting an operation frees all associated resources except for the <code>operation</code> structure itself. Once aborted, the operation object can be reused for another operation by calling <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup()</a> again.</p>
+<p>You may call this function any time after the operation object has been initialized by any of the following methods:</p><ul>
+<li>A call to <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup()</a>, whether it succeeds or not.</li>
+<li>Initializing the <code>struct</code> to all-bits-zero.</li>
+<li>Initializing the <code>struct</code> to logical zeros, e.g. <code>psa_hash_operation_t operation = {0}</code>.</li>
+</ul>
+<p>In particular, calling <a class="el" href="group__hash.html#gab0b4d5f9912a615559497a467b532928">psa_hash_abort()</a> after the operation has been terminated by a call to <a class="el" href="group__hash.html#gab0b4d5f9912a615559497a467b532928">psa_hash_abort()</a>, <a class="el" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">psa_hash_finish()</a> or <a class="el" href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">psa_hash_verify()</a> is safe and has no effect.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Initialized hash operation.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td><code>operation</code> is not an active hash operation. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga4795fd06a0067b0adcd92e9627b8c97e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga4795fd06a0067b0adcd92e9627b8c97e">◆ </a></span>psa_hash_finish()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_hash_finish </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>hash</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>hash_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>hash_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Finish the calculation of the hash of a message.</p>
+<p>The application must call <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup()</a> before calling this function. This function calculates the hash of the message formed by concatenating the inputs passed to preceding calls to <a class="el" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">psa_hash_update()</a>.</p>
+<p>When this function returns, the operation becomes inactive.</p>
+<dl class="section warning"><dt>Warning</dt><dd>Applications should not call this function if they expect a specific value for the hash. Call <a class="el" href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">psa_hash_verify()</a> instead. Beware that comparing integrity or authenticity data such as hash values with a function such as <code>memcmp</code> is risky because the time taken by the comparison may leak information about the hashed data which could allow an attacker to guess a valid hash and thereby bypass security controls.</dd></dl>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Active hash operation. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">hash</td><td>Buffer where the hash is to be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">hash_size</td><td>Size of the <code>hash</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">hash_length</td><td>On success, the number of bytes that make up the hash value. This is always <a class="el" href="group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99">PSA_HASH_SIZE</a>(<code>alg</code>) where <code>alg</code> is the hash algorithm that is calculated.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td>The operation state is not valid (not started, or already completed). </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8">PSA_ERROR_BUFFER_TOO_SMALL</a></td><td>The size of the <code>hash</code> buffer is too small. You can determine a sufficient buffer size by calling <a class="el" href="group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99">PSA_HASH_SIZE</a>(<code>alg</code>) where <code>alg</code> is the hash algorithm that is calculated. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga8d72896cf70fc4d514c5c6b978912515"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga8d72896cf70fc4d514c5c6b978912515">◆ </a></span>psa_hash_setup()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_hash_setup </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Start a multipart hash operation.</p>
+<p>The sequence of operations to calculate a hash (message digest) is as follows:</p><ol type="1">
+<li>Allocate an operation object which will be passed to all the functions listed here.</li>
+<li>Call <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup()</a> to specify the algorithm.</li>
+<li>Call <a class="el" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">psa_hash_update()</a> zero, one or more times, passing a fragment of the message each time. The hash that is calculated is the hash of the concatenation of these messages in order.</li>
+<li>To calculate the hash, call <a class="el" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">psa_hash_finish()</a>. To compare the hash with an expected value, call <a class="el" href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">psa_hash_verify()</a>.</li>
+</ol>
+<p>The application may call <a class="el" href="group__hash.html#gab0b4d5f9912a615559497a467b532928">psa_hash_abort()</a> at any time after the operation has been initialized with <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup()</a>.</p>
+<p>After a successful call to <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup()</a>, the application must eventually terminate the operation. The following events terminate an operation:</p><ul>
+<li>A failed call to <a class="el" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">psa_hash_update()</a>.</li>
+<li>A call to <a class="el" href="group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e">psa_hash_finish()</a>, <a class="el" href="group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0">psa_hash_verify()</a> or <a class="el" href="group__hash.html#gab0b4d5f9912a615559497a467b532928">psa_hash_abort()</a>.</li>
+</ul>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[out]</td><td class="paramname">operation</td><td>The operation object to use. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>The hash algorithm to compute (<code>PSA_ALG_XXX</code> value such that <a class="el" href="group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f">PSA_ALG_IS_HASH</a>(<code>alg</code>) is true).</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td><code>alg</code> is not supported or is not a hash algorithm. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga65b16ef97d7f650899b7db4b7d1112ff"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga65b16ef97d7f650899b7db4b7d1112ff">◆ </a></span>psa_hash_update()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_hash_update </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>input</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>input_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Add a message fragment to a multipart hash operation.</p>
+<p>The application must call <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup()</a> before calling this function.</p>
+<p>If this function returns an error status, the operation becomes inactive.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Active hash operation. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">input</td><td>Buffer containing the message fragment to hash. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">input_length</td><td>Size of the <code>input</code> buffer in bytes.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td>The operation state is not valid (not started, or already completed). </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga7be923c5700c9c70ef77ee9b76d1a5c0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7be923c5700c9c70ef77ee9b76d1a5c0">◆ </a></span>psa_hash_verify()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_hash_verify </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab">psa_hash_operation_t</a> * </td>
+ <td class="paramname"><em>operation</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>hash</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>hash_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Finish the calculation of the hash of a message and compare it with an expected value.</p>
+<p>The application must call <a class="el" href="group__hash.html#ga8d72896cf70fc4d514c5c6b978912515">psa_hash_setup()</a> before calling this function. This function calculates the hash of the message formed by concatenating the inputs passed to preceding calls to <a class="el" href="group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff">psa_hash_update()</a>. It then compares the calculated hash with the expected hash passed as a parameter to this function.</p>
+<p>When this function returns, the operation becomes inactive.</p>
+<dl class="section note"><dt>Note</dt><dd>Implementations shall make the best effort to ensure that the comparison between the actual hash and the expected hash is performed in constant time.</dd></dl>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in,out]</td><td class="paramname">operation</td><td>Active hash operation. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">hash</td><td>Buffer containing the expected hash value. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">hash_length</td><td>Size of the <code>hash</code> buffer in bytes.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>The expected hash is identical to the actual hash of the message. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga35927f755d232c4766de600f2c49e9f2">PSA_ERROR_INVALID_SIGNATURE</a></td><td>The hash of the message was calculated successfully, but it differs from the expected hash. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga933d40fa2a591004f2e93aa91e11db84">PSA_ERROR_BAD_STATE</a></td><td>The operation state is not valid (not started, or already completed). </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__key__management.html b/docs/html/group__key__management.html
new file mode 100644
index 0000000..3018934
--- /dev/null
+++ b/docs/html/group__key__management.html
@@ -0,0 +1,396 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Key management</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Key management</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:gace37363530e2525a2562f07ceec8efb5"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5">psa_import_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> type, const uint8_t *data, size_t data_length)</td></tr>
+<tr class="memdesc:gace37363530e2525a2562f07ceec8efb5"><td class="mdescLeft"> </td><td class="mdescRight">Import a key in binary format. <a href="#gace37363530e2525a2562f07ceec8efb5">More...</a><br /></td></tr>
+<tr class="separator:gace37363530e2525a2562f07ceec8efb5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga2e9a60a9525ce6b3082a72df2080f0c5"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__key__management.html#ga2e9a60a9525ce6b3082a72df2080f0c5">psa_destroy_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key)</td></tr>
+<tr class="memdesc:ga2e9a60a9525ce6b3082a72df2080f0c5"><td class="mdescLeft"> </td><td class="mdescRight">Destroy a key and restore the slot to its default state. <a href="#ga2e9a60a9525ce6b3082a72df2080f0c5">More...</a><br /></td></tr>
+<tr class="separator:ga2e9a60a9525ce6b3082a72df2080f0c5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf105167657ab1d484cb4a51f93413717"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__key__management.html#gaf105167657ab1d484cb4a51f93413717">psa_get_key_information</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> *type, size_t *bits)</td></tr>
+<tr class="memdesc:gaf105167657ab1d484cb4a51f93413717"><td class="mdescLeft"> </td><td class="mdescRight">Get basic metadata about a key. <a href="#gaf105167657ab1d484cb4a51f93413717">More...</a><br /></td></tr>
+<tr class="separator:gaf105167657ab1d484cb4a51f93413717"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaa67bc459b20028b268f3d75a05afe022"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__key__management.html#gaa67bc459b20028b268f3d75a05afe022">psa_export_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, uint8_t *data, size_t data_size, size_t *data_length)</td></tr>
+<tr class="memdesc:gaa67bc459b20028b268f3d75a05afe022"><td class="mdescLeft"> </td><td class="mdescRight">Export a key in binary format. <a href="#gaa67bc459b20028b268f3d75a05afe022">More...</a><br /></td></tr>
+<tr class="separator:gaa67bc459b20028b268f3d75a05afe022"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7355b38f8eb9330db2786604f4a83a3b"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__key__management.html#ga7355b38f8eb9330db2786604f4a83a3b">psa_export_public_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, uint8_t *data, size_t data_size, size_t *data_length)</td></tr>
+<tr class="memdesc:ga7355b38f8eb9330db2786604f4a83a3b"><td class="mdescLeft"> </td><td class="mdescRight">Export a public key or the public part of a key pair in binary format. <a href="#ga7355b38f8eb9330db2786604f4a83a3b">More...</a><br /></td></tr>
+<tr class="separator:ga7355b38f8eb9330db2786604f4a83a3b"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga2e9a60a9525ce6b3082a72df2080f0c5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga2e9a60a9525ce6b3082a72df2080f0c5">◆ </a></span>psa_destroy_key()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_destroy_key </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Destroy a key and restore the slot to its default state. </p>
+<p>This function destroys the content of the key slot from both volatile memory and, if applicable, non-volatile storage. Implementations shall make a best effort to ensure that any previous content of the slot is unrecoverable.</p>
+<p>This function also erases any metadata such as policies. It returns the specified slot to its default state.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">key</td><td>The key slot to erase.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>The slot's content, if any, has been erased. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a></td><td>The slot holds content and cannot be erased because it is read-only, either due to a policy or due to physical restrictions. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td>The specified slot number does not designate a valid slot. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td>There was an failure in communication with the cryptoprocessor. The key material may still be present in the cryptoprocessor. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gadd169a1af2707862b95fb9df91dfc37d">PSA_ERROR_STORAGE_FAILURE</a></td><td>The storage is corrupted. Implementations shall make a best effort to erase key material even in this stage, however applications should be aware that it may be impossible to guarantee that the key material is not recoverable in such cases. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td>An unexpected condition which is not a storage corruption or a communication failure occurred. The cryptoprocessor may have been compromised. </td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gaa67bc459b20028b268f3d75a05afe022"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaa67bc459b20028b268f3d75a05afe022">◆ </a></span>psa_export_key()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_export_key </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>data</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>data_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>data_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Export a key in binary format. </p>
+<p>The output of this function can be passed to <a class="el" href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5" title="Import a key in binary format. ">psa_import_key()</a> to create an equivalent object.</p>
+<p>If a key is created with <a class="el" href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5" title="Import a key in binary format. ">psa_import_key()</a> and then exported with this function, it is not guaranteed that the resulting data is identical: the implementation may choose a different representation of the same key if the format permits it.</p>
+<p>For standard key types, the output format is as follows:</p>
+<ul>
+<li>For symmetric keys (including MAC keys), the format is the raw bytes of the key.</li>
+<li>For DES, the key data consists of 8 bytes. The parity bits must be correct.</li>
+<li>For Triple-DES, the format is the concatenation of the two or three DES keys.</li>
+<li>For RSA key pairs (<a class="el" href="group__crypto__types.html#ga581f50687f5d650456925278948f2799">PSA_KEY_TYPE_RSA_KEYPAIR</a>), the format is the non-encrypted DER representation defined by PKCS#1 (RFC 8017) as RSAPrivateKey.</li>
+<li>For RSA public keys (<a class="el" href="group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b">PSA_KEY_TYPE_RSA_PUBLIC_KEY</a>), the format is the DER representation defined by RFC 5280 as SubjectPublicKeyInfo.</li>
+</ul>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot whose content is to be exported. This must be an occupied key slot. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">data</td><td>Buffer where the key data is to be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">data_size</td><td>Size of the <code>data</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">data_length</td><td>On success, the number of bytes that make up the key data.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1">PSA_ERROR_NOT_PERMITTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga7355b38f8eb9330db2786604f4a83a3b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7355b38f8eb9330db2786604f4a83a3b">◆ </a></span>psa_export_public_key()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_export_public_key </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>data</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>data_size</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>data_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Export a public key or the public part of a key pair in binary format. </p>
+<p>The output of this function can be passed to <a class="el" href="group__key__management.html#gace37363530e2525a2562f07ceec8efb5" title="Import a key in binary format. ">psa_import_key()</a> to create an object that is equivalent to the public key.</p>
+<p>For standard key types, the output format is as follows:</p>
+<ul>
+<li>For RSA keys (<a class="el" href="group__crypto__types.html#ga581f50687f5d650456925278948f2799">PSA_KEY_TYPE_RSA_KEYPAIR</a> or <a class="el" href="group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b">PSA_KEY_TYPE_RSA_PUBLIC_KEY</a>), the format is the DER representation of the public key defined by RFC 5280 as SubjectPublicKeyInfo.</li>
+</ul>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot whose content is to be exported. This must be an occupied key slot. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">data</td><td>Buffer where the key data is to be written. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">data_size</td><td>Size of the <code>data</code> buffer in bytes. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">data_length</td><td>On success, the number of bytes that make up the key data.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gaf105167657ab1d484cb4a51f93413717"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf105167657ab1d484cb4a51f93413717">◆ </a></span>psa_get_key_information()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_get_key_information </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> * </td>
+ <td class="paramname"><em>type</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t * </td>
+ <td class="paramname"><em>bits</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Get basic metadata about a key. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot whose content is queried. This must be an occupied key slot. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">type</td><td>On success, the key type (a <code>PSA_KEY_TYPE_XXX</code> value). This may be a null pointer, in which case the key type is not written. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">bits</td><td>On success, the key size in bits. This may be a null pointer, in which case the key size is not written.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040">PSA_ERROR_EMPTY_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gace37363530e2525a2562f07ceec8efb5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gace37363530e2525a2562f07ceec8efb5">◆ </a></span>psa_import_key()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_import_key </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> </td>
+ <td class="paramname"><em>type</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const uint8_t * </td>
+ <td class="paramname"><em>data</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>data_length</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Import a key in binary format. </p>
+<p>This function supports any output from <a class="el" href="group__key__management.html#gaa67bc459b20028b268f3d75a05afe022" title="Export a key in binary format. ">psa_export_key()</a>. Refer to the documentation of <a class="el" href="group__key__management.html#gaa67bc459b20028b268f3d75a05afe022" title="Export a key in binary format. ">psa_export_key()</a> for the format for each key type.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot where the key will be stored. This must be a valid slot for a key of the chosen type. It must be unoccupied. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">type</td><td>Key type (a <code>PSA_KEY_TYPE_XXX</code> value). </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">data</td><td>Buffer containing the key data. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">data_length</td><td>Size of the <code>data</code> buffer in bytes.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td>The key type or key size is not supported, either by the implementation in general or in this particular slot. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td>The key slot is invalid, or the key data is not correctly formatted. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gac2fee3a51249fbea45360aaa911f3e58">PSA_ERROR_OCCUPIED_SLOT</a></td><td>There is already a key in the specified slot. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga897a45eb206a6f6b7be7ffbe36f0d766">PSA_ERROR_INSUFFICIENT_STORAGE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__persistence.html b/docs/html/group__persistence.html
new file mode 100644
index 0000000..6eb3769
--- /dev/null
+++ b/docs/html/group__persistence.html
@@ -0,0 +1,264 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Key lifetime</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#define-members">Macros</a> |
+<a href="#typedef-members">Typedefs</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Key lifetime</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ga8b438870ba69489b685730d346455108"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#ga8b438870ba69489b685730d346455108">PSA_KEY_LIFETIME_VOLATILE</a>   ((<a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a>)0x00000000)</td></tr>
+<tr class="separator:ga8b438870ba69489b685730d346455108"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga3713a01c5fcd5f7eae46ff22ceaf6d02"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#ga3713a01c5fcd5f7eae46ff22ceaf6d02">PSA_KEY_LIFETIME_PERSISTENT</a>   ((<a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a>)0x00000001)</td></tr>
+<tr class="separator:ga3713a01c5fcd5f7eae46ff22ceaf6d02"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gae6b8443238ef1900cf132550d7df557f"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#gae6b8443238ef1900cf132550d7df557f">PSA_KEY_LIFETIME_WRITE_ONCE</a>   ((<a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a>)0x7fffffff)</td></tr>
+<tr class="separator:gae6b8443238ef1900cf132550d7df557f"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ga6821ff6dd39dc2bc370ded760ad8b0cf"><td class="memItemLeft" align="right" valign="top">typedef uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a></td></tr>
+<tr class="separator:ga6821ff6dd39dc2bc370ded760ad8b0cf"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:gaf0daaa1dba14dc324ca83dfe1495a5e2"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#gaf0daaa1dba14dc324ca83dfe1495a5e2">psa_get_key_lifetime</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a> *lifetime)</td></tr>
+<tr class="memdesc:gaf0daaa1dba14dc324ca83dfe1495a5e2"><td class="mdescLeft"> </td><td class="mdescRight">Retrieve the lifetime of a key slot. <a href="#gaf0daaa1dba14dc324ca83dfe1495a5e2">More...</a><br /></td></tr>
+<tr class="separator:gaf0daaa1dba14dc324ca83dfe1495a5e2"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga1bd1ee6d00ebd9962fc6ad72cbd22ef8"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__persistence.html#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8">psa_set_key_lifetime</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a> lifetime)</td></tr>
+<tr class="memdesc:ga1bd1ee6d00ebd9962fc6ad72cbd22ef8"><td class="mdescLeft"> </td><td class="mdescRight">Change the lifetime of a key slot. <a href="#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8">More...</a><br /></td></tr>
+<tr class="separator:ga1bd1ee6d00ebd9962fc6ad72cbd22ef8"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="ga3713a01c5fcd5f7eae46ff22ceaf6d02"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga3713a01c5fcd5f7eae46ff22ceaf6d02">◆ </a></span>PSA_KEY_LIFETIME_PERSISTENT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_LIFETIME_PERSISTENT   ((<a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a>)0x00000001)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>A persistent key slot retains its content as long as it is not explicitly destroyed. </p>
+
+</div>
+</div>
+<a id="ga8b438870ba69489b685730d346455108"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga8b438870ba69489b685730d346455108">◆ </a></span>PSA_KEY_LIFETIME_VOLATILE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_LIFETIME_VOLATILE   ((<a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a>)0x00000000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>A volatile key slot retains its content as long as the application is running. It is guaranteed to be erased on a power reset. </p>
+
+</div>
+</div>
+<a id="gae6b8443238ef1900cf132550d7df557f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gae6b8443238ef1900cf132550d7df557f">◆ </a></span>PSA_KEY_LIFETIME_WRITE_ONCE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_LIFETIME_WRITE_ONCE   ((<a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a>)0x7fffffff)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>A write-once key slot may not be modified once a key has been set. It will retain its content as long as the device remains operational. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="ga6821ff6dd39dc2bc370ded760ad8b0cf"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga6821ff6dd39dc2bc370ded760ad8b0cf">◆ </a></span>psa_key_lifetime_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef uint32_t <a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Encoding of key lifetimes. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="gaf0daaa1dba14dc324ca83dfe1495a5e2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf0daaa1dba14dc324ca83dfe1495a5e2">◆ </a></span>psa_get_key_lifetime()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_get_key_lifetime </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a> * </td>
+ <td class="paramname"><em>lifetime</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Retrieve the lifetime of a key slot. </p>
+<p>The assignment of lifetimes to slots is implementation-dependent.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot to query. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">lifetime</td><td>On success, the lifetime value.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td>The key slot is invalid. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga1bd1ee6d00ebd9962fc6ad72cbd22ef8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8">◆ </a></span>psa_set_key_lifetime()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_set_key_lifetime </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf">psa_key_lifetime_t</a> </td>
+ <td class="paramname"><em>lifetime</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Change the lifetime of a key slot. </p>
+<p>Whether the lifetime of a key slot can be changed at all, and if so whether the lifetime of an occupied key slot can be changed, is implementation-dependent.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramname">key</td><td>Slot whose lifetime is to be changed. </td></tr>
+ <tr><td class="paramname">lifetime</td><td>The lifetime value to set for the given key slot.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td>Success. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td>The key slot is invalid, or the lifetime value is invalid. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td>The implementation does not support the specified lifetime value, at least for the specified key slot. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gac2fee3a51249fbea45360aaa911f3e58">PSA_ERROR_OCCUPIED_SLOT</a></td><td>The slot contains a key, and the implementation does not support changing the lifetime of an occupied slot. </td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__platform.html b/docs/html/group__platform.html
new file mode 100644
index 0000000..eeec51f
--- /dev/null
+++ b/docs/html/group__platform.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Implementation-specific definitions</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#typedef-members">Typedefs</a> </div>
+ <div class="headertitle">
+<div class="title">Implementation-specific definitions</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:gac3da92a6b8a7f0c01dc348f8e0432e4c"><td class="memItemLeft" align="right" valign="top">typedef _unsigned_integral_type_ </td><td class="memItemRight" valign="bottom"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a></td></tr>
+<tr class="memdesc:gac3da92a6b8a7f0c01dc348f8e0432e4c"><td class="mdescLeft"> </td><td class="mdescRight">Key slot number. <a href="#gac3da92a6b8a7f0c01dc348f8e0432e4c">More...</a><br /></td></tr>
+<tr class="separator:gac3da92a6b8a7f0c01dc348f8e0432e4c"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="gac3da92a6b8a7f0c01dc348f8e0432e4c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac3da92a6b8a7f0c01dc348f8e0432e4c">◆ </a></span>psa_key_slot_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef _unsigned_integral_type_ <a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Key slot number. </p>
+<p>This type represents key slots. It must be an unsigned integral type. The choice of type is implementation-dependent. 0 is not a valid key slot number. The meaning of other values is implementation dependent.</p>
+<p>At any given point in time, each key slot either contains a cryptographic object, or is empty. Key slots are persistent: once set, the cryptographic object remains in the key slot until explicitly destroyed. </p>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__policy.html b/docs/html/group__policy.html
new file mode 100644
index 0000000..27dddcf
--- /dev/null
+++ b/docs/html/group__policy.html
@@ -0,0 +1,466 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Key policies</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#define-members">Macros</a> |
+<a href="#typedef-members">Typedefs</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Key policies</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:ga7dddccdd1303176e87a4d20c87b589ed"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga7dddccdd1303176e87a4d20c87b589ed">PSA_KEY_USAGE_EXPORT</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000001)</td></tr>
+<tr class="separator:ga7dddccdd1303176e87a4d20c87b589ed"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga75153b296d045d529d97203a6a995dad"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga75153b296d045d529d97203a6a995dad">PSA_KEY_USAGE_ENCRYPT</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000100)</td></tr>
+<tr class="separator:ga75153b296d045d529d97203a6a995dad"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac3f2d2e5983db1edde9f142ca9bf8e6a"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gac3f2d2e5983db1edde9f142ca9bf8e6a">PSA_KEY_USAGE_DECRYPT</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000200)</td></tr>
+<tr class="separator:gac3f2d2e5983db1edde9f142ca9bf8e6a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga99b9f456cf59efc4b5579465407aef5a"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga99b9f456cf59efc4b5579465407aef5a">PSA_KEY_USAGE_SIGN</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000400)</td></tr>
+<tr class="separator:ga99b9f456cf59efc4b5579465407aef5a"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga39b54ffd5958b69634607924fa53cea6"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga39b54ffd5958b69634607924fa53cea6">PSA_KEY_USAGE_VERIFY</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000800)</td></tr>
+<tr class="separator:ga39b54ffd5958b69634607924fa53cea6"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf19022acc5ef23cf12477f632b48a0b2"><td class="memItemLeft" align="right" valign="top">#define </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gaf19022acc5ef23cf12477f632b48a0b2">PSA_KEY_USAGE_DERIVE</a>   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00001000)</td></tr>
+<tr class="separator:gaf19022acc5ef23cf12477f632b48a0b2"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:ga7bb9de71337e0e98de843aa7f9b55f25"><td class="memItemLeft" align="right" valign="top"><a id="ga7bb9de71337e0e98de843aa7f9b55f25"></a>
+typedef uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a></td></tr>
+<tr class="memdesc:ga7bb9de71337e0e98de843aa7f9b55f25"><td class="mdescLeft"> </td><td class="mdescRight">Encoding of permitted usage on a key. <br /></td></tr>
+<tr class="separator:ga7bb9de71337e0e98de843aa7f9b55f25"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaf553efd409845b6d09ff25ce2ba36607"><td class="memItemLeft" align="right" valign="top">typedef struct psa_key_policy_s </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a></td></tr>
+<tr class="separator:gaf553efd409845b6d09ff25ce2ba36607"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:gad49eb85e3fcbe70f763f511ac83e762e"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gad49eb85e3fcbe70f763f511ac83e762e">psa_key_policy_init</a> (<a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy)</td></tr>
+<tr class="memdesc:gad49eb85e3fcbe70f763f511ac83e762e"><td class="mdescLeft"> </td><td class="mdescRight">Initialize a key policy structure to a default that forbids all usage of the key. <a href="#gad49eb85e3fcbe70f763f511ac83e762e">More...</a><br /></td></tr>
+<tr class="separator:gad49eb85e3fcbe70f763f511ac83e762e"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gac16792fd6d375a5f76d372090df40607"><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gac16792fd6d375a5f76d372090df40607">psa_key_policy_set_usage</a> (<a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy, <a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a> usage, <a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> alg)</td></tr>
+<tr class="memdesc:gac16792fd6d375a5f76d372090df40607"><td class="mdescLeft"> </td><td class="mdescRight">Set the standard fields of a policy structure. <a href="#gac16792fd6d375a5f76d372090df40607">More...</a><br /></td></tr>
+<tr class="separator:gac16792fd6d375a5f76d372090df40607"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga7746662b7503e484774d0ecb5d8ac2ab"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga7746662b7503e484774d0ecb5d8ac2ab">psa_key_policy_get_usage</a> (const <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy)</td></tr>
+<tr class="memdesc:ga7746662b7503e484774d0ecb5d8ac2ab"><td class="mdescLeft"> </td><td class="mdescRight">Retrieve the usage field of a policy structure. <a href="#ga7746662b7503e484774d0ecb5d8ac2ab">More...</a><br /></td></tr>
+<tr class="separator:ga7746662b7503e484774d0ecb5d8ac2ab"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gaadf16b89ace53e1d2cb5bcb0aef24c86"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gaadf16b89ace53e1d2cb5bcb0aef24c86">psa_key_policy_get_algorithm</a> (const <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy)</td></tr>
+<tr class="memdesc:gaadf16b89ace53e1d2cb5bcb0aef24c86"><td class="mdescLeft"> </td><td class="mdescRight">Retrieve the algorithm field of a policy structure. <a href="#gaadf16b89ace53e1d2cb5bcb0aef24c86">More...</a><br /></td></tr>
+<tr class="separator:gaadf16b89ace53e1d2cb5bcb0aef24c86"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gad7faa7e64aa771f7441c44ceff21af19"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#gad7faa7e64aa771f7441c44ceff21af19">psa_set_key_policy</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, const <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy)</td></tr>
+<tr class="memdesc:gad7faa7e64aa771f7441c44ceff21af19"><td class="mdescLeft"> </td><td class="mdescRight">Set the usage policy on a key slot. <a href="#gad7faa7e64aa771f7441c44ceff21af19">More...</a><br /></td></tr>
+<tr class="separator:gad7faa7e64aa771f7441c44ceff21af19"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:ga613f28712124f9149bd640614376ab5a"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__policy.html#ga613f28712124f9149bd640614376ab5a">psa_get_key_policy</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> *policy)</td></tr>
+<tr class="memdesc:ga613f28712124f9149bd640614376ab5a"><td class="mdescLeft"> </td><td class="mdescRight">Get the usage policy for a key slot. <a href="#ga613f28712124f9149bd640614376ab5a">More...</a><br /></td></tr>
+<tr class="separator:ga613f28712124f9149bd640614376ab5a"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="gac3f2d2e5983db1edde9f142ca9bf8e6a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac3f2d2e5983db1edde9f142ca9bf8e6a">◆ </a></span>PSA_KEY_USAGE_DECRYPT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_USAGE_DECRYPT   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000200)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the key may be used to decrypt a message.</p>
+<p>This flag allows the key to be used for a symmetric decryption operation, for an AEAD decryption-and-verification operation, or for an asymmetric decryption operation, if otherwise permitted by the key's type and policy.</p>
+<p>For a key pair, this concerns the private key. </p>
+
+</div>
+</div>
+<a id="gaf19022acc5ef23cf12477f632b48a0b2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf19022acc5ef23cf12477f632b48a0b2">◆ </a></span>PSA_KEY_USAGE_DERIVE</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_USAGE_DERIVE   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00001000)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the key may be used to derive other keys. </p>
+
+</div>
+</div>
+<a id="ga75153b296d045d529d97203a6a995dad"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga75153b296d045d529d97203a6a995dad">◆ </a></span>PSA_KEY_USAGE_ENCRYPT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_USAGE_ENCRYPT   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000100)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the key may be used to encrypt a message.</p>
+<p>This flag allows the key to be used for a symmetric encryption operation, for an AEAD encryption-and-authentication operation, or for an asymmetric encryption operation, if otherwise permitted by the key's type and policy.</p>
+<p>For a key pair, this concerns the public key. </p>
+
+</div>
+</div>
+<a id="ga7dddccdd1303176e87a4d20c87b589ed"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7dddccdd1303176e87a4d20c87b589ed">◆ </a></span>PSA_KEY_USAGE_EXPORT</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_USAGE_EXPORT   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000001)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the key may be exported.</p>
+<p>A public key or the public part of a key pair may always be exported regardless of the value of this permission flag.</p>
+<p>If a key does not have export permission, implementations shall not allow the key to be exported in plain form from the cryptoprocessor, whether through <a class="el" href="group__key__management.html#gaa67bc459b20028b268f3d75a05afe022" title="Export a key in binary format. ">psa_export_key()</a> or through a proprietary interface. The key may however be exportable in a wrapped form, i.e. in a form where it is encrypted by another key. </p>
+
+</div>
+</div>
+<a id="ga99b9f456cf59efc4b5579465407aef5a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga99b9f456cf59efc4b5579465407aef5a">◆ </a></span>PSA_KEY_USAGE_SIGN</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_USAGE_SIGN   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000400)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the key may be used to sign a message.</p>
+<p>This flag allows the key to be used for a MAC calculation operation or for an asymmetric signature operation, if otherwise permitted by the key's type and policy.</p>
+<p>For a key pair, this concerns the private key. </p>
+
+</div>
+</div>
+<a id="ga39b54ffd5958b69634607924fa53cea6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga39b54ffd5958b69634607924fa53cea6">◆ </a></span>PSA_KEY_USAGE_VERIFY</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define PSA_KEY_USAGE_VERIFY   ((<a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a>)0x00000800)</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Whether the key may be used to verify a message signature.</p>
+<p>This flag allows the key to be used for a MAC verification operation or for an asymmetric signature verification operation, if otherwise permitted by by the key's type and policy.</p>
+<p>For a key pair, this concerns the public key. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="gaf553efd409845b6d09ff25ce2ba36607"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaf553efd409845b6d09ff25ce2ba36607">◆ </a></span>psa_key_policy_t</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">typedef struct psa_key_policy_s <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>The type of the key policy data structure.</p>
+<p>This is an implementation-defined <code>struct</code>. Applications should not make any assumptions about the content of this structure except as directed by the documentation of a specific implementation. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="ga613f28712124f9149bd640614376ab5a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga613f28712124f9149bd640614376ab5a">◆ </a></span>psa_get_key_policy()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_get_key_policy </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> * </td>
+ <td class="paramname"><em>policy</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Get the usage policy for a key slot. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>The key slot whose policy is being queried. </td></tr>
+ <tr><td class="paramdir">[out]</td><td class="paramname">policy</td><td>On success, the key's policy.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gaadf16b89ace53e1d2cb5bcb0aef24c86"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gaadf16b89ace53e1d2cb5bcb0aef24c86">◆ </a></span>psa_key_policy_get_algorithm()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> psa_key_policy_get_algorithm </td>
+ <td>(</td>
+ <td class="paramtype">const <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> * </td>
+ <td class="paramname"><em>policy</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Retrieve the algorithm field of a policy structure. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in]</td><td class="paramname">policy</td><td>The policy object to query.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The permitted algorithm for a key with this policy. </dd></dl>
+
+</div>
+</div>
+<a id="ga7746662b7503e484774d0ecb5d8ac2ab"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga7746662b7503e484774d0ecb5d8ac2ab">◆ </a></span>psa_key_policy_get_usage()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a> psa_key_policy_get_usage </td>
+ <td>(</td>
+ <td class="paramtype">const <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> * </td>
+ <td class="paramname"><em>policy</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Retrieve the usage field of a policy structure. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[in]</td><td class="paramname">policy</td><td>The policy object to query.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd>The permitted uses for a key with this policy. </dd></dl>
+
+</div>
+</div>
+<a id="gad49eb85e3fcbe70f763f511ac83e762e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gad49eb85e3fcbe70f763f511ac83e762e">◆ </a></span>psa_key_policy_init()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void psa_key_policy_init </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> * </td>
+ <td class="paramname"><em>policy</em></td><td>)</td>
+ <td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Initialize a key policy structure to a default that forbids all usage of the key. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[out]</td><td class="paramname">policy</td><td>The policy object to initialize. </td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gac16792fd6d375a5f76d372090df40607"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gac16792fd6d375a5f76d372090df40607">◆ </a></span>psa_key_policy_set_usage()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void psa_key_policy_set_usage </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> * </td>
+ <td class="paramname"><em>policy</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25">psa_key_usage_t</a> </td>
+ <td class="paramname"><em>usage</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69">psa_algorithm_t</a> </td>
+ <td class="paramname"><em>alg</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Set the standard fields of a policy structure. </p>
+<p>Note that this function does not make any consistency check of the parameters. The values are only checked when applying the policy to a key slot with <a class="el" href="group__policy.html#gad7faa7e64aa771f7441c44ceff21af19" title="Set the usage policy on a key slot. ">psa_set_key_policy()</a>.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[out]</td><td class="paramname">policy</td><td>The policy object to modify. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">usage</td><td>The permitted uses for the key. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">alg</td><td>The algorithm that the key may be used for. </td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="gad7faa7e64aa771f7441c44ceff21af19"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gad7faa7e64aa771f7441c44ceff21af19">◆ </a></span>psa_set_key_policy()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_set_key_policy </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const <a class="el" href="group__policy.html#gaf553efd409845b6d09ff25ce2ba36607">psa_key_policy_t</a> * </td>
+ <td class="paramname"><em>policy</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Set the usage policy on a key slot. </p>
+<p>This function must be called on an empty key slot, before importing, generating or creating a key in the slot. Changing the policy of an existing key is not permitted.</p>
+<p>Implementations may set restrictions on supported key policies depending on the key type and the key slot.</p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>The key slot whose policy is to be changed. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">policy</td><td>The policy object to query.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#gac2fee3a51249fbea45360aaa911f3e58">PSA_ERROR_OCCUPIED_SLOT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/group__random.html b/docs/html/group__random.html
new file mode 100644
index 0000000..b1ebaef
--- /dev/null
+++ b/docs/html/group__random.html
@@ -0,0 +1,220 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Random generation</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="summary">
+<a href="#nested-classes">Classes</a> |
+<a href="#func-members">Functions</a> </div>
+ <div class="headertitle">
+<div class="title">Random generation</div> </div>
+</div><!--header-->
+<div class="contents">
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="nested-classes"></a>
+Classes</h2></td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct  </td><td class="memItemRight" valign="bottom"><a class="el" href="structpsa__generate__key__extra__rsa.html">psa_generate_key_extra_rsa</a></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2"> </td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:ga1985eae417dfbccedf50d5fff54ea8c5"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__random.html#ga1985eae417dfbccedf50d5fff54ea8c5">psa_generate_random</a> (uint8_t *output, size_t output_size)</td></tr>
+<tr class="memdesc:ga1985eae417dfbccedf50d5fff54ea8c5"><td class="mdescLeft"> </td><td class="mdescRight">Generate random bytes. <a href="#ga1985eae417dfbccedf50d5fff54ea8c5">More...</a><br /></td></tr>
+<tr class="separator:ga1985eae417dfbccedf50d5fff54ea8c5"><td class="memSeparator" colspan="2"> </td></tr>
+<tr class="memitem:gada1d701903f6b4de6b4c6a1d613c1b10"><td class="memItemLeft" align="right" valign="top"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10">psa_generate_key</a> (<a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> key, <a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> type, size_t bits, const void *extra, size_t extra_size)</td></tr>
+<tr class="memdesc:gada1d701903f6b4de6b4c6a1d613c1b10"><td class="mdescLeft"> </td><td class="mdescRight">Generate a key or key pair. <a href="#gada1d701903f6b4de6b4c6a1d613c1b10">More...</a><br /></td></tr>
+<tr class="separator:gada1d701903f6b4de6b4c6a1d613c1b10"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="gada1d701903f6b4de6b4c6a1d613c1b10"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#gada1d701903f6b4de6b4c6a1d613c1b10">◆ </a></span>psa_generate_key()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_generate_key </td>
+ <td>(</td>
+ <td class="paramtype"><a class="el" href="group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c">psa_key_slot_t</a> </td>
+ <td class="paramname"><em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"><a class="el" href="group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628">psa_key_type_t</a> </td>
+ <td class="paramname"><em>type</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>bits</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const void * </td>
+ <td class="paramname"><em>extra</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>extra_size</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Generate a key or key pair. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir"></td><td class="paramname">key</td><td>Slot where the key will be stored. This must be a valid slot for a key of the chosen type. It must be unoccupied. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">type</td><td>Key type (a <code>PSA_KEY_TYPE_XXX</code> value). </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">bits</td><td>Key size in bits. </td></tr>
+ <tr><td class="paramdir">[in]</td><td class="paramname">extra</td><td>Extra parameters for key generation. The interpretation of this parameter depends on <code>type</code>. All types support <code>NULL</code> to use default parameters. Implementation that support the generation of vendor-specific key types that allow extra parameters shall document the format of these extra parameters and the default values. For standard parameters, the meaning of <code>extra</code> is as follows:<ul>
+<li>For a symmetric key type (a type such that <a class="el" href="group__crypto__types.html#gab138ae2ebf2905dfbaf4154db2620939">PSA_KEY_TYPE_IS_ASYMMETRIC</a>(<code>type</code>) is false), <code>extra</code> must be <code>NULL</code>.</li>
+<li>For an elliptic curve key type (a type such that <a class="el" href="group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66">PSA_KEY_TYPE_IS_ECC</a>(<code>type</code>) is false), <code>extra</code> must be <code>NULL</code>.</li>
+<li>For an RSA key (<code>type</code> is <a class="el" href="group__crypto__types.html#ga581f50687f5d650456925278948f2799">PSA_KEY_TYPE_RSA_KEYPAIR</a>), <code>extra</code> is an optional <a class="el" href="structpsa__generate__key__extra__rsa.html">psa_generate_key_extra_rsa</a> structure specifying the public exponent. The default public exponent used when <code>extra</code> is <code>NULL</code> is 65537. </li>
+</ul>
+</td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">extra_size</td><td>Size of the buffer that <code>extra</code> points to, in bytes. Note that if <code>extra</code> is <code>NULL</code> then <code>extra_size</code> must be zero.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f">PSA_ERROR_INVALID_ARGUMENT</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5">PSA_ERROR_INSUFFICIENT_MEMORY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">PSA_ERROR_INSUFFICIENT_ENTROPY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+<a id="ga1985eae417dfbccedf50d5fff54ea8c5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ga1985eae417dfbccedf50d5fff54ea8c5">◆ </a></span>psa_generate_random()</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname"><a class="el" href="group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9">psa_status_t</a> psa_generate_random </td>
+ <td>(</td>
+ <td class="paramtype">uint8_t * </td>
+ <td class="paramname"><em>output</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t </td>
+ <td class="paramname"><em>output_size</em> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+
+<p>Generate random bytes. </p>
+<dl class="section warning"><dt>Warning</dt><dd>This function <b>can</b> fail! Callers MUST check the return status and MUST NOT use the content of the output buffer if the return status is not <a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a>.</dd></dl>
+<dl class="section note"><dt>Note</dt><dd>To generate a key, use <a class="el" href="group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10" title="Generate a key or key pair. ">psa_generate_key()</a> instead.</dd></dl>
+<dl class="params"><dt>Parameters</dt><dd>
+ <table class="params">
+ <tr><td class="paramdir">[out]</td><td class="paramname">output</td><td>Output buffer for the generated data. </td></tr>
+ <tr><td class="paramdir"></td><td class="paramname">output_size</td><td>Number of bytes to generate and output.</td></tr>
+ </table>
+ </dd>
+</dl>
+<dl class="retval"><dt>Return values</dt><dd>
+ <table class="retval">
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1">PSA_SUCCESS</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga1dcc6d130633ed5db8942257581b55dd">PSA_ERROR_NOT_SUPPORTED</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga4deb59fec02297ec5d8b42178323f675">PSA_ERROR_INSUFFICIENT_ENTROPY</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga5cdb6948371d49e916106249020ea3f7">PSA_ERROR_COMMUNICATION_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b">PSA_ERROR_HARDWARE_FAILURE</a></td><td></td></tr>
+ <tr><td class="paramname"><a class="el" href="group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004">PSA_ERROR_TAMPERING_DETECTED</a></td><td></td></tr>
+ </table>
+ </dd>
+</dl>
+
+</div>
+</div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/index.html b/docs/html/index.html
new file mode 100644
index 0000000..beaff3b
--- /dev/null
+++ b/docs/html/index.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Main Page</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">Platform Security Architecture — cryptography and keystore interface Documentation</div> </div>
+</div><!--header-->
+<div class="contents">
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/jquery.js b/docs/html/jquery.js
new file mode 100644
index 0000000..f5343ed
--- /dev/null
+++ b/docs/html/jquery.js
@@ -0,0 +1,87 @@
+/*!
+ * jQuery JavaScript Library v1.7.1
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Mon Nov 21 21:11:03 2011 -0500
+ */
+(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b4<b3;b4++){if((b9=arguments[b4])!=null){for(b2 in b9){b0=b5[b2];b1=b9[b2];if(b5===b1){continue}if(b8&&b1&&(bF.isPlainObject(b1)||(b6=bF.isArray(b1)))){if(b6){b6=false;b7=b0&&bF.isArray(b0)?b0:[]}else{b7=b0&&bF.isPlainObject(b0)?b0:{}}b5[b2]=bF.extend(b8,b7,b1)}else{if(b1!==L){b5[b2]=b1}}}}}return b5};bF.extend({noConflict:function(b0){if(bb.$===bF){bb.$=bH}if(b0&&bb.jQuery===bF){bb.jQuery=bU}return bF},isReady:false,readyWait:1,holdReady:function(b0){if(b0){bF.readyWait++}else{bF.ready(true)}},ready:function(b0){if((b0===true&&!--bF.readyWait)||(b0!==true&&!bF.isReady)){if(!av.body){return setTimeout(bF.ready,1)}bF.isReady=true;if(b0!==true&&--bF.readyWait>0){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b4<b5;){if(b6.apply(b3[b4++],b2)===false){break}}}}else{if(b0){for(b1 in b3){if(b6.call(b3[b1],b1,b3[b1])===false){break}}}else{for(;b4<b5;){if(b6.call(b3[b4],b4,b3[b4++])===false){break}}}}return b3},trim:bO?function(b0){return b0==null?"":bO.call(b0)}:function(b0){return b0==null?"":b0.toString().replace(bI,"").replace(bE,"")},makeArray:function(b3,b1){var b0=b1||[];if(b3!=null){var b2=bF.type(b3);if(b3.length==null||b2==="string"||b2==="function"||b2==="regexp"||bF.isWindow(b3)){bz.call(b0,b3)}else{bF.merge(b0,b3)}}return b0},inArray:function(b2,b3,b1){var b0;if(b3){if(bv){return bv.call(b3,b2,b1)}b0=b3.length;b1=b1?b1<0?Math.max(0,b0+b1):b1:0;for(;b1<b0;b1++){if(b1 in b3&&b3[b1]===b2){return b1}}}return -1},merge:function(b4,b2){var b3=b4.length,b1=0;if(typeof b2.length==="number"){for(var b0=b2.length;b1<b0;b1++){b4[b3++]=b2[b1]}}else{while(b2[b1]!==L){b4[b3++]=b2[b1++]}}b4.length=b3;return b4},grep:function(b1,b6,b0){var b2=[],b5;b0=!!b0;for(var b3=0,b4=b1.length;b3<b4;b3++){b5=!!b6(b1[b3],b3);if(b0!==b5){b2.push(b1[b3])}}return b2},map:function(b0,b7,b8){var b5,b6,b4=[],b2=0,b1=b0.length,b3=b0 instanceof bF||b1!==L&&typeof b1==="number"&&((b1>0&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b2<b1;b2++){b5=b7(b0[b2],b2,b8);if(b5!=null){b4[b4.length]=b5}}}else{for(b6 in b0){b5=b7(b0[b6],b6,b8);if(b5!=null){b4[b4.length]=b5}}}return b4.concat.apply([],b4)},guid:1,proxy:function(b4,b3){if(typeof b3==="string"){var b2=b4[b3];b3=b4;b4=b2}if(!bF.isFunction(b4)){return L}var b0=bK.call(arguments,2),b1=function(){return b4.apply(b3,b0.concat(bK.call(arguments)))};b1.guid=b4.guid=b4.guid||b1.guid||bF.guid++;return b1},access:function(b0,b8,b6,b2,b5,b7){var b1=b0.length;if(typeof b8==="object"){for(var b3 in b8){bF.access(b0,b3,b8[b3],b2,b5,b6)}return b0}if(b6!==L){b2=!b7&&b2&&bF.isFunction(b6);for(var b4=0;b4<b1;b4++){b5(b0[b4],b8,b2?b6.call(b0[b4],b4,b5(b0[b4],b8)):b6,b7)}return b0}return b1?b5(b0[0],b8):L},now:function(){return(new Date()).getTime()},uaMatch:function(b1){b1=b1.toLowerCase();var b0=by.exec(b1)||bR.exec(b1)||bQ.exec(b1)||b1.indexOf("compatible")<0&&bS.exec(b1)||[];return{browser:b0[1]||"",version:b0[2]||"0"}},sub:function(){function b0(b3,b4){return new b0.fn.init(b3,b4)}bF.extend(true,b0,this);b0.superclass=this;b0.fn=b0.prototype=this();b0.fn.constructor=b0;b0.sub=this.sub;b0.fn.init=function b2(b3,b4){if(b4&&b4 instanceof bF&&!(b4 instanceof b0)){b4=b0(b4)}return bF.fn.init.call(this,b3,b4,b1)};b0.fn.init.prototype=b0.fn;var b1=b0(av);return b0},browser:{}});bF.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(b1,b0){bx["[object "+b0+"]"]=b0.toLowerCase()});bV=bF.uaMatch(bX);if(bV.browser){bF.browser[bV.browser]=true;bF.browser.version=bV.version}if(bF.browser.webkit){bF.browser.safari=true}if(bM.test("\xA0")){bI=/^[\s\xA0]+/;bE=/[\s\xA0]+$/}bD=bF(av);if(av.addEventListener){e=function(){av.removeEventListener("DOMContentLoaded",e,false);bF.ready()}}else{if(av.attachEvent){e=function(){if(av.readyState==="complete"){av.detachEvent("onreadystatechange",e);bF.ready()}}}}function bw(){if(bF.isReady){return}try{av.documentElement.doScroll("left")}catch(b0){setTimeout(bw,1);return}bF.ready()}return bF})();var a2={};function X(e){var bv=a2[e]={},bw,bx;e=e.split(/\s+/);for(bw=0,bx=e.length;bw<bx;bw++){bv[e[bw]]=true}return bv}b.Callbacks=function(bw){bw=bw?(a2[bw]||X(bw)):{};var bB=[],bC=[],bx,by,bv,bz,bA,bE=function(bF){var bG,bJ,bI,bH,bK;for(bG=0,bJ=bF.length;bG<bJ;bG++){bI=bF[bG];bH=b.type(bI);if(bH==="array"){bE(bI)}else{if(bH==="function"){if(!bw.unique||!bD.has(bI)){bB.push(bI)}}}}},e=function(bG,bF){bF=bF||[];bx=!bw.memory||[bG,bF];by=true;bA=bv||0;bv=0;bz=bB.length;for(;bB&&bA<bz;bA++){if(bB[bA].apply(bG,bF)===false&&bw.stopOnFalse){bx=true;break}}by=false;if(bB){if(!bw.once){if(bC&&bC.length){bx=bC.shift();bD.fireWith(bx[0],bx[1])}}else{if(bx===true){bD.disable()}else{bB=[]}}}},bD={add:function(){if(bB){var bF=bB.length;bE(arguments);if(by){bz=bB.length}else{if(bx&&bx!==true){bv=bF;e(bx[0],bx[1])}}}return this},remove:function(){if(bB){var bF=arguments,bH=0,bI=bF.length;for(;bH<bI;bH++){for(var bG=0;bG<bB.length;bG++){if(bF[bH]===bB[bG]){if(by){if(bG<=bz){bz--;if(bG<=bA){bA--}}}bB.splice(bG--,1);if(bw.unique){break}}}}}return this},has:function(bG){if(bB){var bF=0,bH=bB.length;for(;bF<bH;bF++){if(bG===bB[bF]){return true}}}return false},empty:function(){bB=[];return this},disable:function(){bB=bC=bx=L;return this},disabled:function(){return !bB},lock:function(){bC=L;if(!bx||bx===true){bD.disable()}return this},locked:function(){return !bC},fireWith:function(bG,bF){if(bC){if(by){if(!bw.once){bC.push([bG,bF])}}else{if(!(bw.once&&bx)){e(bG,bF)}}}return this},fire:function(){bD.fireWith(this,arguments);return this},fired:function(){return !!bx}};return bD};var aJ=[].slice;b.extend({Deferred:function(by){var bx=b.Callbacks("once memory"),bw=b.Callbacks("once memory"),bv=b.Callbacks("memory"),e="pending",bA={resolve:bx,reject:bw,notify:bv},bC={done:bx.add,fail:bw.add,progress:bv.add,state:function(){return e},isResolved:bx.fired,isRejected:bw.fired,then:function(bE,bD,bF){bB.done(bE).fail(bD).progress(bF);return this},always:function(){bB.done.apply(bB,arguments).fail.apply(bB,arguments);return this},pipe:function(bF,bE,bD){return b.Deferred(function(bG){b.each({done:[bF,"resolve"],fail:[bE,"reject"],progress:[bD,"notify"]},function(bI,bL){var bH=bL[0],bK=bL[1],bJ;if(b.isFunction(bH)){bB[bI](function(){bJ=bH.apply(this,arguments);if(bJ&&b.isFunction(bJ.promise)){bJ.promise().then(bG.resolve,bG.reject,bG.notify)}else{bG[bK+"With"](this===bB?bG:this,[bJ])}})}else{bB[bI](bG[bK])}})}).promise()},promise:function(bE){if(bE==null){bE=bC}else{for(var bD in bC){bE[bD]=bC[bD]}}return bE}},bB=bC.promise({}),bz;for(bz in bA){bB[bz]=bA[bz].fire;bB[bz+"With"]=bA[bz].fireWith}bB.done(function(){e="resolved"},bw.disable,bv.lock).fail(function(){e="rejected"},bx.disable,bv.lock);if(by){by.call(bB,bB)}return bB},when:function(bA){var bx=aJ.call(arguments,0),bv=0,e=bx.length,bB=new Array(e),bw=e,by=e,bC=e<=1&&bA&&b.isFunction(bA.promise)?bA:b.Deferred(),bE=bC.promise();function bD(bF){return function(bG){bx[bF]=arguments.length>1?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv<e;bv++){if(bx[bv]&&bx[bv].promise&&b.isFunction(bx[bv].promise)){bx[bv].promise().then(bD(bv),bC.reject,bz(bv))}else{--bw}}if(!bw){bC.resolveWith(bC,bx)}}else{if(bC!==bA){bC.resolveWith(bC,e?[bA]:[])}}return bE}});b.support=(function(){var bJ,bI,bF,bG,bx,bE,bA,bD,bz,bK,bB,by,bw,bv=av.createElement("div"),bH=av.documentElement;bv.setAttribute("className","t");bv.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav></:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="<div "+e+"><div></div></div><table "+e+" cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="<div style='width:4px;'></div>";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA<bz;bA++){delete bB[bv[bA]]}if(!(by?S:b.isEmptyObject)(bB)){return}}}if(!by){delete e[bw].data;if(!S(e[bw])){return}}if(b.support.deleteExpando||!e.setInterval){delete e[bw]}else{e[bw]=null}if(bD){if(b.support.deleteExpando){delete bx[bC]}else{if(bx.removeAttribute){bx.removeAttribute(bC)}else{bx[bC]=null}}}},_data:function(bv,e,bw){return b.data(bv,e,bw,true)},acceptData:function(bv){if(bv.nodeName){var e=b.noData[bv.nodeName.toLowerCase()];if(e){return !(e===true||bv.getAttribute("classid")!==e)}}return true}});b.fn.extend({data:function(by,bA){var bB,e,bw,bz=null;if(typeof by==="undefined"){if(this.length){bz=b.data(this[0]);if(this[0].nodeType===1&&!b._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var bx=0,bv=e.length;bx<bv;bx++){bw=e[bx].name;if(bw.indexOf("data-")===0){bw=b.camelCase(bw.substring(5));a5(this[0],bw,bz[bw])}}b._data(this[0],"parsedAttrs",true)}}return bz}else{if(typeof by==="object"){return this.each(function(){b.data(this,by)})}}bB=by.split(".");bB[1]=bB[1]?"."+bB[1]:"";if(bA===L){bz=this.triggerHandler("getData"+bB[1]+"!",[bB[0]]);if(bz===L&&this.length){bz=b.data(this[0],by);bz=a5(this[0],by,bz)}return bz===L&&bB[1]?this.data(bB[0]):bz}else{return this.each(function(){var bC=b(this),bD=[bB[0],bA];bC.triggerHandler("setData"+bB[1]+"!",bD);b.data(this,by,bA);bC.triggerHandler("changeData"+bB[1]+"!",bD)})}},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function a5(bx,bw,by){if(by===L&&bx.nodeType===1){var bv="data-"+bw.replace(aA,"-$1").toLowerCase();by=bx.getAttribute(bv);if(typeof by==="string"){try{by=by==="true"?true:by==="false"?false:by==="null"?null:b.isNumeric(by)?parseFloat(by):aS.test(by)?b.parseJSON(by):by}catch(bz){}b.data(bx,bw,by)}else{by=L}}return by}function S(bv){for(var e in bv){if(e==="data"&&b.isEmptyObject(bv[e])){continue}if(e!=="toJSON"){return false}}return true}function bi(by,bx,bA){var bw=bx+"defer",bv=bx+"queue",e=bx+"mark",bz=b._data(by,bw);if(bz&&(bA==="queue"||!b._data(by,bv))&&(bA==="mark"||!b._data(by,e))){setTimeout(function(){if(!b._data(by,bv)&&!b._data(by,e)){b.removeData(by,bw,true);bz.fire()}},0)}}b.extend({_mark:function(bv,e){if(bv){e=(e||"fx")+"mark";b._data(bv,e,(b._data(bv,e)||0)+1)}},_unmark:function(by,bx,bv){if(by!==true){bv=bx;bx=by;by=false}if(bx){bv=bv||"fx";var e=bv+"mark",bw=by?0:((b._data(bx,e)||1)-1);if(bw){b._data(bx,e,bw)}else{b.removeData(bx,e,true);bi(bx,bv,"mark")}}},queue:function(bv,e,bx){var bw;if(bv){e=(e||"fx")+"queue";bw=b._data(bv,e);if(bx){if(!bw||b.isArray(bx)){bw=b._data(bv,e,b.makeArray(bx))}else{bw.push(bx)}}return bw||[]}},dequeue:function(by,bx){bx=bx||"fx";var bv=b.queue(by,bx),bw=bv.shift(),e={};if(bw==="inprogress"){bw=bv.shift()}if(bw){if(bx==="fx"){bv.unshift("inprogress")}b._data(by,bx+".run",e);bw.call(by,function(){b.dequeue(by,bx)},e)}if(!bv.length){b.removeData(by,bx+"queue "+bx+".run",true);bi(by,bx,"queue")}}});b.fn.extend({queue:function(e,bv){if(typeof e!=="string"){bv=e;e="fx"}if(bv===L){return b.queue(this[0],e)}return this.each(function(){var bw=b.queue(this,e,bv);if(e==="fx"&&bw[0]!=="inprogress"){b.dequeue(this,e)}})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(bv,e){bv=b.fx?b.fx.speeds[bv]||bv:bv;e=e||"fx";return this.queue(e,function(bx,bw){var by=setTimeout(bx,bv);bw.stop=function(){clearTimeout(by)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(bD,bw){if(typeof bD!=="string"){bw=bD;bD=L}bD=bD||"fx";var e=b.Deferred(),bv=this,by=bv.length,bB=1,bz=bD+"defer",bA=bD+"queue",bC=bD+"mark",bx;function bE(){if(!(--bB)){e.resolveWith(bv,[bv])}}while(by--){if((bx=b.data(bv[by],bz,L,true)||(b.data(bv[by],bA,L,true)||b.data(bv[by],bC,L,true))&&b.data(bv[by],bz,b.Callbacks("once memory"),true))){bB++;bx.add(bE)}}bE();return e.promise()}});var aP=/[\n\t\r]/g,af=/\s+/,aU=/\r/g,g=/^(?:button|input)$/i,D=/^(?:button|input|object|select|textarea)$/i,l=/^a(?:rea)?$/i,ao=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,F=b.support.getSetAttribute,be,aY,aF;b.fn.extend({attr:function(e,bv){return b.access(this,e,bv,true,b.attr)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,bv){return b.access(this,e,bv,true,b.prop)},removeProp:function(e){e=b.propFix[e]||e;return this.each(function(){try{this[e]=L;delete this[e]}catch(bv){}})},addClass:function(by){var bA,bw,bv,bx,bz,bB,e;if(b.isFunction(by)){return this.each(function(bC){b(this).addClass(by.call(this,bC,this.className))})}if(by&&typeof by==="string"){bA=by.split(af);for(bw=0,bv=this.length;bw<bv;bw++){bx=this[bw];if(bx.nodeType===1){if(!bx.className&&bA.length===1){bx.className=by}else{bz=" "+bx.className+" ";for(bB=0,e=bA.length;bB<e;bB++){if(!~bz.indexOf(" "+bA[bB]+" ")){bz+=bA[bB]+" "}}bx.className=b.trim(bz)}}}}return this},removeClass:function(bz){var bA,bw,bv,by,bx,bB,e;if(b.isFunction(bz)){return this.each(function(bC){b(this).removeClass(bz.call(this,bC,this.className))})}if((bz&&typeof bz==="string")||bz===L){bA=(bz||"").split(af);for(bw=0,bv=this.length;bw<bv;bw++){by=this[bw];if(by.nodeType===1&&by.className){if(bz){bx=(" "+by.className+" ").replace(aP," ");for(bB=0,e=bA.length;bB<e;bB++){bx=bx.replace(" "+bA[bB]+" "," ")}by.className=b.trim(bx)}else{by.className=""}}}}return this},toggleClass:function(bx,bv){var bw=typeof bx,e=typeof bv==="boolean";if(b.isFunction(bx)){return this.each(function(by){b(this).toggleClass(bx.call(this,by,this.className,bv),bv)})}return this.each(function(){if(bw==="string"){var bA,bz=0,by=b(this),bB=bv,bC=bx.split(af);while((bA=bC[bz++])){bB=e?bB:!by.hasClass(bA);by[bB?"addClass":"removeClass"](bA)}}else{if(bw==="undefined"||bw==="boolean"){if(this.className){b._data(this,"__className__",this.className)}this.className=this.className||bx===false?"":b._data(this,"__className__")||""}}})},hasClass:function(e){var bx=" "+e+" ",bw=0,bv=this.length;for(;bw<bv;bw++){if(this[bw].nodeType===1&&(" "+this[bw].className+" ").replace(aP," ").indexOf(bx)>-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv<bz;bv++){bx=bC[bv];if(bx.selected&&(b.support.optDisabled?!bx.disabled:bx.getAttribute("disabled")===null)&&(!bx.parentNode.disabled||!b.nodeName(bx.parentNode,"optgroup"))){bA=b(bx).val();if(bw){return bA}bB.push(bA)}}if(bw&&!bB.length&&bC.length){return b(bC[by]).val()}return bB},set:function(bv,bw){var e=b.makeArray(bw);b(bv).find("option").each(function(){this.selected=b.inArray(b(this).val(),e)>=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType;if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw<e;bw++){bv=bA[bw];if(bv){by=b.propFix[bv]||bv;b.attr(bx,bv,"");bx.removeAttribute(F?bv:by);if(ao.test(bv)&&by in bx){bx[by]=false}}}}},attrHooks:{type:{set:function(e,bv){if(g.test(e.nodeName)&&e.parentNode){b.error("type property can't be changed")}else{if(!b.support.radioValue&&bv==="radio"&&b.nodeName(e,"input")){var bw=e.value;e.setAttribute("type",bv);if(bw){e.value=bw}return bv}}}},value:{get:function(bv,e){if(be&&b.nodeName(bv,"button")){return be.get(bv,e)}return e in bv?bv.value:null},set:function(bv,bw,e){if(be&&b.nodeName(bv,"button")){return be.set(bv,bw,e)}bv.value=bw}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(bz,bx,bA){var bw,e,by,bv=bz.nodeType;if(!bz||bv===3||bv===8||bv===2){return}by=bv!==1||!b.isXMLDoc(bz);if(by){bx=b.propFix[bx]||bx;e=b.propHooks[bx]}if(bA!==L){if(e&&"set" in e&&(bw=e.set(bz,bA,bx))!==L){return bw}else{return(bz[bx]=bA)}}else{if(e&&"get" in e&&(bw=e.get(bz,bx))!==null){return bw}else{return bz[bx]}}},propHooks:{tabIndex:{get:function(bv){var e=bv.getAttributeNode("tabindex");return e&&e.specified?parseInt(e.value,10):D.test(bv.nodeName)||l.test(bv.nodeName)&&bv.href?0:L}}}});b.attrHooks.tabindex=b.propHooks.tabIndex;aY={get:function(bv,e){var bx,bw=b.prop(bv,e);return bw===true||typeof bw!=="boolean"&&(bx=bv.getAttributeNode(e))&&bx.nodeValue!==false?e.toLowerCase():L},set:function(bv,bx,e){var bw;if(bx===false){b.removeAttr(bv,e)}else{bw=b.propFix[e]||e;if(bw in bv){bv[bw]=true}bv.setAttribute(e,e.toLowerCase())}return e}};if(!F){aF={name:true,id:true};be=b.valHooks.button={get:function(bw,bv){var e;e=bw.getAttributeNode(bv);return e&&(aF[bv]?e.nodeValue!=="":e.specified)?e.nodeValue:L},set:function(bw,bx,bv){var e=bw.getAttributeNode(bv);if(!e){e=av.createAttribute(bv);bw.setAttributeNode(e)}return(e.nodeValue=bx+"")}};b.attrHooks.tabindex.set=be.set;b.each(["width","height"],function(bv,e){b.attrHooks[e]=b.extend(b.attrHooks[e],{set:function(bw,bx){if(bx===""){bw.setAttribute(e,"auto");return bx}}})});b.attrHooks.contenteditable={get:be.get,set:function(bv,bw,e){if(bw===""){bw="false"}be.set(bv,bw,e)}}}if(!b.support.hrefNormalized){b.each(["href","src","width","height"],function(bv,e){b.attrHooks[e]=b.extend(b.attrHooks[e],{get:function(bx){var bw=bx.getAttribute(e,2);return bw===null?L:bw}})})}if(!b.support.style){b.attrHooks.style={get:function(e){return e.style.cssText.toLowerCase()||L},set:function(e,bv){return(e.style.cssText=""+bv)}}}if(!b.support.optSelected){b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(bv){var e=bv.parentNode;if(e){e.selectedIndex;if(e.parentNode){e.parentNode.selectedIndex}}return null}})}if(!b.support.enctype){b.propFix.enctype="encoding"}if(!b.support.checkOn){b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}})}b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,bv){if(b.isArray(bv)){return(e.checked=b.inArray(b(e).val(),bv)>=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI<bC.length;bI++){bH=n.exec(bC[bI])||[];bF=bH[1];e=(bH[2]||"").split(".").sort();bE=b.event.special[bF]||{};bF=(by?bE.delegateType:bE.bindType)||bF;bE=b.event.special[bF]||{};bG=b.extend({type:bF,origType:bH[1],data:bA,handler:bJ,guid:bJ.guid,selector:by,quick:Y(by),namespace:e.join(".")},bv);bw=bK[bF];if(!bw){bw=bK[bF]=[];bw.delegateCount=0;if(!bE.setup||bE.setup.call(bx,bA,e,bB)===false){if(bx.addEventListener){bx.addEventListener(bF,bB,false)}else{if(bx.attachEvent){bx.attachEvent("on"+bF,bB)}}}}if(bE.add){bE.add.call(bx,bG);if(!bG.handler.guid){bG.handler.guid=bJ.guid}}if(by){bw.splice(bw.delegateCount++,0,bG)}else{bw.push(bG)}b.event.global[bF]=true}bx=null},global:{},remove:function(bJ,bE,bv,bH,bB){var bI=b.hasData(bJ)&&b._data(bJ),bF,bx,bz,bL,bC,bA,bG,bw,by,bK,bD,e;if(!bI||!(bw=bI.events)){return}bE=b.trim(bt(bE||"")).split(" ");for(bF=0;bF<bE.length;bF++){bx=n.exec(bE[bF])||[];bz=bL=bx[1];bC=bx[2];if(!bz){for(bz in bw){b.event.remove(bJ,bz+bE[bF],bv,bH,true)}continue}by=b.event.special[bz]||{};bz=(bH?by.delegateType:by.bindType)||bz;bD=bw[bz]||[];bA=bD.length;bC=bC?new RegExp("(^|\\.)"+bC.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(bG=0;bG<bD.length;bG++){e=bD[bG];if((bB||bL===e.origType)&&(!bv||bv.guid===e.guid)&&(!bC||bC.test(e.namespace))&&(!bH||bH===e.selector||bH==="**"&&e.selector)){bD.splice(bG--,1);if(e.selector){bD.delegateCount--}if(by.remove){by.remove.call(bJ,e)}}}if(bD.length===0&&bA!==bD.length){if(!by.teardown||by.teardown.call(bJ,bC)===false){b.removeEvent(bJ,bz,bI.handle)}delete bw[bz]}}if(b.isEmptyObject(bw)){bK=bI.handle;if(bK){bK.elem=null}b.removeData(bJ,["events","handle"],true)}},customEvent:{getData:true,setData:true,changeData:true},trigger:function(bv,bD,bA,bJ){if(bA&&(bA.nodeType===3||bA.nodeType===8)){return}var bG=bv.type||bv,bx=[],e,bw,bC,bH,bz,by,bF,bE,bB,bI;if(T.test(bG+b.event.triggered)){return}if(bG.indexOf("!")>=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bC<bB.length&&!bv.isPropagationStopped();bC++){bH=bB[bC][0];bv.type=bB[bC][1];bE=(b._data(bH,"events")||{})[bv.type]&&b._data(bH,"handle");if(bE){bE.apply(bH,bD)}bE=by&&bH[by];if(bE&&b.acceptData(bH)&&bE.apply(bH,bD)===false){bv.preventDefault()}}bv.type=bG;if(!bJ&&!bv.isDefaultPrevented()){if((!bF._default||bF._default.apply(bA.ownerDocument,bD)===false)&&!(bG==="click"&&b.nodeName(bA,"a"))&&b.acceptData(bA)){if(by&&bA[bG]&&((bG!=="focus"&&bG!=="blur")||bv.target.offsetWidth!==0)&&!b.isWindow(bA)){bz=bA[by];if(bz){bA[by]=null}b.event.triggered=bG;bA[bG]();b.event.triggered=L;if(bz){bA[by]=bz}}}}return bv.result},dispatch:function(e){e=b.event.fix(e||bb.event);var bz=((b._data(this,"events")||{})[e.type]||[]),bA=bz.delegateCount,bG=[].slice.call(arguments,0),by=!e.exclusive&&!e.namespace,bH=[],bC,bB,bK,bx,bF,bE,bv,bD,bI,bw,bJ;bG[0]=e;e.delegateTarget=this;if(bA&&!e.target.disabled&&!(e.button&&e.type==="click")){bx=b(this);bx.context=this.ownerDocument||this;for(bK=e.target;bK!=this;bK=bK.parentNode||this){bE={};bD=[];bx[0]=bK;for(bC=0;bC<bA;bC++){bI=bz[bC];bw=bI.selector;if(bE[bw]===L){bE[bw]=(bI.quick?j(bK,bI.quick):bx.is(bw))}if(bE[bw]){bD.push(bI)}}if(bD.length){bH.push({elem:bK,matches:bD})}}}if(bz.length>bA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC<bH.length&&!e.isPropagationStopped();bC++){bv=bH[bC];e.currentTarget=bv.elem;for(bB=0;bB<bv.matches.length&&!e.isImmediatePropagationStopped();bB++){bI=bv.matches[bB];if(by||(!e.namespace&&!bI.namespace)||e.namespace_re&&e.namespace_re.test(bI.namespace)){e.data=bI.data;e.handleObj=bI;bF=((b.event.special[bI.origType]||{}).handle||bI.handler).apply(bv.elem,bG);if(bF!==L){e.result=bF;if(bF===false){e.preventDefault();e.stopPropagation()}}}}}return e.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(bv,e){if(bv.which==null){bv.which=e.charCode!=null?e.charCode:e.keyCode}return bv}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(bx,bw){var by,bz,e,bv=bw.button,bA=bw.fromElement;if(bx.pageX==null&&bw.clientX!=null){by=bx.target.ownerDocument||av;bz=by.documentElement;e=by.body;bx.pageX=bw.clientX+(bz&&bz.scrollLeft||e&&e.scrollLeft||0)-(bz&&bz.clientLeft||e&&e.clientLeft||0);bx.pageY=bw.clientY+(bz&&bz.scrollTop||e&&e.scrollTop||0)-(bz&&bz.clientTop||e&&e.clientTop||0)}if(!bx.relatedTarget&&bA){bx.relatedTarget=bA===bx.target?bw.toElement:bA}if(!bx.which&&bv!==L){bx.which=(bv&1?1:(bv&2?3:(bv&4?2:0)))}return bx}},fix:function(bw){if(bw[b.expando]){return bw}var bv,bz,e=bw,bx=b.event.fixHooks[bw.type]||{},by=bx.props?this.props.concat(bx.props):this.props;bw=b.Event(e);for(bv=by.length;bv;){bz=by[--bv];bw[bz]=e[bz]}if(!bw.target){bw.target=e.srcElement||av}if(bw.target.nodeType===3){bw.target=bw.target.parentNode}if(bw.metaKey===L){bw.metaKey=bw.ctrlKey}return bx.filter?bx.filter(bw,e):bw},special:{ready:{setup:b.bindReady},load:{noBubble:true},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(bw,bv,e){if(b.isWindow(this)){this.onbeforeunload=e}},teardown:function(bv,e){if(this.onbeforeunload===e){this.onbeforeunload=null}}}},simulate:function(bw,by,bx,bv){var bz=b.extend(new b.Event(),bx,{type:bw,isSimulated:true,originalEvent:{}});if(bv){b.event.trigger(bz,null,by)}else{b.event.dispatch.call(by,bz)}if(bz.isDefaultPrevented()){bx.preventDefault()}}};b.event.handle=b.event.dispatch;b.removeEvent=av.removeEventListener?function(bv,e,bw){if(bv.removeEventListener){bv.removeEventListener(e,bw,false)}}:function(bv,e,bw){if(bv.detachEvent){bv.detachEvent("on"+e,bw)}};b.Event=function(bv,e){if(!(this instanceof b.Event)){return new b.Event(bv,e)}if(bv&&bv.type){this.originalEvent=bv;this.type=bv.type;this.isDefaultPrevented=(bv.defaultPrevented||bv.returnValue===false||bv.getPreventDefault&&bv.getPreventDefault())?i:bk}else{this.type=bv}if(e){b.extend(this,e)}this.timeStamp=bv&&bv.timeStamp||b.now();this[b.expando]=true};function bk(){return false}function i(){return true}b.Event.prototype={preventDefault:function(){this.isDefaultPrevented=i;var bv=this.originalEvent;if(!bv){return}if(bv.preventDefault){bv.preventDefault()}else{bv.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=i;var bv=this.originalEvent;if(!bv){return}if(bv.stopPropagation){bv.stopPropagation()}bv.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=i;this.stopPropagation()},isDefaultPrevented:bk,isPropagationStopped:bk,isImmediatePropagationStopped:bk};b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(bv,e){b.event.special[bv]={delegateType:e,bindType:e,handle:function(bz){var bB=this,bA=bz.relatedTarget,by=bz.handleObj,bw=by.selector,bx;if(!bA||(bA!==bB&&!b.contains(bB,bA))){bz.type=by.origType;bx=by.handler.apply(this,arguments);bz.type=e}return bx}}});if(!b.support.submitBubbles){b.event.special.submit={setup:function(){if(b.nodeName(this,"form")){return false}b.event.add(this,"click._submit keypress._submit",function(bx){var bw=bx.target,bv=b.nodeName(bw,"input")||b.nodeName(bw,"button")?bw.form:L;if(bv&&!bv._submit_attached){b.event.add(bv,"submit._submit",function(e){if(this.parentNode&&!e.isTrigger){b.event.simulate("submit",this.parentNode,e,true)}});bv._submit_attached=true}})},teardown:function(){if(b.nodeName(this,"form")){return false}b.event.remove(this,"._submit")}}}if(!b.support.changeBubbles){b.event.special.change={setup:function(){if(bd.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio"){b.event.add(this,"propertychange._change",function(e){if(e.originalEvent.propertyName==="checked"){this._just_changed=true}});b.event.add(this,"click._change",function(e){if(this._just_changed&&!e.isTrigger){this._just_changed=false;b.event.simulate("change",this,e,true)}})}return false}b.event.add(this,"beforeactivate._change",function(bw){var bv=bw.target;if(bd.test(bv.nodeName)&&!bv._change_attached){b.event.add(bv,"change._change",function(e){if(this.parentNode&&!e.isSimulated&&!e.isTrigger){b.event.simulate("change",this.parentNode,e,true)}});bv._change_attached=true}})},handle:function(bv){var e=bv.target;if(this!==e||bv.isSimulated||bv.isTrigger||(e.type!=="radio"&&e.type!=="checkbox")){return bv.handleObj.handler.apply(this,arguments)}},teardown:function(){b.event.remove(this,"._change");return bd.test(this.nodeName)}}}if(!b.support.focusinBubbles){b.each({focus:"focusin",blur:"focusout"},function(bx,e){var bv=0,bw=function(by){b.event.simulate(e,by.target,b.event.fix(by),true)};b.event.special[e]={setup:function(){if(bv++===0){av.addEventListener(bx,bw,true)}},teardown:function(){if(--bv===0){av.removeEventListener(bx,bw,true)}}}})}b.fn.extend({on:function(bw,e,bz,by,bv){var bA,bx;if(typeof bw==="object"){if(typeof e!=="string"){bz=e;e=L}for(bx in bw){this.on(bx,e,bz,bw[bx],bv)}return this}if(bz==null&&by==null){by=e;bz=e=L}else{if(by==null){if(typeof e==="string"){by=bz;bz=L}else{by=bz;bz=e;e=L}}}if(by===false){by=bk}else{if(!by){return this}}if(bv===1){bA=by;by=function(bB){b().off(bB);return bA.apply(this,arguments)};by.guid=bA.guid||(bA.guid=b.guid++)}return this.each(function(){b.event.add(this,bw,by,bz,e)})},one:function(bv,e,bx,bw){return this.on.call(this,bv,e,bx,bw,1)},off:function(bw,e,by){if(bw&&bw.preventDefault&&bw.handleObj){var bv=bw.handleObj;b(bw.delegateTarget).off(bv.namespace?bv.type+"."+bv.namespace:bv.type,bv.selector,bv.handler);return this}if(typeof bw==="object"){for(var bx in bw){this.off(bx,e,bw[bx])}return this}if(e===false||typeof e==="function"){by=e;e=L}if(by===false){by=bk}return this.each(function(){b.event.remove(this,bw,by,e)})},bind:function(e,bw,bv){return this.on(e,null,bw,bv)},unbind:function(e,bv){return this.off(e,null,bv)},live:function(e,bw,bv){b(this.context).on(e,this.selector,bw,bv);return this},die:function(e,bv){b(this.context).off(e,this.selector||"**",bv);return this},delegate:function(e,bv,bx,bw){return this.on(bv,e,bx,bw)},undelegate:function(e,bv,bw){return arguments.length==1?this.off(e,"**"):this.off(bv,e,bw)},trigger:function(e,bv){return this.each(function(){b.event.trigger(e,bv,this)})},triggerHandler:function(e,bv){if(this[0]){return b.event.trigger(e,bv,this[0],true)}},toggle:function(bx){var bv=arguments,e=bx.guid||b.guid++,bw=0,by=function(bz){var bA=(b._data(this,"lastToggle"+bx.guid)||0)%bw;b._data(this,"lastToggle"+bx.guid,bA+1);bz.preventDefault();return bv[bA].apply(this,arguments)||false};by.guid=e;while(bw<bv.length){bv[bw++].guid=e}return this.click(by)},hover:function(e,bv){return this.mouseenter(e).mouseleave(bv||e)}});b.each(("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu").split(" "),function(bv,e){b.fn[e]=function(bx,bw){if(bw==null){bw=bx;bx=null}return arguments.length>0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}});
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e<bR.length;e++){if(bR[e]===bR[e-1]){bR.splice(e--,1)}}}}return bR};by.matches=function(e,bR){return by(e,null,null,bR)};by.matchesSelector=function(e,bR){return by(bR,null,null,[e]).length>0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS<bU;bS++){bV=bE.order[bS];if((bT=bE.leftMatch[bV].exec(bX))){bR=bT[1];bT.splice(1,1);if(bR.substr(bR.length-1)!=="\\"){bT[1]=(bT[1]||"").replace(bK,"");bW=bE.find[bV](bT,e,bY);if(bW!=null){bX=bX.replace(bE.match[bV],"");break}}}}if(!bW){bW=typeof e.getElementsByTagName!=="undefined"?e.getElementsByTagName("*"):[]}return{set:bW,expr:bX}};by.filter=function(b1,b0,b4,bU){var bW,e,bZ,b6,b3,bR,bT,bV,b2,bS=b1,b5=[],bY=b0,bX=b0&&b0[0]&&by.isXML(b0[0]);while(b1&&b0.length){for(bZ in bE.filter){if((bW=bE.leftMatch[bZ].exec(b1))!=null&&bW[2]){bR=bE.filter[bZ];bT=bW[1];e=false;bW.splice(1,1);if(bT.substr(bT.length-1)==="\\"){continue}if(bY===b5){b5=[]}if(bE.preFilter[bZ]){bW=bE.preFilter[bZ](bW,bY,b4,b5,bU,bX);if(!bW){e=b6=true}else{if(bW===true){continue}}}if(bW){for(bV=0;(b3=bY[bV])!=null;bV++){if(b3){b6=bR(b3,bW,bV,bY);b2=bU^b6;if(b4&&b6!=null){if(b2){e=true}else{bY[bV]=false}}else{if(b2){b5.push(b3);e=true}}}}}if(b6!==L){if(!b4){bY=b5}b1=b1.replace(bE.match[bZ],"");if(!e){return[]}break}}}if(b1===bS){if(e==null){by.error(b1)}else{break}}bS=b1}return bY};by.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)};var bw=by.getText=function(bU){var bS,bT,e=bU.nodeType,bR="";if(e){if(e===1||e===9){if(typeof bU.textContent==="string"){return bU.textContent}else{if(typeof bU.innerText==="string"){return bU.innerText.replace(bO,"")}else{for(bU=bU.firstChild;bU;bU=bU.nextSibling){bR+=bw(bU)}}}}else{if(e===3||e===4){return bU.nodeValue}}}else{for(bS=0;(bT=bU[bS]);bS++){if(bT.nodeType!==8){bR+=bw(bT)}}}return bR};var bE=by.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(e){return e.getAttribute("href")},type:function(e){return e.getAttribute("type")}},relative:{"+":function(bW,bR){var bT=typeof bR==="string",bV=bT&&!bQ.test(bR),bX=bT&&!bV;if(bV){bR=bR.toLowerCase()}for(var bS=0,e=bW.length,bU;bS<e;bS++){if((bU=bW[bS])){while((bU=bU.previousSibling)&&bU.nodeType!==1){}bW[bS]=bX||bU&&bU.nodeName.toLowerCase()===bR?bU||false:bU===bR}}if(bX){by.filter(bR,bW,true)}},">":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS<e;bS++){bV=bW[bS];if(bV){var bT=bV.parentNode;bW[bS]=bT.nodeName.toLowerCase()===bR?bT:false}}}else{for(;bS<e;bS++){bV=bW[bS];if(bV){bW[bS]=bU?bV.parentNode:bV.parentNode===bR}}if(bU){by.filter(bR,bW,true)}}},"":function(bT,bR,bV){var bU,bS=bI++,e=bN;if(typeof bR==="string"&&!bQ.test(bR)){bR=bR.toLowerCase();bU=bR;e=bv}e("parentNode",bR,bS,bT,bU,bV)},"~":function(bT,bR,bV){var bU,bS=bI++,e=bN;if(typeof bR==="string"&&!bQ.test(bR)){bR=bR.toLowerCase();bU=bR;e=bv}e("previousSibling",bR,bS,bT,bU,bV)}},find:{ID:function(bR,bS,bT){if(typeof bS.getElementById!=="undefined"&&!bT){var e=bS.getElementById(bR[1]);return e&&e.parentNode?[e]:[]}},NAME:function(bS,bV){if(typeof bV.getElementsByName!=="undefined"){var bR=[],bU=bV.getElementsByName(bS[1]);for(var bT=0,e=bU.length;bT<e;bT++){if(bU[bT].getAttribute("name")===bS[1]){bR.push(bU[bT])}}return bR.length===0?null:bR}},TAG:function(e,bR){if(typeof bR.getElementsByTagName!=="undefined"){return bR.getElementsByTagName(e[1])}}},preFilter:{CLASS:function(bT,bR,bS,e,bW,bX){bT=" "+bT[1].replace(bK,"")+" ";if(bX){return bT}for(var bU=0,bV;(bV=bR[bU])!=null;bU++){if(bV){if(bW^(bV.className&&(" "+bV.className+" ").replace(/[\t\n\r]/g," ").indexOf(bT)>=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1},lt:function(bS,bR,e){return bR<e[3]-0},gt:function(bS,bR,e){return bR>e[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV<bU;bV++){if(bT[bV]===bS){return false}}return true}else{by.error(e)}}}},CHILD:function(bS,bU){var bT,b0,bW,bZ,e,bV,bY,bX=bU[1],bR=bS;switch(bX){case"only":case"first":while((bR=bR.previousSibling)){if(bR.nodeType===1){return false}}if(bX==="first"){return true}bR=bS;case"last":while((bR=bR.nextSibling)){if(bR.nodeType===1){return false}}return true;case"nth":bT=bU[2];b0=bU[3];if(bT===1&&b0===0){return true}bW=bU[0];bZ=bS.parentNode;if(bZ&&(bZ[bC]!==bW||!bS.nodeIndex)){bV=0;for(bR=bZ.firstChild;bR;bR=bR.nextSibling){if(bR.nodeType===1){bR.nodeIndex=++bV}}bZ[bC]=bW}bY=bS.nodeIndex-b0;if(bT===0){return bY===0}else{return(bY%bT===0&&bY/bT>=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS<e;bS++){bR.push(bU[bS])}}else{for(;bU[bS];bS++){bR.push(bU[bS])}}}return bR}}var bJ,bG;if(av.documentElement.compareDocumentPosition){bJ=function(bR,e){if(bR===e){bB=true;return 0}if(!bR.compareDocumentPosition||!e.compareDocumentPosition){return bR.compareDocumentPosition?-1:1}return bR.compareDocumentPosition(e)&4?-1:1}}else{bJ=function(bY,bX){if(bY===bX){bB=true;return 0}else{if(bY.sourceIndex&&bX.sourceIndex){return bY.sourceIndex-bX.sourceIndex}}var bV,bR,bS=[],e=[],bU=bY.parentNode,bW=bX.parentNode,bZ=bU;if(bU===bW){return bG(bY,bX)}else{if(!bU){return -1}else{if(!bW){return 1}}}while(bZ){bS.unshift(bZ);bZ=bZ.parentNode}bZ=bW;while(bZ){e.unshift(bZ);bZ=bZ.parentNode}bV=bS.length;bR=e.length;for(var bT=0;bT<bV&&bT<bR;bT++){if(bS[bT]!==e[bT]){return bG(bS[bT],e[bT])}}return bT===bV?bG(bY,e[bT],-1):bG(bS[bT],bX,1)};bG=function(bR,e,bS){if(bR===e){return bS}var bT=bR.nextSibling;while(bT){if(bT===e){return -1}bT=bT.nextSibling}return 1}}(function(){var bR=av.createElement("div"),bS="script"+(new Date()).getTime(),e=av.documentElement;bR.innerHTML="<a name='"+bS+"'/>";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="<a href='#'></a>";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="<p class='TEST'></p>";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="<div class='test e'></div><div class='test'></div>";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT<bS;bT++){var e=bZ[bT];if(e){var bU=false;e=e[bR];while(e){if(e[bC]===bV){bU=bZ[e.sizset];break}if(e.nodeType===1&&!bY){e[bC]=bV;e.sizset=bT}if(e.nodeName.toLowerCase()===bW){bU=e;break}e=e[bR]}bZ[bT]=bU}}}function bN(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT<bS;bT++){var e=bZ[bT];if(e){var bU=false;e=e[bR];while(e){if(e[bC]===bV){bU=bZ[e.sizset];break}if(e.nodeType===1){if(!bY){e[bC]=bV;e.sizset=bT}if(typeof bW!=="string"){if(e===bW){bU=true;break}}else{if(by.filter(bW,[e]).length>0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT<bR;bT++){by(bS,bY[bT],bX,bW)}return by.filter(bU,bX)};by.attr=b.attr;by.selectors.attrMap={};b.find=by;b.expr=by.selectors;b.expr[":"]=b.expr.filters;b.unique=by.uniqueSort;b.text=by.getText;b.isXMLDoc=by.isXML;b.contains=by.contains})();var ab=/Until$/,aq=/^(?:parents|prevUntil|prevAll)/,a9=/,/,bp=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,H=b.expr.match.POS,ay={children:true,contents:true,next:true,prev:true};b.fn.extend({find:function(e){var bw=this,by,bv;if(typeof e!=="string"){return b(e).filter(function(){for(by=0,bv=bw.length;by<bv;by++){if(b.contains(bw[by],this)){return true}}})}var bx=this.pushStack("","find",e),bA,bB,bz;for(by=0,bv=this.length;by<bv;by++){bA=bx.length;b.find(e,this[by],bx);if(by>0){for(bB=bA;bB<bx.length;bB++){for(bz=0;bz<bA;bz++){if(bx[bz]===bx[bB]){bx.splice(bB--,1);break}}}}}return bx},has:function(bv){var e=b(bv);return this.filter(function(){for(var bx=0,bw=e.length;bx<bw;bx++){if(b.contains(this,e[bx])){return true}}})},not:function(e){return this.pushStack(aG(this,e,false),"not",e)},filter:function(e){return this.pushStack(aG(this,e,true),"filter",e)},is:function(e){return !!e&&(typeof e==="string"?H.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw<by.length;bw++){if(b(bz).is(by[bw])){bv.push({selector:by[bw],elem:bz,level:bB})}}bz=bz.parentNode;bB++}return bv}var bA=H.test(by)||typeof by!=="string"?b(by,bx||this.context):0;for(bw=0,e=this.length;bw<e;bw++){bz=this[bw];while(bz){if(bA?bA.index(bz)>-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/<tbody/i,W=/<|&#?\w+;/,ae=/<(?:script|style)/i,O=/<(?:script|object|embed|option|style)/i,ah=new RegExp("<(?:"+aR+")","i"),o=/checked\s*(?:[^=]|=\s*.checked.)/i,bm=/\/(java|ecma)script/i,aN=/^\s*<!(?:\[CDATA\[|\-\-)/,ax={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},ac=a(av);ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div<div>","</div>"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1></$2>");try{for(var bw=0,bv=this.length;bw<bv;bw++){if(this[bw].nodeType===1){b.cleanData(this[bw].getElementsByTagName("*"));this[bw].innerHTML=bx}}}catch(by){this.empty().append(bx)}}else{if(b.isFunction(bx)){this.each(function(bz){var e=b(this);e.html(bx.call(this,bz,e.html()))})}else{this.empty().append(bx)}}}return this},replaceWith:function(e){if(this[0]&&this[0].parentNode){if(b.isFunction(e)){return this.each(function(bx){var bw=b(this),bv=bw.html();bw.replaceWith(e.call(this,bx,bv))})}if(typeof e!=="string"){e=b(e).detach()}return this.each(function(){var bw=this.nextSibling,bv=this.parentNode;b(this).remove();if(bw){b(bw).before(e)}else{b(bv).append(e)}})}else{return this.length?this.pushStack(b(b.isFunction(e)?e():e),"replaceWith",e):this}},detach:function(e){return this.remove(e,true)},domManip:function(bB,bF,bE){var bx,by,bA,bD,bC=bB[0],bv=[];if(!b.support.checkClone&&arguments.length===3&&typeof bC==="string"&&o.test(bC)){return this.each(function(){b(this).domManip(bB,bF,bE,true)})}if(b.isFunction(bC)){return this.each(function(bH){var bG=b(this);bB[0]=bC.call(this,bH,bF?bG.html():L);bG.domManip(bB,bF,bE)})}if(this[0]){bD=bC&&bC.parentNode;if(b.support.parentNode&&bD&&bD.nodeType===11&&bD.childNodes.length===this.length){bx={fragment:bD}}else{bx=b.buildFragment(bB,this,bv)}bA=bx.fragment;if(bA.childNodes.length===1){by=bA=bA.firstChild}else{by=bA.firstChild}if(by){bF=bF&&b.nodeName(by,"tr");for(var bw=0,e=this.length,bz=e-1;bw<e;bw++){bE.call(bF?ba(this[bw],by):this[bw],bx.cacheable||(e>1&&bw<bz)?b.clone(bA,true,true):bA)}}if(bv.length){b.each(bv,bo)}}return this}});function ba(e,bv){return b.nodeName(e,"table")?(e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody"))):e}function t(bB,bv){if(bv.nodeType!==1||!b.hasData(bB)){return}var by,bx,e,bA=b._data(bB),bz=b._data(bv,bA),bw=bA.events;if(bw){delete bz.handle;bz.events={};for(by in bw){for(bx=0,e=bw[by].length;bx<e;bx++){b.event.add(bv,by+(bw[by][bx].namespace?".":"")+bw[by][bx].namespace,bw[by][bx],bw[by][bx].data)}}}if(bz.data){bz.data=b.extend({},bz.data)}}function ai(bv,e){var bw;if(e.nodeType!==1){return}if(e.clearAttributes){e.clearAttributes()}if(e.mergeAttributes){e.mergeAttributes(bv)}bw=e.nodeName.toLowerCase();if(bw==="object"){e.outerHTML=bv.outerHTML}else{if(bw==="input"&&(bv.type==="checkbox"||bv.type==="radio")){if(bv.checked){e.defaultChecked=e.checked=bv.checked}if(e.value!==bv.value){e.value=bv.value}}else{if(bw==="option"){e.selected=bv.defaultSelected}else{if(bw==="input"||bw==="textarea"){e.defaultValue=bv.defaultValue}}}}e.removeAttribute(b.expando)}b.buildFragment=function(bz,bx,bv){var by,e,bw,bA,bB=bz[0];if(bx&&bx[0]){bA=bx[0].ownerDocument||bx[0]}if(!bA.createDocumentFragment){bA=av}if(bz.length===1&&typeof bB==="string"&&bB.length<512&&bA===av&&bB.charAt(0)==="<"&&!O.test(bB)&&(b.support.checkClone||!o.test(bB))&&(b.support.html5Clone||!ah.test(bB))){e=true;bw=b.fragments[bB];if(bw&&bw!==1){by=bw}}if(!by){by=bA.createDocumentFragment();b.clean(bz,bA,by,bv)}if(e){b.fragments[bB]=bw?by:1}return{fragment:by,cacheable:e}};b.fragments={};b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,bv){b.fn[e]=function(bw){var bz=[],bC=b(bw),bB=this.length===1&&this[0].parentNode;if(bB&&bB.nodeType===11&&bB.childNodes.length===1&&bC.length===1){bC[bv](this[0]);return this}else{for(var bA=0,bx=bC.length;bA<bx;bA++){var by=(bA>0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1></$2>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]==="<table>"&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB<bG;bB++){E(bz[bB])}}else{E(bz)}}if(bz.nodeType){bI.push(bz)}else{bI=b.merge(bI,bz)}}if(bH){bF=function(bL){return !bL.type||bm.test(bL.type)};for(bE=0;bI[bE];bE++){if(bA&&b.nodeName(bI[bE],"script")&&(!bI[bE].type||bI[bE].type.toLowerCase()==="text/javascript")){bA.push(bI[bE].parentNode?bI[bE].parentNode.removeChild(bI[bE]):bI[bE])}else{if(bI[bE].nodeType===1){var bJ=b.grep(bI[bE].getElementsByTagName("script"),bF);bI.splice.apply(bI,[bE+1,0].concat(bJ))}bH.appendChild(bI[bE])}}}return bI},cleanData:function(bv){var by,bw,e=b.cache,bB=b.event.special,bA=b.support.deleteExpando;for(var bz=0,bx;(bx=bv[bz])!=null;bz++){if(bx.nodeName&&b.noData[bx.nodeName.toLowerCase()]){continue}bw=bx[b.expando];if(bw){by=e[bw];if(by&&by.events){for(var bC in by.events){if(bB[bC]){b.event.remove(bx,bC)}else{b.removeEvent(bx,bC,by.handle)}}if(by.handle){by.handle.elem=null}}if(bA){delete bx[b.expando]}else{if(bx.removeAttribute){bx.removeAttribute(b.expando)}}delete e[bw]}}}});function bo(e,bv){if(bv.src){b.ajax({url:bv.src,async:false,dataType:"script"})}else{b.globalEval((bv.text||bv.textContent||bv.innerHTML||"").replace(aN,"/*$0*/"))}if(bv.parentNode){bv.parentNode.removeChild(bv)}}var ak=/alpha\([^)]*\)/i,au=/opacity=([^)]*)/,z=/([A-Z]|^ms)/g,bc=/^-?\d+(?:px)?$/i,bn=/^-?\d/,I=/^([\-+])=([\-+.\de]+)/,a7={position:"absolute",visibility:"hidden",display:"block"},an=["Left","Right"],a1=["Top","Bottom"],Z,aI,aX;b.fn.css=function(e,bv){if(arguments.length===2&&bv===L){return this}return b.access(this,e,bv,true,function(bx,bw,by){return by!==L?b.style(bx,bw,by):b.css(bx,bw)})};b.extend({cssHooks:{opacity:{get:function(bw,bv){if(bv){var e=Z(bw,"opacity","opacity");return e===""?"1":e}else{return bw.style.opacity}}}},cssNumber:{fillOpacity:true,fontWeight:true,lineHeight:true,opacity:true,orphans:true,widows:true,zIndex:true,zoom:true},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(bx,bw,bD,by){if(!bx||bx.nodeType===3||bx.nodeType===8||!bx.style){return}var bB,bC,bz=b.camelCase(bw),bv=bx.style,bE=b.cssHooks[bz];bw=b.cssProps[bz]||bz;if(bD!==L){bC=typeof bD;if(bC==="string"&&(bB=I.exec(bD))){bD=(+(bB[1]+1)*+bB[2])+parseFloat(b.css(bx,bw));bC="number"}if(bD==null||bC==="number"&&isNaN(bD)){return}if(bC==="number"&&!b.cssNumber[bz]){bD+="px"}if(!bE||!("set" in bE)||(bD=bE.set(bx,bD))!==L){try{bv[bw]=bD}catch(bA){}}}else{if(bE&&"get" in bE&&(bB=bE.get(bx,false,by))!==L){return bB}return bv[bw]}},css:function(by,bx,bv){var bw,e;bx=b.camelCase(bx);e=b.cssHooks[bx];bx=b.cssProps[bx]||bx;if(bx==="cssFloat"){bx="float"}if(e&&"get" in e&&(bw=e.get(by,true,bv))!==L){return bw}else{if(Z){return Z(by,bx)}}},swap:function(bx,bw,by){var e={};for(var bv in bw){e[bv]=bx.style[bv];bx.style[bv]=bw[bv]}by.call(bx);for(bv in bw){bx.style[bv]=e[bv]}}});b.curCSS=b.css;b.each(["height","width"],function(bv,e){b.cssHooks[e]={get:function(by,bx,bw){var bz;if(bx){if(by.offsetWidth!==0){return p(by,e,bw)}else{b.swap(by,a7,function(){bz=p(by,e,bw)})}return bz}},set:function(bw,bx){if(bc.test(bx)){bx=parseFloat(bx);if(bx>=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length;if(bA>0){if(bv!=="border"){for(;bx<e;bx++){if(!bv){bA-=parseFloat(b.css(by,"padding"+bz[bx]))||0}if(bv==="margin"){bA+=parseFloat(b.css(by,bv+bz[bx]))||0}else{bA-=parseFloat(b.css(by,"border"+bz[bx]+"Width"))||0}}}return bA+"px"}bA=Z(by,bw,bw);if(bA<0||bA==null){bA=by.style[bw]||0}bA=parseFloat(bA)||0;if(bv){for(;bx<e;bx++){bA+=parseFloat(b.css(by,"padding"+bz[bx]))||0;if(bv!=="padding"){bA+=parseFloat(b.css(by,"border"+bz[bx]+"Width"))||0}if(bv==="margin"){bA+=parseFloat(b.css(by,bv+bz[bx]))||0}}}return bA+"px"}if(b.expr&&b.expr.filters){b.expr.filters.hidden=function(bw){var bv=bw.offsetWidth,e=bw.offsetHeight;return(bv===0&&e===0)||(!b.support.reliableHiddenOffsets&&((bw.style&&bw.style.display)||b.css(bw,"display"))==="none")};b.expr.filters.visible=function(e){return !b.expr.filters.hidden(e)}}var k=/%20/g,ap=/\[\]$/,bs=/\r?\n/g,bq=/#.*$/,aD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,aZ=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,aM=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,aQ=/^(?:GET|HEAD)$/,c=/^\/\//,M=/\?/,a6=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw<bz;bw++){bv=bx[bw];bC=/^\+/.test(bv);if(bC){bv=bv.substr(1)||"*"}bB=e[bv]=e[bv]||[];bB[bC?"unshift":"push"](bA)}}}}function aW(bv,bE,bz,bD,bB,bx){bB=bB||bE.dataTypes[0];bx=bx||{};bx[bB]=true;var bA=bv[bB],bw=0,e=bA?bA.length:0,by=(bv===aa),bC;for(;bw<e&&(by||!bC);bw++){bC=bA[bw](bE,bz,bD);if(typeof bC==="string"){if(!by||bx[bC]){bC=L}else{bE.dataTypes.unshift(bC);bC=aW(bv,bE,bz,bD,bC,bx)}}}if((by||!bC)&&!bx["*"]){bC=aW(bv,bE,bz,bD,"*",bx)}return bC}function am(bw,bx){var bv,e,by=b.ajaxSettings.flatOptions||{};for(bv in bx){if(bx[bv]!==L){(by[bv]?bw:(e||(e={})))[bv]=bx[bv]}}if(e){b.extend(true,bw,e)}}b.fn.extend({load:function(bw,bz,bA){if(typeof bw!=="string"&&A){return A.apply(this,arguments)}else{if(!this.length){return this}}var by=bw.indexOf(" ");if(by>=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("<div>").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA<bw;bA++){if(bA===1){for(bE in bH.converters){if(typeof bE==="string"){bG[bE.toLowerCase()]=bH.converters[bE]}}}bx=bC;bC=bD[bA];if(bC==="*"){bC=bx}else{if(bx!=="*"&&bx!==bC){by=bx+" "+bC;bF=bG[by]||bG["* "+bC];if(!bF){e=L;for(bv in bG){bB=bv.split(" ");if(bB[0]===bx||bB[0]==="*"){e=bG[bB[1]+" "+bC];if(e){bv=bG[bv];if(bv===true){bF=e}else{if(e===true){bF=bv}}break}}}}if(!(bF||e)){b.error("No conversion from "+by.replace(" "," to "))}if(bF!==true){bz=bF?bF(bz):e(bv(bz))}}}}return bz}var aC=b.now(),u=/(\=)\?(&|$)|\?\?/i;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return b.expando+"_"+(aC++)}});b.ajaxPrefilter("json jsonp",function(bD,bA,bC){var bx=bD.contentType==="application/x-www-form-urlencoded"&&(typeof bD.data==="string");if(bD.dataTypes[0]==="jsonp"||bD.jsonp!==false&&(u.test(bD.url)||bx&&u.test(bD.data))){var bB,bw=bD.jsonpCallback=b.isFunction(bD.jsonpCallback)?bD.jsonpCallback():bD.jsonpCallback,bz=bb[bw],e=bD.url,by=bD.data,bv="$1"+bw+"$2";if(bD.jsonp!==false){e=e.replace(u,bv);if(bD.url===e){if(bx){by=by.replace(u,bv)}if(bD.data===by){e+=(/\?/.test(e)?"&":"?")+bD.jsonp+"="+bw}}}bD.url=e;bD.data=by;bb[bw]=function(bE){bB=[bE]};bC.always(function(){bb[bw]=bz;if(bB&&b.isFunction(bz)){bb[bw](bB[0])}});bD.converters["script json"]=function(){if(!bB){b.error(bw+" was not called")}return bB[0]};bD.dataTypes[0]="json";return"script"}});b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){b.globalEval(e);return e}}});b.ajaxPrefilter("script",function(e){if(e.cache===L){e.cache=false}if(e.crossDomain){e.type="GET";e.global=false}});b.ajaxTransport("script",function(bw){if(bw.crossDomain){var e,bv=av.head||av.getElementsByTagName("head")[0]||av.documentElement;return{send:function(bx,by){e=av.createElement("script");e.async="async";if(bw.scriptCharset){e.charset=bw.scriptCharset}e.src=bw.url;e.onload=e.onreadystatechange=function(bA,bz){if(bz||!e.readyState||/loaded|complete/.test(e.readyState)){e.onload=e.onreadystatechange=null;if(bv&&e.parentNode){bv.removeChild(e)}e=L;if(!bz){by(200,"success")}}};bv.insertBefore(e,bv.firstChild)},abort:function(){if(e){e.onload(0,1)}}}}});var B=bb.ActiveXObject?function(){for(var e in N){N[e](0,1)}}:false,y=0,N;function aL(){try{return new bb.XMLHttpRequest()}catch(bv){}}function aj(){try{return new bb.ActiveXObject("Microsoft.XMLHTTP")}catch(bv){}}b.ajaxSettings.xhr=bb.ActiveXObject?function(){return !this.isLocal&&aL()||aj()}:aL;(function(e){b.extend(b.support,{ajax:!!e,cors:!!e&&("withCredentials" in e)})})(b.ajaxSettings.xhr());if(b.support.ajax){b.ajaxTransport(function(e){if(!e.crossDomain||b.support.cors){var bv;return{send:function(bB,bw){var bA=e.xhr(),bz,by;if(e.username){bA.open(e.type,e.url,e.async,e.username,e.password)}else{bA.open(e.type,e.url,e.async)}if(e.xhrFields){for(by in e.xhrFields){bA[by]=e.xhrFields[by]}}if(e.mimeType&&bA.overrideMimeType){bA.overrideMimeType(e.mimeType)}if(!e.crossDomain&&!bB["X-Requested-With"]){bB["X-Requested-With"]="XMLHttpRequest"}try{for(by in bB){bA.setRequestHeader(by,bB[by])}}catch(bx){}bA.send((e.hasContent&&e.data)||null);bv=function(bK,bE){var bF,bD,bC,bI,bH;try{if(bv&&(bE||bA.readyState===4)){bv=L;if(bz){bA.onreadystatechange=b.noop;if(B){delete N[bz]}}if(bE){if(bA.readyState!==4){bA.abort()}}else{bF=bA.status;bC=bA.getAllResponseHeaders();bI={};bH=bA.responseXML;if(bH&&bH.documentElement){bI.xml=bH}bI.text=bA.responseText;try{bD=bA.statusText}catch(bJ){bD=""}if(!bF&&e.isLocal&&!e.crossDomain){bF=bI.text?200:404}else{if(bF===1223){bF=204}}}}}catch(bG){if(!bE){bw(-1,bG)}}if(bI){bw(bF,bD,bI,bC)}};if(!e.async||bA.readyState===4){bv()}else{bz=++y;if(B){if(!N){N={};b(bb).unload(B)}N[bz]=bv}bA.onreadystatechange=bv}},abort:function(){if(bv){bv(0,1)}}}}})}var Q={},a8,m,aB=/^(?:toggle|show|hide)$/,aT=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,a3,aH=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],a4;b.fn.extend({show:function(bx,bA,bz){var bw,by;if(bx||bx===0){return this.animate(a0("show",3),bx,bA,bz)}else{for(var bv=0,e=this.length;bv<e;bv++){bw=this[bv];if(bw.style){by=bw.style.display;if(!b._data(bw,"olddisplay")&&by==="none"){by=bw.style.display=""}if(by===""&&b.css(bw,"display")==="none"){b._data(bw,"olddisplay",x(bw.nodeName))}}}for(bv=0;bv<e;bv++){bw=this[bv];if(bw.style){by=bw.style.display;if(by===""||by==="none"){bw.style.display=b._data(bw,"olddisplay")||""}}}return this}},hide:function(bx,bA,bz){if(bx||bx===0){return this.animate(a0("hide",3),bx,bA,bz)}else{var bw,by,bv=0,e=this.length;for(;bv<e;bv++){bw=this[bv];if(bw.style){by=b.css(bw,"display");if(by!=="none"&&!b._data(bw,"olddisplay")){b._data(bw,"olddisplay",by)}}}for(bv=0;bv<e;bv++){if(this[bv].style){this[bv].style.display="none"}}return this}},_toggle:b.fn.toggle,toggle:function(bw,bv,bx){var e=typeof bw==="boolean";if(b.isFunction(bw)&&b.isFunction(bv)){this._toggle.apply(this,arguments)}else{if(bw==null||e){this.each(function(){var by=e?bw:b(this).is(":hidden");b(this)[by?"show":"hide"]()})}else{this.animate(a0("toggle",3),bw,bv,bx)}}return this},fadeTo:function(e,bx,bw,bv){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:bx},e,bw,bv)},animate:function(bz,bw,by,bx){var e=b.speed(bw,by,bx);if(b.isEmptyObject(bz)){return this.each(e.complete,[false])}bz=b.extend({},bz);function bv(){if(e.queue===false){b._mark(this)}var bE=b.extend({},e),bK=this.nodeType===1,bI=bK&&b(this).is(":hidden"),bB,bF,bD,bJ,bH,bC,bG,bL,bA;bE.animatedProperties={};for(bD in bz){bB=b.camelCase(bD);if(bD!==bB){bz[bB]=bz[bD];delete bz[bD]}bF=bz[bB];if(b.isArray(bF)){bE.animatedProperties[bB]=bF[1];bF=bz[bB]=bF[0]}else{bE.animatedProperties[bB]=bE.specialEasing&&bE.specialEasing[bB]||bE.easing||"swing"}if(bF==="hide"&&bI||bF==="show"&&!bI){return bE.complete.call(this)}if(bK&&(bB==="height"||bB==="width")){bE.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(b.css(this,"display")==="inline"&&b.css(this,"float")==="none"){if(!b.support.inlineBlockNeedsLayout||x(this.nodeName)==="inline"){this.style.display="inline-block"}else{this.style.zoom=1}}}}if(bE.overflow!=null){this.style.overflow="hidden"}for(bD in bz){bJ=new b.fx(this,bE,bD);bF=bz[bD];if(aB.test(bF)){bA=b._data(this,"toggle"+bD)||(bF==="toggle"?bI?"show":"hide":0);if(bA){b._data(this,"toggle"+bD,bA==="show"?"hide":"show");bJ[bA]()}else{bJ[bF]()}}else{bH=aT.exec(bF);bC=bJ.cur();if(bH){bG=parseFloat(bH[2]);bL=bH[3]||(b.cssNumber[bD]?"":"px");if(bL!=="px"){b.style(this,bD,(bG||1)+bL);bC=((bG||1)/bJ.cur())*bC;b.style(this,bD,bC+bL)}if(bH[1]){bG=((bH[1]==="-="?-1:1)*bG)+bC}bJ.custom(bC,bG,bL)}else{bJ.custom(bC,bF,"")}}}return true}return e.queue===false?this.each(bv):this.queue(e.queue,bv)},stop:function(bw,bv,e){if(typeof bw!=="string"){e=bv;bv=bw;bw=L}if(bv&&bw!==false){this.queue(bw||"fx",[])}return this.each(function(){var bx,by=false,bA=b.timers,bz=b._data(this);if(!e){b._unmark(true,this)}function bB(bE,bF,bD){var bC=bF[bD];b.removeData(bE,bD,true);bC.stop(e)}if(bw==null){for(bx in bz){if(bz[bx]&&bz[bx].stop&&bx.indexOf(".run")===bx.length-4){bB(this,bz,bx)}}}else{if(bz[bx=bw+".run"]&&bz[bx].stop){bB(this,bz,bx)}}for(bx=bA.length;bx--;){if(bA[bx].elem===this&&(bw==null||bA[bx].queue===bw)){if(e){bA[bx](true)}else{bA[bx].saveState()}by=true;bA.splice(bx,1)}}if(!(e&&by)){b.dequeue(this,bw)}})}});function bh(){setTimeout(at,0);return(a4=b.now())}function at(){a4=L}function a0(bv,e){var bw={};b.each(aH.concat.apply([],aH.slice(0,e)),function(){bw[this]=bv});return bw}b.each({slideDown:a0("show",1),slideUp:a0("hide",1),slideToggle:a0("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,bv){b.fn[e]=function(bw,by,bx){return this.animate(bv,bw,by,bx)}});b.extend({speed:function(bw,bx,bv){var e=bw&&typeof bw==="object"?b.extend({},bw):{complete:bv||!bv&&bx||b.isFunction(bw)&&bw,duration:bw,easing:bv&&bx||bx&&!b.isFunction(bx)&&bx};e.duration=b.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in b.fx.speeds?b.fx.speeds[e.duration]:b.fx.speeds._default;if(e.queue==null||e.queue===true){e.queue="fx"}e.old=e.complete;e.complete=function(by){if(b.isFunction(e.old)){e.old.call(this)}if(e.queue){b.dequeue(this,e.queue)}else{if(by!==false){b._unmark(this)}}};return e},easing:{linear:function(bw,bx,e,bv){return e+bv*bw},swing:function(bw,bx,e,bv){return((-Math.cos(bw*Math.PI)/2)+0.5)*bv+e}},timers:[],fx:function(bv,e,bw){this.options=e;this.elem=bv;this.prop=bw;e.orig=e.orig||{}}});b.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(b.fx.step[this.prop]||b.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var e,bv=b.css(this.elem,this.prop);return isNaN(e=parseFloat(bv))?!bv||bv==="auto"?0:bv:e},custom:function(bz,by,bx){var e=this,bw=b.fx;this.startTime=a4||bh();this.end=by;this.now=this.start=bz;this.pos=this.state=0;this.unit=bx||this.unit||(b.cssNumber[this.prop]?"":"px");function bv(bA){return e.step(bA)}bv.queue=this.options.queue;bv.elem=this.elem;bv.saveState=function(){if(e.options.hide&&b._data(e.elem,"fxshow"+e.prop)===L){b._data(e.elem,"fxshow"+e.prop,e.start)}};if(bv()&&b.timers.push(bv)&&!a3){a3=setInterval(bw.tick,bw.interval)}},show:function(){var e=b._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=e||b.style(this.elem,this.prop);this.options.show=true;if(e!==L){this.custom(this.cur(),e)}else{this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur())}b(this.elem).show()},hide:function(){this.options.orig[this.prop]=b._data(this.elem,"fxshow"+this.prop)||b.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(by){var bA,bB,bv,bx=a4||bh(),e=true,bz=this.elem,bw=this.options;if(by||bx>=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e<bv.length;e++){bw=bv[e];if(!bw()&&bv[e]===bw){bv.splice(e--,1)}}if(!bv.length){b.fx.stop()}},interval:13,stop:function(){clearInterval(a3);a3=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(e){b.style(e.elem,"opacity",e.now)},_default:function(e){if(e.elem.style&&e.elem.style[e.prop]!=null){e.elem.style[e.prop]=e.now+e.unit}else{e.elem[e.prop]=e.now}}}});b.each(["width","height"],function(e,bv){b.fx.step[bv]=function(bw){b.style(bw.elem,bv,Math.max(0,bw.now)+bw.unit)}});if(b.expr&&b.expr.filters){b.expr.filters.animated=function(e){return b.grep(b.timers,function(bv){return e===bv.elem}).length}}function x(bx){if(!Q[bx]){var e=av.body,bv=b("<"+bx+">").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b})}})(window);/*!
+ * jQuery UI 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI
+ */
+(function(a,d){a.ui=a.ui||{};if(a.ui.version){return}a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(e,f){return typeof e==="number"?this.each(function(){var g=this;setTimeout(function(){a(g).focus();if(f){f.call(g)}},e)}):this._focus.apply(this,arguments)},scrollParent:function(){var e;if((a.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){e=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(a.curCSS(this,"position",1))&&(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}else{e=this.parents().filter(function(){return(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!e.length?a(document):e},zIndex:function(h){if(h!==d){return this.css("zIndex",h)}if(this.length){var f=a(this[0]),e,g;while(f.length&&f[0]!==document){e=f.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){g=parseInt(f.css("zIndex"),10);if(!isNaN(g)&&g!==0){return g}}f=f.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});a.each(["Width","Height"],function(g,e){var f=e==="Width"?["Left","Right"]:["Top","Bottom"],h=e.toLowerCase(),k={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};function j(m,l,i,n){a.each(f,function(){l-=parseFloat(a.curCSS(m,"padding"+this,true))||0;if(i){l-=parseFloat(a.curCSS(m,"border"+this+"Width",true))||0}if(n){l-=parseFloat(a.curCSS(m,"margin"+this,true))||0}});return l}a.fn["inner"+e]=function(i){if(i===d){return k["inner"+e].call(this)}return this.each(function(){a(this).css(h,j(this,i)+"px")})};a.fn["outer"+e]=function(i,l){if(typeof i!=="number"){return k["outer"+e].call(this,i)}return this.each(function(){a(this).css(h,j(this,i,true,l)+"px")})}});function c(g,e){var j=g.nodeName.toLowerCase();if("area"===j){var i=g.parentNode,h=i.name,f;if(!g.href||!h||i.nodeName.toLowerCase()!=="map"){return false}f=a("img[usemap=#"+h+"]")[0];return !!f&&b(f)}return(/input|select|textarea|button|object/.test(j)?!g.disabled:"a"==j?g.href||e:e)&&b(g)}function b(e){return !a(e).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.extend(a.expr[":"],{data:function(g,f,e){return !!a.data(g,e[3])},focusable:function(e){return c(e,!isNaN(a.attr(e,"tabindex")))},tabbable:function(g){var e=a.attr(g,"tabindex"),f=isNaN(e);return(f||e>=0)&&c(g,!f)}});a(function(){var e=document.body,f=e.appendChild(f=document.createElement("div"));f.offsetHeight;a.extend(f.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});a.support.minHeight=f.offsetHeight===100;a.support.selectstart="onselectstart" in f;e.removeChild(f).style.display="none"});a.extend(a.ui,{plugin:{add:function(f,g,j){var h=a.ui[f].prototype;for(var e in j){h.plugins[e]=h.plugins[e]||[];h.plugins[e].push([g,j[e]])}},call:function(e,g,f){var j=e.plugins[g];if(!j||!e.element[0].parentNode){return}for(var h=0;h<j.length;h++){if(e.options[j[h][0]]){j[h][1].apply(e.element,f)}}}},contains:function(f,e){return document.compareDocumentPosition?f.compareDocumentPosition(e)&16:f!==e&&f.contains(e)},hasScroll:function(h,f){if(a(h).css("overflow")==="hidden"){return false}var e=(f&&f==="left")?"scrollLeft":"scrollTop",g=false;if(h[e]>0){return true}h[e]=1;g=(h[e]>0);h[e]=0;return g},isOverAxis:function(f,e,g){return(f>e)&&(f<(e+g))},isOver:function(j,f,i,h,e,g){return a.ui.isOverAxis(j,i,e)&&a.ui.isOverAxis(f,h,g)}})})(jQuery);/*!
+ * jQuery UI Widget 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Widget
+ */
+(function(b,d){if(b.cleanData){var c=b.cleanData;b.cleanData=function(f){for(var g=0,h;(h=f[g])!=null;g++){try{b(h).triggerHandler("remove")}catch(j){}}c(f)}}else{var a=b.fn.remove;b.fn.remove=function(e,f){return this.each(function(){if(!f){if(!e||b.filter(e,[this]).length){b("*",this).add([this]).each(function(){try{b(this).triggerHandler("remove")}catch(g){}})}}return a.call(b(this),e,f)})}}b.widget=function(f,h,e){var g=f.split(".")[0],j;f=f.split(".")[1];j=g+"-"+f;if(!e){e=h;h=b.Widget}b.expr[":"][j]=function(k){return !!b.data(k,f)};b[g]=b[g]||{};b[g][f]=function(k,l){if(arguments.length){this._createWidget(k,l)}};var i=new h();i.options=b.extend(true,{},i.options);b[g][f].prototype=b.extend(true,i,{namespace:g,widgetName:f,widgetEventPrefix:b[g][f].prototype.widgetEventPrefix||f,widgetBaseClass:j},e);b.widget.bridge(f,b[g][f])};b.widget.bridge=function(f,e){b.fn[f]=function(i){var g=typeof i==="string",h=Array.prototype.slice.call(arguments,1),j=this;i=!g&&h.length?b.extend.apply(null,[true,i].concat(h)):i;if(g&&i.charAt(0)==="_"){return j}if(g){this.each(function(){var k=b.data(this,f),l=k&&b.isFunction(k[i])?k[i].apply(k,h):k;if(l!==k&&l!==d){j=l;return false}})}else{this.each(function(){var k=b.data(this,f);if(k){k.option(i||{})._init()}else{b.data(this,f,new e(i,this))}})}return j}};b.Widget=function(e,f){if(arguments.length){this._createWidget(e,f)}};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(f,g){b.data(g,this.widgetName,this);this.element=b(g);this.options=b.extend(true,{},this.options,this._getCreateOptions(),f);var e=this;this.element.bind("remove."+this.widgetName,function(){e.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(f,g){var e=f;if(arguments.length===0){return b.extend({},this.options)}if(typeof f==="string"){if(g===d){return this.options[f]}e={};e[f]=g}this._setOptions(e);return this},_setOptions:function(f){var e=this;b.each(f,function(g,h){e._setOption(g,h)});return this},_setOption:function(e,f){this.options[e]=f;if(e==="disabled"){this.widget()[f?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",f)}return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(e,f,g){var j,i,h=this.options[e];g=g||{};f=b.Event(f);f.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase();f.target=this.element[0];i=f.originalEvent;if(i){for(j in i){if(!(j in f)){f[j]=i[j]}}}this.element.trigger(f,g);return !(b.isFunction(h)&&h.call(this.element[0],f,g)===false||f.isDefaultPrevented())}}})(jQuery);/*!
+ * jQuery UI Mouse 1.8.18
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * Depends:
+ * jquery.ui.widget.js
+ */
+(function(b,c){var a=false;b(document).mouseup(function(d){a=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var d=this;this.element.bind("mousedown."+this.widgetName,function(e){return d._mouseDown(e)}).bind("click."+this.widgetName,function(e){if(true===b.data(e.target,d.widgetName+".preventClickEvent")){b.removeData(e.target,d.widgetName+".preventClickEvent");e.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(f){if(a){return}(this._mouseStarted&&this._mouseUp(f));this._mouseDownEvent=f;var e=this,g=(f.which==1),d=(typeof this.options.cancel=="string"&&f.target.nodeName?b(f.target).closest(this.options.cancel).length:false);if(!g||d||!this._mouseCapture(f)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(f)&&this._mouseDelayMet(f)){this._mouseStarted=(this._mouseStart(f)!==false);if(!this._mouseStarted){f.preventDefault();return true}}if(true===b.data(f.target,this.widgetName+".preventClickEvent")){b.removeData(f.target,this.widgetName+".preventClickEvent")}this._mouseMoveDelegate=function(h){return e._mouseMove(h)};this._mouseUpDelegate=function(h){return e._mouseUp(h)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);f.preventDefault();a=true;return true},_mouseMove:function(d){if(b.browser.msie&&!(document.documentMode>=9)&&!d.button){return this._mouseUp(d)}if(this._mouseStarted){this._mouseDrag(d);return d.preventDefault()}if(this._mouseDistanceMet(d)&&this._mouseDelayMet(d)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,d)!==false);(this._mouseStarted?this._mouseDrag(d):this._mouseUp(d))}return !this._mouseStarted},_mouseUp:function(d){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;if(d.target==this._mouseDownEvent.target){b.data(d.target,this.widgetName+".preventClickEvent",true)}this._mouseStop(d)}return false},_mouseDistanceMet:function(d){return(Math.max(Math.abs(this._mouseDownEvent.pageX-d.pageX),Math.abs(this._mouseDownEvent.pageY-d.pageY))>=this.options.distance)},_mouseDelayMet:function(d){return this.mouseDelayMet},_mouseStart:function(d){},_mouseDrag:function(d){},_mouseStop:function(d){},_mouseCapture:function(d){return true}})})(jQuery);(function(c,d){c.widget("ui.resizable",c.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000},_create:function(){var f=this,k=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(k.aspectRatio),aspectRatio:k.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:k.helper||k.ghost||k.animate?k.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){this.element.wrap(c('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=k.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var l=this.handles.split(",");this.handles={};for(var g=0;g<l.length;g++){var j=c.trim(l[g]),e="ui-resizable-"+j;var h=c('<div class="ui-resizable-handle '+e+'"></div>');if(/sw|se|ne|nw/.test(j)){h.css({zIndex:++k.zIndex})}if("se"==j){h.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[j]=".ui-resizable-"+j;this.element.append(h)}}this._renderAxis=function(q){q=q||this.element;for(var n in this.handles){if(this.handles[n].constructor==String){this.handles[n]=c(this.handles[n],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var o=c(this.handles[n],this.element),p=0;p=/sw|ne|nw|se|n|s/.test(n)?o.outerHeight():o.outerWidth();var m=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");q.css(m,p);this._proportionallyResize()}if(!c(this.handles[n]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!f.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}f.axis=i&&i[1]?i[1]:"se"}});if(k.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){if(k.disabled){return}c(this).removeClass("ui-resizable-autohide");f._handles.show()},function(){if(k.disabled){return}if(!f.resizing){c(this).addClass("ui-resizable-autohide");f._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var e=function(g){c(g).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){e(this.element);var f=this.element;f.after(this.originalElement.css({position:f.css("position"),width:f.outerWidth(),height:f.outerHeight(),top:f.css("top"),left:f.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);e(this.originalElement);return this},_mouseCapture:function(f){var g=false;for(var e in this.handles){if(c(this.handles[e])[0]==f.target){g=true}}return !this.options.disabled&&g},_mouseStart:function(g){var j=this.options,f=this.element.position(),e=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(e.is(".ui-draggable")||(/absolute/).test(e.css("position"))){e.css({position:"absolute",top:f.top,left:f.left})}this._renderProxy();var k=b(this.helper.css("left")),h=b(this.helper.css("top"));if(j.containment){k+=c(j.containment).scrollLeft()||0;h+=c(j.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:k,top:h};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:k,top:h};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:g.pageX,top:g.pageY};this.aspectRatio=(typeof j.aspectRatio=="number")?j.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var i=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",i=="auto"?this.axis+"-resize":i);e.addClass("ui-resizable-resizing");this._propagate("start",g);return true},_mouseDrag:function(e){var h=this.helper,g=this.options,m={},q=this,j=this.originalMousePosition,n=this.axis;var r=(e.pageX-j.left)||0,p=(e.pageY-j.top)||0;var i=this._change[n];if(!i){return false}var l=i.apply(this,[e,r,p]),k=c.browser.msie&&c.browser.version<7,f=this.sizeDiff;this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey){l=this._updateRatio(l,e)}l=this._respectSize(l,e);this._propagate("resize",e);h.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(l);this._trigger("resize",e,this.ui());return false},_mouseStop:function(h){this.resizing=false;var i=this.options,m=this;if(this._helper){var g=this._proportionallyResizeElements,e=g.length&&(/textarea/i).test(g[0].nodeName),f=e&&c.ui.hasScroll(g[0],"left")?0:m.sizeDiff.height,k=e?0:m.sizeDiff.width;var n={width:(m.helper.width()-k),height:(m.helper.height()-f)},j=(parseInt(m.element.css("left"),10)+(m.position.left-m.originalPosition.left))||null,l=(parseInt(m.element.css("top"),10)+(m.position.top-m.originalPosition.top))||null;if(!i.animate){this.element.css(c.extend(n,{top:l,left:j}))}m.helper.height(m.size.height);m.helper.width(m.size.width);if(this._helper&&!i.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",h);if(this._helper){this.helper.remove()}return false},_updateVirtualBoundaries:function(g){var j=this.options,i,h,f,k,e;e={minWidth:a(j.minWidth)?j.minWidth:0,maxWidth:a(j.maxWidth)?j.maxWidth:Infinity,minHeight:a(j.minHeight)?j.minHeight:0,maxHeight:a(j.maxHeight)?j.maxHeight:Infinity};if(this._aspectRatio||g){i=e.minHeight*this.aspectRatio;f=e.minWidth/this.aspectRatio;h=e.maxHeight*this.aspectRatio;k=e.maxWidth/this.aspectRatio;if(i>e.minWidth){e.minWidth=i}if(f>e.minHeight){e.minHeight=f}if(h<e.maxWidth){e.maxWidth=h}if(k<e.maxHeight){e.maxHeight=k}}this._vBoundaries=e},_updateCache:function(e){var f=this.options;this.offset=this.helper.offset();if(a(e.left)){this.position.left=e.left}if(a(e.top)){this.position.top=e.top}if(a(e.height)){this.size.height=e.height}if(a(e.width)){this.size.width=e.width}},_updateRatio:function(h,g){var i=this.options,j=this.position,f=this.size,e=this.axis;if(a(h.height)){h.width=(h.height*this.aspectRatio)}else{if(a(h.width)){h.height=(h.width/this.aspectRatio)}}if(e=="sw"){h.left=j.left+(f.width-h.width);h.top=null}if(e=="nw"){h.top=j.top+(f.height-h.height);h.left=j.left+(f.width-h.width)}return h},_respectSize:function(l,g){var j=this.helper,i=this._vBoundaries,r=this._aspectRatio||g.shiftKey,q=this.axis,t=a(l.width)&&i.maxWidth&&(i.maxWidth<l.width),m=a(l.height)&&i.maxHeight&&(i.maxHeight<l.height),h=a(l.width)&&i.minWidth&&(i.minWidth>l.width),s=a(l.height)&&i.minHeight&&(i.minHeight>l.height);if(h){l.width=i.minWidth}if(s){l.height=i.minHeight}if(t){l.width=i.maxWidth}if(m){l.height=i.maxHeight}var f=this.originalPosition.left+this.originalSize.width,p=this.position.top+this.size.height;var k=/sw|nw|w/.test(q),e=/nw|ne|n/.test(q);if(h&&k){l.left=f-i.minWidth}if(t&&k){l.left=f-i.maxWidth}if(s&&e){l.top=p-i.minHeight}if(m&&e){l.top=p-i.maxHeight}var n=!l.width&&!l.height;if(n&&!l.left&&l.top){l.top=null}else{if(n&&!l.top&&l.left){l.left=null}}return l},_proportionallyResize:function(){var k=this.options;if(!this._proportionallyResizeElements.length){return}var g=this.helper||this.element;for(var f=0;f<this._proportionallyResizeElements.length;f++){var h=this._proportionallyResizeElements[f];if(!this.borderDif){var e=[h.css("borderTopWidth"),h.css("borderRightWidth"),h.css("borderBottomWidth"),h.css("borderLeftWidth")],j=[h.css("paddingTop"),h.css("paddingRight"),h.css("paddingBottom"),h.css("paddingLeft")];this.borderDif=c.map(e,function(l,n){var m=parseInt(l,10)||0,o=parseInt(j[n],10)||0;return m+o})}if(c.browser.msie&&!(!(c(g).is(":hidden")||c(g).parents(":hidden").length))){continue}h.css({height:(g.height()-this.borderDif[0]-this.borderDif[2])||0,width:(g.width()-this.borderDif[1]-this.borderDif[3])||0})}},_renderProxy:function(){var f=this.element,i=this.options;this.elementOffset=f.offset();if(this._helper){this.helper=this.helper||c('<div style="overflow:hidden;"></div>');var e=c.browser.msie&&c.browser.version<7,g=(e?1:0),h=(e?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+h,height:this.element.outerHeight()+h,position:"absolute",left:this.elementOffset.left-g+"px",top:this.elementOffset.top-g+"px",zIndex:++i.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(g,f,e){return{width:this.originalSize.width+f}},w:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{left:i.left+f,width:g.width-f}},n:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{top:i.top+e,height:g.height-e}},s:function(g,f,e){return{height:this.originalSize.height+e}},se:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},sw:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[g,f,e]))},ne:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},nw:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[g,f,e]))}},_propagate:function(f,e){c.ui.plugin.call(this,f,[e,this.ui()]);(f!="resize"&&this._trigger(f,e,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});c.extend(c.ui.resizable,{version:"1.8.18"});c.ui.plugin.add("resizable","alsoResize",{start:function(f,g){var e=c(this).data("resizable"),i=e.options;var h=function(j){c(j).each(function(){var k=c(this);k.data("resizable-alsoresize",{width:parseInt(k.width(),10),height:parseInt(k.height(),10),left:parseInt(k.css("left"),10),top:parseInt(k.css("top"),10)})})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.parentNode){if(i.alsoResize.length){i.alsoResize=i.alsoResize[0];h(i.alsoResize)}else{c.each(i.alsoResize,function(j){h(j)})}}else{h(i.alsoResize)}},resize:function(g,i){var f=c(this).data("resizable"),j=f.options,h=f.originalSize,l=f.originalPosition;var k={height:(f.size.height-h.height)||0,width:(f.size.width-h.width)||0,top:(f.position.top-l.top)||0,left:(f.position.left-l.left)||0},e=function(m,n){c(m).each(function(){var q=c(this),r=c(this).data("resizable-alsoresize"),p={},o=n&&n.length?n:q.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];c.each(o,function(s,u){var t=(r[u]||0)+(k[u]||0);if(t&&t>=0){p[u]=t||null}});q.css(p)})};if(typeof(j.alsoResize)=="object"&&!j.alsoResize.nodeType){c.each(j.alsoResize,function(m,n){e(m,n)})}else{e(j.alsoResize)}},stop:function(e,f){c(this).removeData("resizable-alsoresize")}});c.ui.plugin.add("resizable","animate",{stop:function(i,n){var p=c(this).data("resizable"),j=p.options;var h=p._proportionallyResizeElements,e=h.length&&(/textarea/i).test(h[0].nodeName),f=e&&c.ui.hasScroll(h[0],"left")?0:p.sizeDiff.height,l=e?0:p.sizeDiff.width;var g={width:(p.size.width-l),height:(p.size.height-f)},k=(parseInt(p.element.css("left"),10)+(p.position.left-p.originalPosition.left))||null,m=(parseInt(p.element.css("top"),10)+(p.position.top-p.originalPosition.top))||null;p.element.animate(c.extend(g,m&&k?{top:m,left:k}:{}),{duration:j.animateDuration,easing:j.animateEasing,step:function(){var o={width:parseInt(p.element.css("width"),10),height:parseInt(p.element.css("height"),10),top:parseInt(p.element.css("top"),10),left:parseInt(p.element.css("left"),10)};if(h&&h.length){c(h[0]).css({width:o.width,height:o.height})}p._updateCache(o);p._propagate("resize",i)}})}});c.ui.plugin.add("resizable","containment",{start:function(f,r){var t=c(this).data("resizable"),j=t.options,l=t.element;var g=j.containment,k=(g instanceof c)?g.get(0):(/parent/.test(g))?l.parent().get(0):g;if(!k){return}t.containerElement=c(k);if(/document/.test(g)||g==document){t.containerOffset={left:0,top:0};t.containerPosition={left:0,top:0};t.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var n=c(k),i=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){i[p]=b(n.css("padding"+o))});t.containerOffset=n.offset();t.containerPosition=n.position();t.containerSize={height:(n.innerHeight()-i[3]),width:(n.innerWidth()-i[1])};var q=t.containerOffset,e=t.containerSize.height,m=t.containerSize.width,h=(c.ui.hasScroll(k,"left")?k.scrollWidth:m),s=(c.ui.hasScroll(k)?k.scrollHeight:e);t.parentData={element:k,left:q.left,top:q.top,width:h,height:s}}},resize:function(g,q){var t=c(this).data("resizable"),i=t.options,f=t.containerSize,p=t.containerOffset,m=t.size,n=t.position,r=t._aspectRatio||g.shiftKey,e={top:0,left:0},h=t.containerElement;if(h[0]!=document&&(/static/).test(h.css("position"))){e=p}if(n.left<(t._helper?p.left:0)){t.size.width=t.size.width+(t._helper?(t.position.left-p.left):(t.position.left-e.left));if(r){t.size.height=t.size.width/i.aspectRatio}t.position.left=i.helper?p.left:0}if(n.top<(t._helper?p.top:0)){t.size.height=t.size.height+(t._helper?(t.position.top-p.top):t.position.top);if(r){t.size.width=t.size.height*i.aspectRatio}t.position.top=t._helper?p.top:0}t.offset.left=t.parentData.left+t.position.left;t.offset.top=t.parentData.top+t.position.top;var l=Math.abs((t._helper?t.offset.left-e.left:(t.offset.left-e.left))+t.sizeDiff.width),s=Math.abs((t._helper?t.offset.top-e.top:(t.offset.top-p.top))+t.sizeDiff.height);var k=t.containerElement.get(0)==t.element.parent().get(0),j=/relative|absolute/.test(t.containerElement.css("position"));if(k&&j){l-=t.parentData.left}if(l+t.size.width>=t.parentData.width){t.size.width=t.parentData.width-l;if(r){t.size.height=t.size.width/t.aspectRatio}}if(s+t.size.height>=t.parentData.height){t.size.height=t.parentData.height-s;if(r){t.size.width=t.size.height*t.aspectRatio}}},stop:function(f,n){var q=c(this).data("resizable"),g=q.options,l=q.position,m=q.containerOffset,e=q.containerPosition,i=q.containerElement;var j=c(q.helper),r=j.offset(),p=j.outerWidth()-q.sizeDiff.width,k=j.outerHeight()-q.sizeDiff.height;if(q._helper&&!g.animate&&(/relative/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}if(q._helper&&!g.animate&&(/static/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}}});c.ui.plugin.add("resizable","ghost",{start:function(g,h){var e=c(this).data("resizable"),i=e.options,f=e.size;e.ghost=e.originalElement.clone();e.ghost.css({opacity:0.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:"");e.ghost.appendTo(e.helper)},resize:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost){e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})}},stop:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost&&e.helper){e.helper.get(0).removeChild(e.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(e,m){var p=c(this).data("resizable"),h=p.options,k=p.size,i=p.originalSize,j=p.originalPosition,n=p.axis,l=h._aspectRatio||e.shiftKey;h.grid=typeof h.grid=="number"?[h.grid,h.grid]:h.grid;var g=Math.round((k.width-i.width)/(h.grid[0]||1))*(h.grid[0]||1),f=Math.round((k.height-i.height)/(h.grid[1]||1))*(h.grid[1]||1);if(/^(se|s|e)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f}else{if(/^(ne)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f}else{if(/^(sw)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.left=j.left-g}else{p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f;p.position.left=j.left-g}}}}});var b=function(e){return parseInt(e,10)||0};var a=function(e){return !isNaN(parseInt(e,10))}})(jQuery);/*!
+ * jQuery hashchange event - v1.3 - 7/21/2010
+ * http://benalman.com/projects/jquery-hashchange-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){r||l(a());n()}).attr("src",r||"javascript:0").insertAfter("body")[0].contentWindow;h.onpropertychange=function(){try{if(event.propertyName==="title"){q.document.title=h.title}}catch(s){}}}};j.stop=k;o=function(){return a(q.location.href)};l=function(v,s){var u=q.document,t=$.fn[c].domain;if(v!==s){u.title=h.title;u.open();t&&u.write('<script>document.domain="'+t+'"<\/script>');u.close();q.location.hash=v}}})();return j})()})(jQuery,this);(function(c){var a=c.scrollTo=function(f,e,d){c(window).scrollTo(f,e,d)};a.defaults={axis:"xy",duration:parseFloat(c.fn.jquery)>=1.3?0:1};a.window=function(d){return c(window)._scrollable()};c.fn._scrollable=function(){return this.map(function(){var e=this,d=!e.nodeName||c.inArray(e.nodeName.toLowerCase(),["iframe","#document","html","body"])!=-1;if(!d){return e}var f=(e.contentWindow||e).document||e.ownerDocument||e;return c.browser.safari||f.compatMode=="BackCompat"?f.body:f.documentElement})};c.fn.scrollTo=function(f,e,d){if(typeof e=="object"){d=e;e=0}if(typeof d=="function"){d={onAfter:d}}if(f=="max"){f=9000000000}d=c.extend({},a.defaults,d);e=e||d.speed||d.duration;d.queue=d.queue&&d.axis.length>1;if(d.queue){e/=2}d.offset=b(d.offset);d.over=b(d.over);return this._scrollable().each(function(){var l=this,j=c(l),k=f,i,g={},m=j.is("html,body");switch(typeof k){case"number":case"string":if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(k)){k=b(k);break}k=c(k,this);case"object":if(k.is||k.style){i=(k=c(k)).offset()}}c.each(d.axis.split(""),function(q,r){var s=r=="x"?"Left":"Top",u=s.toLowerCase(),p="scroll"+s,o=l[p],n=a.max(l,r);if(i){g[p]=i[u]+(m?0:o-j.offset()[u]);if(d.margin){g[p]-=parseInt(k.css("margin"+s))||0;g[p]-=parseInt(k.css("border"+s+"Width"))||0}g[p]+=d.offset[u]||0;if(d.over[u]){g[p]+=k[r=="x"?"width":"height"]()*d.over[u]}}else{var t=k[u];g[p]=t.slice&&t.slice(-1)=="%"?parseFloat(t)/100*n:t}if(/^\d+$/.test(g[p])){g[p]=g[p]<=0?0:Math.min(g[p],n)}if(!q&&d.queue){if(o!=g[p]){h(d.onAfterFirst)}delete g[p]}});h(d.onAfter);function h(n){j.animate(g,e,d.easing,n&&function(){n.call(this,f,d)})}}).end()};a.max=function(j,i){var h=i=="x"?"Width":"Height",e="scroll"+h;if(!c(j).is("html,body")){return j[e]-c(j)[h.toLowerCase()]()}var g="client"+h,f=j.ownerDocument.documentElement,d=j.ownerDocument.body;return Math.max(f[e],d[e])-Math.min(f[g],d[g])};function b(d){return typeof d=="object"?d:{top:d,left:d}}})(jQuery);/*!
+ PowerTip - v1.2.0 - 2013-04-03
+ http://stevenbenner.github.com/jquery-powertip/
+ Copyright (c) 2013 Steven Benner (http://stevenbenner.com/).
+ Released under MIT license.
+ https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt
+*/
+(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(jQuery)}}(function(k){var A=k(document),s=k(window),w=k("body");var n="displayController",e="hasActiveHover",d="forcedOpen",u="hasMouseMove",f="mouseOnToPopup",g="originalTitle",y="powertip",o="powertipjq",l="powertiptarget",E=180/Math.PI;var c={isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var p={none:0,top:1,bottom:2,left:4,right:8};k.fn.powerTip=function(F,N){if(!this.length){return this}if(k.type(F)==="string"&&k.powerTip[F]){return k.powerTip[F].call(this,this,N)}var O=k.extend({},k.fn.powerTip.defaults,F),G=new x(O);h();this.each(function M(){var R=k(this),Q=R.data(y),P=R.data(o),T=R.data(l),S;if(R.data(n)){k.powerTip.destroy(R)}S=R.attr("title");if(!Q&&!T&&!P&&S){R.data(y,S);R.data(g,S);R.removeAttr("title")}R.data(n,new t(R,O,G))});if(!O.manual){this.on({"mouseenter.powertip":function J(P){k.powerTip.show(this,P)},"mouseleave.powertip":function L(){k.powerTip.hide(this)},"focus.powertip":function K(){k.powerTip.show(this)},"blur.powertip":function H(){k.powerTip.hide(this,true)},"keydown.powertip":function I(P){if(P.keyCode===27){k.powerTip.hide(this,true)}}})}return this};k.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false};k.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};k.powerTip={show:function z(F,G){if(G){i(G);c.previousX=G.pageX;c.previousY=G.pageY;k(F).data(n).show()}else{k(F).first().data(n).show(true,true)}return F},reposition:function r(F){k(F).first().data(n).resetPosition();return F},hide:function D(G,F){if(G){k(G).first().data(n).hide(F)}else{if(c.activeHover){c.activeHover.data(n).hide(true)}}return G},destroy:function C(G){k(G).off(".powertip").each(function F(){var I=k(this),H=[g,n,e,d];if(I.data(g)){I.attr("title",I.data(g));H.push(y)}I.removeData(H)});return G}};k.powerTip.showTip=k.powerTip.show;k.powerTip.closeTip=k.powerTip.hide;function b(){var F=this;F.top="auto";F.left="auto";F.right="auto";F.bottom="auto";F.set=function(H,G){if(k.isNumeric(G)){F[H]=Math.round(G)}}}function t(K,N,F){var J=null;function L(P,Q){M();if(!K.data(e)){if(!P){c.tipOpenImminent=true;J=setTimeout(function O(){J=null;I()},N.intentPollInterval)}else{if(Q){K.data(d,true)}F.showTip(K)}}}function G(P){M();c.tipOpenImminent=false;if(K.data(e)){K.data(d,false);if(!P){c.delayInProgress=true;J=setTimeout(function O(){J=null;F.hideTip(K);c.delayInProgress=false},N.closeDelay)}else{F.hideTip(K)}}}function I(){var Q=Math.abs(c.previousX-c.currentX),O=Math.abs(c.previousY-c.currentY),P=Q+O;if(P<N.intentSensitivity){F.showTip(K)}else{c.previousX=c.currentX;c.previousY=c.currentY;L()}}function M(){J=clearTimeout(J);c.delayInProgress=false}function H(){F.resetPosition(K)}this.show=L;this.hide=G;this.cancel=M;this.resetPosition=H}function j(){function G(M,L,J,O,P){var K=L.split("-")[0],N=new b(),I;if(q(M)){I=H(M,K)}else{I=F(M,K)}switch(L){case"n":N.set("left",I.left-(J/2));N.set("bottom",c.windowHeight-I.top+P);break;case"e":N.set("left",I.left+P);N.set("top",I.top-(O/2));break;case"s":N.set("left",I.left-(J/2));N.set("top",I.top+P);break;case"w":N.set("top",I.top-(O/2));N.set("right",c.windowWidth-I.left+P);break;case"nw":N.set("bottom",c.windowHeight-I.top+P);N.set("right",c.windowWidth-I.left-20);break;case"nw-alt":N.set("left",I.left);N.set("bottom",c.windowHeight-I.top+P);break;case"ne":N.set("left",I.left-20);N.set("bottom",c.windowHeight-I.top+P);break;case"ne-alt":N.set("bottom",c.windowHeight-I.top+P);N.set("right",c.windowWidth-I.left);break;case"sw":N.set("top",I.top+P);N.set("right",c.windowWidth-I.left-20);break;case"sw-alt":N.set("left",I.left);N.set("top",I.top+P);break;case"se":N.set("left",I.left-20);N.set("top",I.top+P);break;case"se-alt":N.set("top",I.top+P);N.set("right",c.windowWidth-I.left);break}return N}function F(K,J){var O=K.offset(),N=K.outerWidth(),I=K.outerHeight(),M,L;switch(J){case"n":M=O.left+N/2;L=O.top;break;case"e":M=O.left+N;L=O.top+I/2;break;case"s":M=O.left+N/2;L=O.top+I;break;case"w":M=O.left;L=O.top+I/2;break;case"nw":M=O.left;L=O.top;break;case"ne":M=O.left+N;L=O.top;break;case"sw":M=O.left;L=O.top+I;break;case"se":M=O.left+N;L=O.top+I;break}return{top:L,left:M}}function H(O,K){var S=O.closest("svg")[0],N=O[0],W=S.createSVGPoint(),L=N.getBBox(),V=N.getScreenCTM(),M=L.width/2,Q=L.height/2,P=[],I=["nw","n","ne","e","se","s","sw","w"],U,X,R,T;function J(){P.push(W.matrixTransform(V))}W.x=L.x;W.y=L.y;J();W.x+=M;J();W.x+=M;J();W.y+=Q;J();W.y+=Q;J();W.x-=M;J();W.x-=M;J();W.y-=Q;J();if(P[0].y!==P[1].y||P[0].x!==P[7].x){X=Math.atan2(V.b,V.a)*E;R=Math.ceil(((X%360)-22.5)/45);if(R<1){R+=8}while(R--){I.push(I.shift())}}for(T=0;T<P.length;T++){if(I[T]===K){U=P[T];break}}return{top:U.y+c.scrollTop,left:U.x+c.scrollLeft}}this.compute=G}function x(Q){var P=new j(),O=k("#"+Q.popupId);if(O.length===0){O=k("<div/>",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.top<G||Math.abs(M.bottom-c.windowHeight)-K<G){H|=p.top}if(M.top+K>I||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.left<J||M.right+L>F){H|=p.left}if(M.left+L>F||M.right<J){H|=p.right}return H}function a(G){var F=0;while(G){G&=G-1;F++}return F}}));/*!
+ * jQuery UI Touch Punch 0.2.3
+ *
+ * Copyright 2011–2014, Dave Furfero
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ * Depends:
+ * jquery.ui.widget.js
+ * jquery.ui.mouse.js
+ */
+(function(b){b.support.touch="ontouchend" in document;if(!b.support.touch){return}var d=b.ui.mouse.prototype,f=d._mouseInit,c=d._mouseDestroy,a;function e(h,i){if(h.originalEvent.touches.length>1){return}h.preventDefault();var j=h.originalEvent.changedTouches[0],g=document.createEvent("MouseEvents");g.initMouseEvent(i,true,true,window,1,j.screenX,j.screenY,j.clientX,j.clientY,false,false,false,false,0,null);h.target.dispatchEvent(g)}d._touchStart=function(h){var g=this;if(a||!g._mouseCapture(h.originalEvent.changedTouches[0])){return}a=true;g._touchMoved=false;e(h,"mouseover");e(h,"mousemove");e(h,"mousedown")};d._touchMove=function(g){if(!a){return}this._touchMoved=true;e(g,"mousemove")};d._touchEnd=function(g){if(!a){return}e(g,"mouseup");e(g,"mouseout");if(!this._touchMoved){e(g,"click")}a=false};d._mouseInit=function(){var g=this;g.element.bind({touchstart:b.proxy(g,"_touchStart"),touchmove:b.proxy(g,"_touchMove"),touchend:b.proxy(g,"_touchEnd")});f.call(g)};d._mouseDestroy=function(){var g=this;g.element.unbind({touchstart:b.proxy(g,"_touchStart"),touchmove:b.proxy(g,"_touchMove"),touchend:b.proxy(g,"_touchEnd")});c.call(g)}})(jQuery);/*!
+ * SmartMenus jQuery Plugin - v1.0.0 - January 27, 2016
+ * http://www.smartmenus.org/
+ *
+ * Copyright Vasil Dinkov, Vadikom Web Ltd.
+ * http://vadikom.com
+ *
+ * Licensed MIT
+ */
+(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{if(typeof module==="object"&&typeof module.exports==="object"){module.exports=a(require("jquery"))}else{a(jQuery)}}}(function(a){var b=[],e=!!window.createPopup,f=false,d="ontouchstart" in window,h=false,g=window.requestAnimationFrame||function(l){return setTimeout(l,1000/60)},c=window.cancelAnimationFrame||function(l){clearTimeout(l)};function k(m){var n=".smartmenus_mouse";if(!h&&!m){var o=true,l=null;a(document).bind(i([["mousemove",function(s){var t={x:s.pageX,y:s.pageY,timeStamp:new Date().getTime()};if(l){var q=Math.abs(l.x-t.x),p=Math.abs(l.y-t.y);if((q>0||p>0)&&q<=2&&p<=2&&t.timeStamp-l.timeStamp<=300){f=true;if(o){var r=a(s.target).closest("a");if(r.is("a")){a.each(b,function(){if(a.contains(this.$root[0],r[0])){this.itemEnter({currentTarget:r[0]});return false}})}o=false}}}l=t}],[d?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut",function(p){if(j(p.originalEvent)){f=false}}]],n));h=true}else{if(h&&m){a(document).unbind(n);h=false}}}function j(l){return !/^(4|mouse)$/.test(l.pointerType)}function i(l,n){if(!n){n=""}var m={};a.each(l,function(o,p){m[p[0].split(" ").join(n+" ")+n]=p[1]});return m}a.SmartMenus=function(m,l){this.$root=a(m);this.opts=l;this.rootId="";this.accessIdPrefix="";this.$subArrow=null;this.activatedItems=[];this.visibleSubMenus=[];this.showTimeout=0;this.hideTimeout=0;this.scrollTimeout=0;this.clickActivated=false;this.focusActivated=false;this.zIndexInc=0;this.idInc=0;this.$firstLink=null;this.$firstSub=null;this.disabled=false;this.$disableOverlay=null;this.$touchScrollingSub=null;this.cssTransforms3d="perspective" in m.style||"webkitPerspective" in m.style;this.wasCollapsible=false;this.init()};a.extend(a.SmartMenus,{hideAll:function(){a.each(b,function(){this.menuHideAll()})},destroy:function(){while(b.length){b[0].destroy()}k(true)},prototype:{init:function(n){var l=this;if(!n){b.push(this);this.rootId=(new Date().getTime()+Math.random()+"").replace(/\D/g,"");this.accessIdPrefix="sm-"+this.rootId+"-";if(this.$root.hasClass("sm-rtl")){this.opts.rightToLeftSubMenus=true}var r=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).bind(i([["mouseover focusin",a.proxy(this.rootOver,this)],["mouseout focusout",a.proxy(this.rootOut,this)],["keydown",a.proxy(this.rootKeyDown,this)]],r)).delegate("a",i([["mouseenter",a.proxy(this.itemEnter,this)],["mouseleave",a.proxy(this.itemLeave,this)],["mousedown",a.proxy(this.itemDown,this)],["focus",a.proxy(this.itemFocus,this)],["blur",a.proxy(this.itemBlur,this)],["click",a.proxy(this.itemClick,this)]],r));r+=this.rootId;if(this.opts.hideOnClick){a(document).bind(i([["touchstart",a.proxy(this.docTouchStart,this)],["touchmove",a.proxy(this.docTouchMove,this)],["touchend",a.proxy(this.docTouchEnd,this)],["click",a.proxy(this.docClick,this)]],r))}a(window).bind(i([["resize orientationchange",a.proxy(this.winResize,this)]],r));if(this.opts.subIndicators){this.$subArrow=a("<span/>").addClass("sub-arrow");if(this.opts.subIndicatorsText){this.$subArrow.html(this.opts.subIndicatorsText)}}k()}this.$firstSub=this.$root.find("ul").each(function(){l.menuInit(a(this))}).eq(0);this.$firstLink=this.$root.find("a").eq(0);if(this.opts.markCurrentItem){var p=/(index|default)\.[^#\?\/]*/i,m=/#.*/,q=window.location.href.replace(p,""),o=q.replace(m,"");this.$root.find("a").each(function(){var s=this.href.replace(p,""),t=a(this);if(s==q||s==o){t.addClass("current");if(l.opts.markCurrentTree){t.parentsUntil("[data-smartmenus-id]","ul").each(function(){a(this).dataSM("parent-a").addClass("current")})}}})}this.wasCollapsible=this.isCollapsible()},destroy:function(m){if(!m){var n=".smartmenus";this.$root.removeData("smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").unbind(n).undelegate(n);n+=this.rootId;a(document).unbind(n);a(window).unbind(n);if(this.opts.subIndicators){this.$subArrow=null}}this.menuHideAll();var l=this;this.$root.find("ul").each(function(){var o=a(this);if(o.dataSM("scroll-arrows")){o.dataSM("scroll-arrows").remove()}if(o.dataSM("shown-before")){if(l.opts.subMenusMinWidth||l.opts.subMenusMaxWidth){o.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap")}if(o.dataSM("scroll-arrows")){o.dataSM("scroll-arrows").remove()}o.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})}if((o.attr("id")||"").indexOf(l.accessIdPrefix)==0){o.removeAttr("id")}}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("ie-shim").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded");this.$root.find("a.has-submenu").each(function(){var o=a(this);if(o.attr("id").indexOf(l.accessIdPrefix)==0){o.removeAttr("id")}}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub");if(this.opts.subIndicators){this.$root.find("span.sub-arrow").remove()}if(this.opts.markCurrentItem){this.$root.find("a.current").removeClass("current")}if(!m){this.$root=null;this.$firstLink=null;this.$firstSub=null;if(this.$disableOverlay){this.$disableOverlay.remove();this.$disableOverlay=null}b.splice(a.inArray(this,b),1)}},disable:function(l){if(!this.disabled){this.menuHideAll();if(!l&&!this.opts.isPopup&&this.$root.is(":visible")){var m=this.$root.offset();this.$disableOverlay=a('<div class="sm-jquery-disable-overlay"/>').css({position:"absolute",top:m.top,left:m.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(true),opacity:0}).appendTo(document.body)}this.disabled=true}},docClick:function(l){if(this.$touchScrollingSub){this.$touchScrollingSub=null;return}if(this.visibleSubMenus.length&&!a.contains(this.$root[0],l.target)||a(l.target).is("a")){this.menuHideAll()}},docTouchEnd:function(m){if(!this.lastTouch){return}if(this.visibleSubMenus.length&&(this.lastTouch.x2===undefined||this.lastTouch.x1==this.lastTouch.x2)&&(this.lastTouch.y2===undefined||this.lastTouch.y1==this.lastTouch.y2)&&(!this.lastTouch.target||!a.contains(this.$root[0],this.lastTouch.target))){if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}var l=this;this.hideTimeout=setTimeout(function(){l.menuHideAll()},350)}this.lastTouch=null},docTouchMove:function(m){if(!this.lastTouch){return}var l=m.originalEvent.touches[0];this.lastTouch.x2=l.pageX;this.lastTouch.y2=l.pageY},docTouchStart:function(m){var l=m.originalEvent.touches[0];this.lastTouch={x1:l.pageX,y1:l.pageY,target:l.target}},enable:function(){if(this.disabled){if(this.$disableOverlay){this.$disableOverlay.remove();this.$disableOverlay=null}this.disabled=false}},getClosestMenu:function(m){var l=a(m).closest("ul");while(l.dataSM("in-mega")){l=l.parent().closest("ul")}return l[0]||null},getHeight:function(l){return this.getOffset(l,true)},getOffset:function(n,l){var m;if(n.css("display")=="none"){m={position:n[0].style.position,visibility:n[0].style.visibility};n.css({position:"absolute",visibility:"hidden"}).show()}var o=n[0].getBoundingClientRect&&n[0].getBoundingClientRect(),p=o&&(l?o.height||o.bottom-o.top:o.width||o.right-o.left);if(!p&&p!==0){p=l?n[0].offsetHeight:n[0].offsetWidth}if(m){n.hide().css(m)}return p},getStartZIndex:function(l){var m=parseInt(this[l?"$root":"$firstSub"].css("z-index"));if(!l&&isNaN(m)){m=parseInt(this.$root.css("z-index"))}return !isNaN(m)?m:1},getTouchPoint:function(l){return l.touches&&l.touches[0]||l.changedTouches&&l.changedTouches[0]||l},getViewport:function(l){var m=l?"Height":"Width",o=document.documentElement["client"+m],n=window["inner"+m];if(n){o=Math.min(o,n)}return o},getViewportHeight:function(){return this.getViewport(true)},getViewportWidth:function(){return this.getViewport()},getWidth:function(l){return this.getOffset(l)},handleEvents:function(){return !this.disabled&&this.isCSSOn()},handleItemEvents:function(l){return this.handleEvents()&&!this.isLinkInMegaMenu(l)},isCollapsible:function(){return this.$firstSub.css("position")=="static"},isCSSOn:function(){return this.$firstLink.css("display")=="block"},isFixed:function(){var l=this.$root.css("position")=="fixed";if(!l){this.$root.parentsUntil("body").each(function(){if(a(this).css("position")=="fixed"){l=true;return false}})}return l},isLinkInMegaMenu:function(l){return a(this.getClosestMenu(l[0])).hasClass("mega-menu")},isTouchMode:function(){return !f||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(p,l){var n=p.closest("ul"),q=n.dataSM("level");if(q>1&&(!this.activatedItems[q-2]||this.activatedItems[q-2][0]!=n.dataSM("parent-a")[0])){var m=this;a(n.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(n).each(function(){m.itemActivate(a(this).dataSM("parent-a"))})}if(!this.isCollapsible()||l){this.menuHideSubMenus(!this.activatedItems[q-1]||this.activatedItems[q-1][0]!=p[0]?q-1:q)}this.activatedItems[q-1]=p;if(this.$root.triggerHandler("activate.smapi",p[0])===false){return}var o=p.dataSM("sub");if(o&&(this.isTouchMode()||(!this.opts.showOnClick||this.clickActivated))){this.menuShow(o)}},itemBlur:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}this.$root.triggerHandler("blur.smapi",l[0])},itemClick:function(o){var n=a(o.currentTarget);if(!this.handleItemEvents(n)){return}if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==n.closest("ul")[0]){this.$touchScrollingSub=null;o.stopPropagation();return false}if(this.$root.triggerHandler("click.smapi",n[0])===false){return false}var p=a(o.target).is("span.sub-arrow"),m=n.dataSM("sub"),l=m?m.dataSM("level")==2:false;if(m&&!m.is(":visible")){if(this.opts.showOnClick&&l){this.clickActivated=true}this.itemActivate(n);if(m.is(":visible")){this.focusActivated=true;return false}}else{if(this.isCollapsible()&&p){this.itemActivate(n);this.menuHide(m);return false}}if(this.opts.showOnClick&&l||n.hasClass("disabled")||this.$root.triggerHandler("select.smapi",n[0])===false){return false}},itemDown:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}l.dataSM("mousedown",true)},itemEnter:function(n){var m=a(n.currentTarget);if(!this.handleItemEvents(m)){return}if(!this.isTouchMode()){if(this.showTimeout){clearTimeout(this.showTimeout);this.showTimeout=0}var l=this;this.showTimeout=setTimeout(function(){l.itemActivate(m)},this.opts.showOnClick&&m.closest("ul").dataSM("level")==1?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",m[0])},itemFocus:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}if(this.focusActivated&&(!this.isTouchMode()||!l.dataSM("mousedown"))&&(!this.activatedItems.length||this.activatedItems[this.activatedItems.length-1][0]!=l[0])){this.itemActivate(l,true)}this.$root.triggerHandler("focus.smapi",l[0])},itemLeave:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}if(!this.isTouchMode()){l[0].blur();if(this.showTimeout){clearTimeout(this.showTimeout);this.showTimeout=0}}l.removeDataSM("mousedown");this.$root.triggerHandler("mouseleave.smapi",l[0])},menuHide:function(m){if(this.$root.triggerHandler("beforehide.smapi",m[0])===false){return}m.stop(true,true);if(m.css("display")!="none"){var l=function(){m.css("z-index","")};if(this.isCollapsible()){if(this.opts.collapsibleHideFunction){this.opts.collapsibleHideFunction.call(this,m,l)}else{m.hide(this.opts.collapsibleHideDuration,l)}}else{if(this.opts.hideFunction){this.opts.hideFunction.call(this,m,l)}else{m.hide(this.opts.hideDuration,l)}}if(m.dataSM("ie-shim")){m.dataSM("ie-shim").remove().css({"-webkit-transform":"",transform:""})}if(m.dataSM("scroll")){this.menuScrollStop(m);m.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).unbind(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()}m.dataSM("parent-a").removeClass("highlighted").attr("aria-expanded","false");m.attr({"aria-expanded":"false","aria-hidden":"true"});var n=m.dataSM("level");this.activatedItems.splice(n-1,1);this.visibleSubMenus.splice(a.inArray(m,this.visibleSubMenus),1);this.$root.triggerHandler("hide.smapi",m[0])}},menuHideAll:function(){if(this.showTimeout){clearTimeout(this.showTimeout);this.showTimeout=0}var m=this.opts.isPopup?1:0;for(var l=this.visibleSubMenus.length-1;l>=m;l--){this.menuHide(this.visibleSubMenus[l])}if(this.opts.isPopup){this.$root.stop(true,true);if(this.$root.is(":visible")){if(this.opts.hideFunction){this.opts.hideFunction.call(this,this.$root)}else{this.$root.hide(this.opts.hideDuration)}if(this.$root.dataSM("ie-shim")){this.$root.dataSM("ie-shim").remove()}}}this.activatedItems=[];this.visibleSubMenus=[];this.clickActivated=false;this.focusActivated=false;this.zIndexInc=0;this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(n){for(var l=this.activatedItems.length-1;l>=n;l--){var m=this.activatedItems[l].dataSM("sub");if(m){this.menuHide(m)}}},menuIframeShim:function(l){if(e&&this.opts.overlapControlsInIE&&!l.dataSM("ie-shim")){l.dataSM("ie-shim",a("<iframe/>").attr({src:"javascript:0",tabindex:-9}).css({position:"absolute",top:"auto",left:"0",opacity:0,border:"0"}))}},menuInit:function(l){if(!l.dataSM("in-mega")){if(l.hasClass("mega-menu")){l.find("ul").dataSM("in-mega",true)}var q=2,m=l[0];while((m=m.parentNode.parentNode)!=this.$root[0]){q++}var n=l.prevAll("a").eq(-1);if(!n.length){n=l.prevAll().find("a").eq(-1)}n.addClass("has-submenu").dataSM("sub",l);l.dataSM("parent-a",n).dataSM("level",q).parent().dataSM("sub",l);var o=n.attr("id")||this.accessIdPrefix+(++this.idInc),p=l.attr("id")||this.accessIdPrefix+(++this.idInc);n.attr({id:o,"aria-haspopup":"true","aria-controls":p,"aria-expanded":"false"});l.attr({id:p,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"});if(this.opts.subIndicators){n[this.opts.subIndicatorsPos](this.$subArrow.clone())}}},menuPosition:function(K){var r=K.dataSM("parent-a"),D=r.closest("li"),E=D.parent(),l=K.dataSM("level"),t=this.getWidth(K),J=this.getHeight(K),u=r.offset(),o=u.left,m=u.top,q=this.getWidth(r),F=this.getHeight(r),H=a(window),v=H.scrollLeft(),s=H.scrollTop(),z=this.getViewportWidth(),L=this.getViewportHeight(),w=E.parent().is("[data-sm-horizontal-sub]")||l==2&&!E.hasClass("sm-vertical"),B=this.opts.rightToLeftSubMenus&&!D.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&D.is("[data-sm-reverse]"),p=l==2?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,n=l==2?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY,C,A;if(w){C=B?q-t-p:p;A=this.opts.bottomToTopSubMenus?-J-n:F+n}else{C=B?p-t:q-p;A=this.opts.bottomToTopSubMenus?F-n-J:n}if(this.opts.keepInViewport){var N=o+C,M=m+A;if(B&&N<v){C=w?v-N+C:q-p}else{if(!B&&N+t>v+z){C=w?v+z-t-N+C:p-t}}if(!w){if(J<L&&M+J>s+L){A+=s+L-J-M}else{if(J>=L||M<s){A+=s-M}}}if(w&&(M+J>s+L+0.49||M<s)||!w&&J>L+0.49){var G=this;if(!K.dataSM("scroll-arrows")){K.dataSM("scroll-arrows",a([a('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0],a('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]]).bind({mouseenter:function(){K.dataSM("scroll").up=a(this).hasClass("scroll-up");G.menuScroll(K)},mouseleave:function(x){G.menuScrollStop(K);G.menuScrollOut(K,x)},"mousewheel DOMMouseScroll":function(x){x.preventDefault()}}).insertAfter(K))}var I=".smartmenus_scroll";K.dataSM("scroll",{y:this.cssTransforms3d?0:A-F,step:1,itemH:F,subH:J,arrowDownH:this.getHeight(K.dataSM("scroll-arrows").eq(1))}).bind(i([["mouseover",function(x){G.menuScrollOver(K,x)}],["mouseout",function(x){G.menuScrollOut(K,x)}],["mousewheel DOMMouseScroll",function(x){G.menuScrollMousewheel(K,x)}]],I)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:C+(parseInt(K.css("border-left-width"))||0),width:t-(parseInt(K.css("border-left-width"))||0)-(parseInt(K.css("border-right-width"))||0),zIndex:K.css("z-index")}).eq(w&&this.opts.bottomToTopSubMenus?0:1).show();if(this.isFixed()){K.css({"touch-action":"none","-ms-touch-action":"none"}).bind(i([[d?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp",function(x){G.menuScrollTouch(K,x)}]],I))}}}K.css({top:"auto",left:"0",marginLeft:C,marginTop:A-F});this.menuIframeShim(K);if(K.dataSM("ie-shim")){K.dataSM("ie-shim").css({zIndex:K.css("z-index"),width:t,height:J,marginLeft:C,marginTop:A-F})}},menuScroll:function(r,m,n){var p=r.dataSM("scroll"),q=r.dataSM("scroll-arrows"),o=p.up?p.upEnd:p.downEnd,s;if(!m&&p.momentum){p.momentum*=0.92;s=p.momentum;if(s<0.5){this.menuScrollStop(r);return}}else{s=n||(m||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(p.step))}var l=r.dataSM("level");if(this.activatedItems[l-1]&&this.activatedItems[l-1].dataSM("sub")&&this.activatedItems[l-1].dataSM("sub").is(":visible")){this.menuHideSubMenus(l-1)}p.y=p.up&&o<=p.y||!p.up&&o>=p.y?p.y:(Math.abs(o-p.y)>s?p.y+(p.up?s:-s):o);r.add(r.dataSM("ie-shim")).css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+p.y+"px, 0)",transform:"translate3d(0, "+p.y+"px, 0)"}:{marginTop:p.y});if(f&&(p.up&&p.y>p.downEnd||!p.up&&p.y<p.upEnd)){q.eq(p.up?1:0).show()}if(p.y==o){if(f){q.eq(p.up?0:1).hide()}this.menuScrollStop(r)}else{if(!m){if(this.opts.scrollAccelerate&&p.step<this.opts.scrollStep){p.step+=0.2}var t=this;this.scrollTimeout=g(function(){t.menuScroll(r)})}}},menuScrollMousewheel:function(m,n){if(this.getClosestMenu(n.target)==m[0]){n=n.originalEvent;var l=(n.wheelDelta||-n.detail)>0;if(m.dataSM("scroll-arrows").eq(l?0:1).is(":visible")){m.dataSM("scroll").up=l;this.menuScroll(m,true)}}n.preventDefault()},menuScrollOut:function(l,m){if(f){if(!/^scroll-(up|down)/.test((m.relatedTarget||"").className)&&(l[0]!=m.relatedTarget&&!a.contains(l[0],m.relatedTarget)||this.getClosestMenu(m.relatedTarget)!=l[0])){l.dataSM("scroll-arrows").css("visibility","hidden")}}},menuScrollOver:function(n,o){if(f){if(!/^scroll-(up|down)/.test(o.target.className)&&this.getClosestMenu(o.target)==n[0]){this.menuScrollRefreshData(n);var m=n.dataSM("scroll"),l=a(window).scrollTop()-n.dataSM("parent-a").offset().top-m.itemH;n.dataSM("scroll-arrows").eq(0).css("margin-top",l).end().eq(1).css("margin-top",l+this.getViewportHeight()-m.arrowDownH).end().css("visibility","visible")}}},menuScrollRefreshData:function(n){var m=n.dataSM("scroll"),l=a(window).scrollTop()-n.dataSM("parent-a").offset().top-m.itemH;if(this.cssTransforms3d){l=-(parseFloat(n.css("margin-top"))-l)}a.extend(m,{upEnd:l,downEnd:l+this.getViewportHeight()-m.subH})},menuScrollStop:function(l){if(this.scrollTimeout){c(this.scrollTimeout);this.scrollTimeout=0;l.dataSM("scroll").step=1;return true}},menuScrollTouch:function(p,q){q=q.originalEvent;if(j(q)){var m=this.getTouchPoint(q);if(this.getClosestMenu(m.target)==p[0]){var o=p.dataSM("scroll");if(/(start|down)$/i.test(q.type)){if(this.menuScrollStop(p)){q.preventDefault();this.$touchScrollingSub=p}else{this.$touchScrollingSub=null}this.menuScrollRefreshData(p);a.extend(o,{touchStartY:m.pageY,touchStartTime:q.timeStamp})}else{if(/move$/i.test(q.type)){var n=o.touchY!==undefined?o.touchY:o.touchStartY;if(n!==undefined&&n!=m.pageY){this.$touchScrollingSub=p;var l=n<m.pageY;if(o.up!==undefined&&o.up!=l){a.extend(o,{touchStartY:m.pageY,touchStartTime:q.timeStamp})}a.extend(o,{up:l,touchY:m.pageY});this.menuScroll(p,true,Math.abs(m.pageY-n))}q.preventDefault()}else{if(o.touchY!==undefined){if(o.momentum=Math.pow(Math.abs(m.pageY-o.touchStartY)/(q.timeStamp-o.touchStartTime),2)*15){this.menuScrollStop(p);this.menuScroll(p);q.preventDefault()}delete o.touchY}}}}}},menuShow:function(n){if(!n.dataSM("beforefirstshowfired")){n.dataSM("beforefirstshowfired",true);if(this.$root.triggerHandler("beforefirstshow.smapi",n[0])===false){return}}if(this.$root.triggerHandler("beforeshow.smapi",n[0])===false){return}n.dataSM("shown-before",true).stop(true,true);if(!n.is(":visible")){var m=n.dataSM("parent-a");if(this.opts.keepHighlighted||this.isCollapsible()){m.addClass("highlighted")}if(this.isCollapsible()){n.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""})}else{n.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1);if(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth){n.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap");if(this.opts.subMenusMinWidth){n.css("min-width",this.opts.subMenusMinWidth)}if(this.opts.subMenusMaxWidth){var o=this.getWidth(n);n.css("max-width",this.opts.subMenusMaxWidth);if(o>this.getWidth(n)){n.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}}}this.menuPosition(n);if(n.dataSM("ie-shim")){n.dataSM("ie-shim").insertBefore(n)}}var l=function(){n.css("overflow","")};if(this.isCollapsible()){if(this.opts.collapsibleShowFunction){this.opts.collapsibleShowFunction.call(this,n,l)}else{n.show(this.opts.collapsibleShowDuration,l)}}else{if(this.opts.showFunction){this.opts.showFunction.call(this,n,l)}else{n.show(this.opts.showDuration,l)}}m.attr("aria-expanded","true");n.attr({"aria-expanded":"true","aria-hidden":"false"});this.visibleSubMenus.push(n);this.$root.triggerHandler("show.smapi",n[0])}},popupHide:function(l){if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}var m=this;this.hideTimeout=setTimeout(function(){m.menuHideAll()},l?1:this.opts.hideTimeout)},popupShow:function(o,n){if(!this.opts.isPopup){alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');return}if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}this.$root.dataSM("shown-before",true).stop(true,true);if(!this.$root.is(":visible")){this.$root.css({left:o,top:n});this.menuIframeShim(this.$root);if(this.$root.dataSM("ie-shim")){this.$root.dataSM("ie-shim").css({zIndex:this.$root.css("z-index"),width:this.getWidth(this.$root),height:this.getHeight(this.$root),left:o,top:n}).insertBefore(this.$root)}var m=this,l=function(){m.$root.css("overflow","")};if(this.opts.showFunction){this.opts.showFunction.call(this,this.$root,l)}else{this.$root.show(this.opts.showDuration,l)}this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(true);this.init(true)},rootKeyDown:function(o){if(!this.handleEvents()){return}switch(o.keyCode){case 27:var m=this.activatedItems[0];if(m){this.menuHideAll();m[0].focus();var n=m.dataSM("sub");if(n){this.menuHide(n)}}break;case 32:var l=a(o.target);if(l.is("a")&&this.handleItemEvents(l)){var n=l.dataSM("sub");if(n&&!n.is(":visible")){this.itemClick({currentTarget:o.target});o.preventDefault()}}break}},rootOut:function(m){if(!this.handleEvents()||this.isTouchMode()||m.target==this.$root[0]){return}if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}if(!this.opts.showOnClick||!this.opts.hideOnClick){var l=this;this.hideTimeout=setTimeout(function(){l.menuHideAll()},this.opts.hideTimeout)}},rootOver:function(l){if(!this.handleEvents()||this.isTouchMode()||l.target==this.$root[0]){return}if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}},winResize:function(m){if(!this.handleEvents()){if(this.$disableOverlay){var n=this.$root.offset();this.$disableOverlay.css({top:n.top,left:n.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}return}if(!("onorientationchange" in window)||m.type=="orientationchange"){var l=this.isCollapsible();if(!(this.wasCollapsible&&l)){if(this.activatedItems.length){this.activatedItems[this.activatedItems.length-1][0].blur()}this.menuHideAll()}this.wasCollapsible=l}}}});a.fn.dataSM=function(l,m){if(m){return this.data(l+"_smartmenus",m)}return this.data(l+"_smartmenus")};a.fn.removeDataSM=function(l){return this.removeData(l+"_smartmenus")};a.fn.smartmenus=function(m){if(typeof m=="string"){var l=arguments,o=m;Array.prototype.shift.call(l);return this.each(function(){var p=a(this).data("smartmenus");if(p&&p[o]){p[o].apply(p,l)}})}var n=a.extend({},a.fn.smartmenus.defaults,m);return this.each(function(){new a.SmartMenus(this,n)})};a.fn.smartmenus.defaults={isPopup:false,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:true,subIndicatorsPos:"prepend",subIndicatorsText:"+",scrollStep:30,scrollAccelerate:true,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(m,l){m.fadeOut(200,l)},collapsibleShowDuration:0,collapsibleShowFunction:function(m,l){m.slideDown(200,l)},collapsibleHideDuration:0,collapsibleHideFunction:function(m,l){m.slideUp(200,l)},showOnClick:false,hideOnClick:true,noMouseOver:false,keepInViewport:true,keepHighlighted:true,markCurrentItem:false,markCurrentTree:true,rightToLeftSubMenus:false,bottomToTopSubMenus:false,overlapControlsInIE:true};return a}));
\ No newline at end of file
diff --git a/docs/html/menu.js b/docs/html/menu.js
new file mode 100644
index 0000000..97db4c2
--- /dev/null
+++ b/docs/html/menu.js
@@ -0,0 +1,26 @@
+function initMenu(relPath,searchEnabled,serverSide,searchPage,search) {
+ function makeTree(data,relPath) {
+ var result='';
+ if ('children' in data) {
+ result+='<ul>';
+ for (var i in data.children) {
+ result+='<li><a href="'+relPath+data.children[i].url+'">'+
+ data.children[i].text+'</a>'+
+ makeTree(data.children[i],relPath)+'</li>';
+ }
+ result+='</ul>';
+ }
+ return result;
+ }
+
+ $('#main-nav').append(makeTree(menudata,relPath));
+ $('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu');
+ if (searchEnabled) {
+ if (serverSide) {
+ $('#main-menu').append('<li style="float:right"><div id="MSearchBox" class="MSearchBoxInactive"><div class="left"><form id="FSearchBox" action="'+searchPage+'" method="get"><img id="MSearchSelect" src="'+relPath+'search/mag.png" alt=""/><input type="text" id="MSearchField" name="query" value="'+search+'" size="20" accesskey="S" onfocus="searchBox.OnSearchFieldFocus(true)" onblur="searchBox.OnSearchFieldFocus(false)"></form></div><div class="right"></div></div></li>');
+ } else {
+ $('#main-menu').append('<li style="float:right"><div id="MSearchBox" class="MSearchBoxInactive"><span class="left"><img id="MSearchSelect" src="'+relPath+'search/mag_sel.png" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()" alt=""/><input type="text" id="MSearchField" value="'+search+'" accesskey="S" onfocus="searchBox.OnSearchFieldFocus(true)" onblur="searchBox.OnSearchFieldFocus(false)" onkeyup="searchBox.OnSearchFieldChange(event)"/></span><span class="right"><a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="'+relPath+'search/close.png" alt=""/></a></span></div></li>');
+ }
+ }
+ $('#main-menu').smartmenus();
+}
diff --git a/docs/html/menudata.js b/docs/html/menudata.js
new file mode 100644
index 0000000..3fa90ba
--- /dev/null
+++ b/docs/html/menudata.js
@@ -0,0 +1,19 @@
+var menudata={children:[
+{text:"Main Page",url:"index.html"},
+{text:"Modules",url:"modules.html"},
+{text:"Classes",url:"annotated.html",children:[
+{text:"Class List",url:"annotated.html"},
+{text:"Class Index",url:"classes.html"},
+{text:"Class Members",url:"functions.html",children:[
+{text:"All",url:"functions.html"},
+{text:"Variables",url:"functions_vars.html"}]}]},
+{text:"Files",url:"files.html",children:[
+{text:"File List",url:"files.html"},
+{text:"File Members",url:"globals.html",children:[
+{text:"All",url:"globals.html",children:[
+{text:"p",url:"globals.html#index_p"}]},
+{text:"Functions",url:"globals_func.html",children:[
+{text:"p",url:"globals_func.html#index_p"}]},
+{text:"Typedefs",url:"globals_type.html"},
+{text:"Macros",url:"globals_defs.html",children:[
+{text:"p",url:"globals_defs.html#index_p"}]}]}]}]}
diff --git a/docs/html/modules.html b/docs/html/modules.html
new file mode 100644
index 0000000..759dfc2
--- /dev/null
+++ b/docs/html/modules.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Modules</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+ <div class="headertitle">
+<div class="title">Modules</div> </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here is a list of all modules:</div><div class="directory">
+<table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__platform.html" target="_self">Implementation-specific definitions</a></td><td class="desc"></td></tr>
+<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__basic.html" target="_self">Basic definitions</a></td><td class="desc"></td></tr>
+<tr id="row_2_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__crypto__types.html" target="_self">Key and algorithm types</a></td><td class="desc"></td></tr>
+<tr id="row_3_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__key__management.html" target="_self">Key management</a></td><td class="desc"></td></tr>
+<tr id="row_4_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__policy.html" target="_self">Key policies</a></td><td class="desc"></td></tr>
+<tr id="row_5_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__persistence.html" target="_self">Key lifetime</a></td><td class="desc"></td></tr>
+<tr id="row_6_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__hash.html" target="_self">Message digests</a></td><td class="desc"></td></tr>
+<tr id="row_7_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__MAC.html" target="_self">Message authentication codes</a></td><td class="desc"></td></tr>
+<tr id="row_8_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__cipher.html" target="_self">Symmetric ciphers</a></td><td class="desc"></td></tr>
+<tr id="row_9_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__aead.html" target="_self">Authenticated encryption with associated data (AEAD)</a></td><td class="desc"></td></tr>
+<tr id="row_10_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__asymmetric.html" target="_self">Asymmetric cryptography</a></td><td class="desc"></td></tr>
+<tr id="row_11_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__generators.html" target="_self">Generators</a></td><td class="desc"></td></tr>
+<tr id="row_12_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__derivation.html" target="_self">Key derivation</a></td><td class="desc"></td></tr>
+<tr id="row_13_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="group__random.html" target="_self">Random generation</a></td><td class="desc"></td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/nav_f.png b/docs/html/nav_f.png
new file mode 100644
index 0000000..72a58a5
--- /dev/null
+++ b/docs/html/nav_f.png
Binary files differ
diff --git a/docs/html/nav_g.png b/docs/html/nav_g.png
new file mode 100644
index 0000000..2093a23
--- /dev/null
+++ b/docs/html/nav_g.png
Binary files differ
diff --git a/docs/html/nav_h.png b/docs/html/nav_h.png
new file mode 100644
index 0000000..33389b1
--- /dev/null
+++ b/docs/html/nav_h.png
Binary files differ
diff --git a/docs/html/open.png b/docs/html/open.png
new file mode 100644
index 0000000..30f75c7
--- /dev/null
+++ b/docs/html/open.png
Binary files differ
diff --git a/docs/html/search/all_0.html b/docs/html/search/all_0.html
new file mode 100644
index 0000000..f25360b
--- /dev/null
+++ b/docs/html/search/all_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_0.js b/docs/html/search/all_0.js
new file mode 100644
index 0000000..9e9cdcb
--- /dev/null
+++ b/docs/html/search/all_0.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['authenticated_20encryption_20with_20associated_20data_20_28aead_29',['Authenticated encryption with associated data (AEAD)',['../group__aead.html',1,'']]],
+ ['asymmetric_20cryptography',['Asymmetric cryptography',['../group__asymmetric.html',1,'']]]
+];
diff --git a/docs/html/search/all_1.html b/docs/html/search/all_1.html
new file mode 100644
index 0000000..b13f0f7
--- /dev/null
+++ b/docs/html/search/all_1.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_1.js b/docs/html/search/all_1.js
new file mode 100644
index 0000000..d379fe2
--- /dev/null
+++ b/docs/html/search/all_1.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['basic_20definitions',['Basic definitions',['../group__basic.html',1,'']]]
+];
diff --git a/docs/html/search/all_2.html b/docs/html/search/all_2.html
new file mode 100644
index 0000000..9543c57
--- /dev/null
+++ b/docs/html/search/all_2.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_2.js b/docs/html/search/all_2.js
new file mode 100644
index 0000000..270f99a
--- /dev/null
+++ b/docs/html/search/all_2.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['crypto_2eh',['crypto.h',['../crypto_8h.html',1,'']]],
+ ['crypto_5fsizes_2eh',['crypto_sizes.h',['../crypto__sizes_8h.html',1,'']]]
+];
diff --git a/docs/html/search/all_3.html b/docs/html/search/all_3.html
new file mode 100644
index 0000000..03405c0
--- /dev/null
+++ b/docs/html/search/all_3.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_3.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_3.js b/docs/html/search/all_3.js
new file mode 100644
index 0000000..9ba7121
--- /dev/null
+++ b/docs/html/search/all_3.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['e',['e',['../structpsa__generate__key__extra__rsa.html#a53ccb9e4375f3c9af6e3ecfe111ce11d',1,'psa_generate_key_extra_rsa']]]
+];
diff --git a/docs/html/search/all_4.html b/docs/html/search/all_4.html
new file mode 100644
index 0000000..8e1f4b9
--- /dev/null
+++ b/docs/html/search/all_4.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_4.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_4.js b/docs/html/search/all_4.js
new file mode 100644
index 0000000..bb51584
--- /dev/null
+++ b/docs/html/search/all_4.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['generators',['Generators',['../group__generators.html',1,'']]]
+];
diff --git a/docs/html/search/all_5.html b/docs/html/search/all_5.html
new file mode 100644
index 0000000..89a879e
--- /dev/null
+++ b/docs/html/search/all_5.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_5.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_5.js b/docs/html/search/all_5.js
new file mode 100644
index 0000000..f48be25
--- /dev/null
+++ b/docs/html/search/all_5.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['implementation_2dspecific_20definitions',['Implementation-specific definitions',['../group__platform.html',1,'']]]
+];
diff --git a/docs/html/search/all_6.html b/docs/html/search/all_6.html
new file mode 100644
index 0000000..6afac06
--- /dev/null
+++ b/docs/html/search/all_6.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_6.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_6.js b/docs/html/search/all_6.js
new file mode 100644
index 0000000..93b7ff0
--- /dev/null
+++ b/docs/html/search/all_6.js
@@ -0,0 +1,8 @@
+var searchData=
+[
+ ['key_20and_20algorithm_20types',['Key and algorithm types',['../group__crypto__types.html',1,'']]],
+ ['key_20derivation',['Key derivation',['../group__derivation.html',1,'']]],
+ ['key_20management',['Key management',['../group__key__management.html',1,'']]],
+ ['key_20lifetime',['Key lifetime',['../group__persistence.html',1,'']]],
+ ['key_20policies',['Key policies',['../group__policy.html',1,'']]]
+];
diff --git a/docs/html/search/all_7.html b/docs/html/search/all_7.html
new file mode 100644
index 0000000..de19107
--- /dev/null
+++ b/docs/html/search/all_7.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_7.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_7.js b/docs/html/search/all_7.js
new file mode 100644
index 0000000..6efdddb
--- /dev/null
+++ b/docs/html/search/all_7.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['message_20digests',['Message digests',['../group__hash.html',1,'']]],
+ ['message_20authentication_20codes',['Message authentication codes',['../group__MAC.html',1,'']]]
+];
diff --git a/docs/html/search/all_8.html b/docs/html/search/all_8.html
new file mode 100644
index 0000000..11e27cd
--- /dev/null
+++ b/docs/html/search/all_8.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_8.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_8.js b/docs/html/search/all_8.js
new file mode 100644
index 0000000..331f5bb
--- /dev/null
+++ b/docs/html/search/all_8.js
@@ -0,0 +1,166 @@
+var searchData=
+[
+ ['psa_5faead_5fdecrypt',['psa_aead_decrypt',['../group__aead.html#ga5b88ad2cfbf2e98039858416fa3ebd7a',1,'crypto.h']]],
+ ['psa_5faead_5fdecrypt_5foutput_5fsize',['PSA_AEAD_DECRYPT_OUTPUT_SIZE',['../crypto__sizes_8h.html#a1d057796166c16eb673ad1997e48a60b',1,'crypto_sizes.h']]],
+ ['psa_5faead_5fencrypt',['psa_aead_encrypt',['../group__aead.html#ga14e4068a3d328515a4884f3037904d54',1,'crypto.h']]],
+ ['psa_5faead_5fencrypt_5foutput_5fsize',['PSA_AEAD_ENCRYPT_OUTPUT_SIZE',['../crypto__sizes_8h.html#a85667d47a7aa6c7b99a80e5273671266',1,'crypto_sizes.h']]],
+ ['psa_5faead_5ftag_5fsize',['PSA_AEAD_TAG_SIZE',['../group__aead.html#ga337ef01fe3c9f71d62ccced33e8917f4',1,'crypto.h']]],
+ ['psa_5falg_5farc4',['PSA_ALG_ARC4',['../group__crypto__types.html#gab6a5284decb0e5e1b5b8740a41ef3c5e',1,'crypto.h']]],
+ ['psa_5falg_5fblock_5fcipher_5fpad_5fnone',['PSA_ALG_BLOCK_CIPHER_PAD_NONE',['../group__crypto__types.html#ga0992d26a02a2a7dc316cd5abc5254966',1,'crypto.h']]],
+ ['psa_5falg_5fcbc_5fbase',['PSA_ALG_CBC_BASE',['../group__crypto__types.html#ga931f31d4f05c3dab9fd5d7fdcd3715f2',1,'crypto.h']]],
+ ['psa_5falg_5fctr',['PSA_ALG_CTR',['../group__crypto__types.html#gad318309706a769cffdc64e4c7e06b2e9',1,'crypto.h']]],
+ ['psa_5falg_5fdeterministic_5fecdsa',['PSA_ALG_DETERMINISTIC_ECDSA',['../group__crypto__types.html#ga11da566bcd341661c8de921e2ca5ed03',1,'crypto.h']]],
+ ['psa_5falg_5fdsa',['PSA_ALG_DSA',['../group__crypto__types.html#ga9a68efdddff5ae95f104a1416b12742e',1,'crypto.h']]],
+ ['psa_5falg_5fecdsa',['PSA_ALG_ECDSA',['../group__crypto__types.html#ga7e3ce9f514a227d5ba5d8318870452e3',1,'crypto.h']]],
+ ['psa_5falg_5fecdsa_5fany',['PSA_ALG_ECDSA_ANY',['../group__crypto__types.html#ga51d6b6044a62e33cae0cf64bfc3b22a4',1,'crypto.h']]],
+ ['psa_5falg_5fhkdf',['PSA_ALG_HKDF',['../group__crypto__types.html#ga32a888fb360e6e25cab8a343772c4a82',1,'crypto.h']]],
+ ['psa_5falg_5fhmac',['PSA_ALG_HMAC',['../group__crypto__types.html#ga70f397425684b3efcde1e0e34c28261f',1,'crypto.h']]],
+ ['psa_5falg_5fis_5faead',['PSA_ALG_IS_AEAD',['../group__crypto__types.html#ga1d44829d60065eaa4ac9a703e7d6abc8',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fasymmetric_5fencryption',['PSA_ALG_IS_ASYMMETRIC_ENCRYPTION',['../group__crypto__types.html#ga41d2ee937d54efd76bd54a97b2ebc08a',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fblock_5fcipher',['PSA_ALG_IS_BLOCK_CIPHER',['../group__crypto__types.html#ga02e787d79c0cd666efcd090569d5b31c',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fcipher',['PSA_ALG_IS_CIPHER',['../group__crypto__types.html#ga1d1a5a402ad89a2e68f12bfb535490eb',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fcipher_5fmac',['PSA_ALG_IS_CIPHER_MAC',['../group__crypto__types.html#ga8986360ff97dbd91f220edf9202e375d',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fhash',['PSA_ALG_IS_HASH',['../group__crypto__types.html#gac9280662bb482590b4b33d1dcd32930f',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fhkdf',['PSA_ALG_IS_HKDF',['../group__crypto__types.html#ga1979d0a76fcee6164cf2e65960f38db2',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fhmac',['PSA_ALG_IS_HMAC',['../group__crypto__types.html#ga4a050c3c3cbc6eb96418f18847601c8a',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fkey_5fagreement',['PSA_ALG_IS_KEY_AGREEMENT',['../group__crypto__types.html#ga59753742cb06553bd22751bbef472b6f',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fkey_5fderivation',['PSA_ALG_IS_KEY_DERIVATION',['../group__crypto__types.html#gaf8b90c648aa53dbd06c236695e300cd0',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fmac',['PSA_ALG_IS_MAC',['../group__crypto__types.html#gaca7aee4c9dde316b3b1a150a26eab776',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fsign',['PSA_ALG_IS_SIGN',['../group__crypto__types.html#ga6d490d0904e0698f6c1268a89d72ff31',1,'crypto.h']]],
+ ['psa_5falg_5fis_5fstream_5fcipher',['PSA_ALG_IS_STREAM_CIPHER',['../group__crypto__types.html#gacfec68e0c6175e02e1b2ebc97df383c0',1,'crypto.h']]],
+ ['psa_5falg_5frsa_5foaep',['PSA_ALG_RSA_OAEP',['../group__crypto__types.html#gaa1235dc3fdd9839c6c1b1a9857344c76',1,'crypto.h']]],
+ ['psa_5falg_5frsa_5fpkcs1v15_5fcrypt',['PSA_ALG_RSA_PKCS1V15_CRYPT',['../group__crypto__types.html#ga4c540d3abe43fb9abcb94f2bc51acef9',1,'crypto.h']]],
+ ['psa_5falg_5frsa_5fpkcs1v15_5fsign',['PSA_ALG_RSA_PKCS1V15_SIGN',['../group__crypto__types.html#ga702ff75385a6ae7d4247033f479439af',1,'crypto.h']]],
+ ['psa_5falg_5frsa_5fpkcs1v15_5fsign_5fraw',['PSA_ALG_RSA_PKCS1V15_SIGN_RAW',['../group__crypto__types.html#ga4215e2a78dcf834e9a625927faa2a817',1,'crypto.h']]],
+ ['psa_5falg_5frsa_5fpss',['PSA_ALG_RSA_PSS',['../group__crypto__types.html#ga62152bf4cb4bf6aace5e1be8f143564d',1,'crypto.h']]],
+ ['psa_5falg_5fsha3_5f224',['PSA_ALG_SHA3_224',['../group__crypto__types.html#ga16f5fe34ccce68c2fada1224c054a999',1,'crypto.h']]],
+ ['psa_5falg_5fsha3_5f256',['PSA_ALG_SHA3_256',['../group__crypto__types.html#gaace70d9515489bbe3c5e7ac1b7d9155b',1,'crypto.h']]],
+ ['psa_5falg_5fsha3_5f384',['PSA_ALG_SHA3_384',['../group__crypto__types.html#gab0f079257ea75e2acfe2fc3b38c78cd8',1,'crypto.h']]],
+ ['psa_5falg_5fsha3_5f512',['PSA_ALG_SHA3_512',['../group__crypto__types.html#ga37e5dbe936dddb155e76f2997de27188',1,'crypto.h']]],
+ ['psa_5falg_5fsha_5f224',['PSA_ALG_SHA_224',['../group__crypto__types.html#ga25d6a3244d10a7148fe6b026d1979f7b',1,'crypto.h']]],
+ ['psa_5falg_5fsha_5f256',['PSA_ALG_SHA_256',['../group__crypto__types.html#ga619471f978e13cdd0a1e37145e4bf341',1,'crypto.h']]],
+ ['psa_5falg_5fsha_5f384',['PSA_ALG_SHA_384',['../group__crypto__types.html#ga58af64dd9a86a287e8da9ed7739eead4',1,'crypto.h']]],
+ ['psa_5falg_5fsha_5f512',['PSA_ALG_SHA_512',['../group__crypto__types.html#gafba3ae409f46d3dd7f37a0910660c3e9',1,'crypto.h']]],
+ ['psa_5falg_5fsha_5f512_5f224',['PSA_ALG_SHA_512_224',['../group__crypto__types.html#ga3fe2d7c3c80e3186ca78d16a35d5d931',1,'crypto.h']]],
+ ['psa_5falg_5fsha_5f512_5f256',['PSA_ALG_SHA_512_256',['../group__crypto__types.html#ga5910b3964c14e9613e8643a45b09c2d4',1,'crypto.h']]],
+ ['psa_5falg_5fsign_5fget_5fhash',['PSA_ALG_SIGN_GET_HASH',['../group__crypto__types.html#ga24cf6d7bcd2b9aeeeff86f07b6c674e3',1,'crypto.h']]],
+ ['psa_5falgorithm_5ft',['psa_algorithm_t',['../group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69',1,'crypto.h']]],
+ ['psa_5fasymmetric_5fdecrypt',['psa_asymmetric_decrypt',['../group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6',1,'crypto.h']]],
+ ['psa_5fasymmetric_5fdecrypt_5foutput_5fsize',['PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE',['../crypto__sizes_8h.html#a61a246f3eac41989821d982e56fea6c1',1,'crypto_sizes.h']]],
+ ['psa_5fasymmetric_5fencrypt',['psa_asymmetric_encrypt',['../group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2',1,'crypto.h']]],
+ ['psa_5fasymmetric_5fencrypt_5foutput_5fsize',['PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE',['../crypto__sizes_8h.html#a66ba3bd93e5ec52870ccc3848778bad8',1,'crypto_sizes.h']]],
+ ['psa_5fasymmetric_5fsign',['psa_asymmetric_sign',['../group__asymmetric.html#ga48091460d1ead078d93caa3611aec976',1,'crypto.h']]],
+ ['psa_5fasymmetric_5fsign_5foutput_5fsize',['PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE',['../crypto__sizes_8h.html#a77565b9b4fe6d8730fd2120f4c8378ab',1,'crypto_sizes.h']]],
+ ['psa_5fasymmetric_5fsignature_5fmax_5fsize',['PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE',['../crypto__sizes_8h.html#ad755101764dba14589e5919ee41be7ca',1,'crypto_sizes.h']]],
+ ['psa_5fasymmetric_5fverify',['psa_asymmetric_verify',['../group__asymmetric.html#gaee3e92946c1c4b3dfa90879e2f7d1321',1,'crypto.h']]],
+ ['psa_5fblock_5fcipher_5fblock_5fsize',['PSA_BLOCK_CIPHER_BLOCK_SIZE',['../group__crypto__types.html#gacaa366bdeb0413e63e87a667c5457b2e',1,'crypto.h']]],
+ ['psa_5fcipher_5fabort',['psa_cipher_abort',['../group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4',1,'crypto.h']]],
+ ['psa_5fcipher_5fdecrypt_5fsetup',['psa_cipher_decrypt_setup',['../group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950',1,'crypto.h']]],
+ ['psa_5fcipher_5fencrypt_5fsetup',['psa_cipher_encrypt_setup',['../group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98',1,'crypto.h']]],
+ ['psa_5fcipher_5ffinish',['psa_cipher_finish',['../group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b',1,'crypto.h']]],
+ ['psa_5fcipher_5fgenerate_5fiv',['psa_cipher_generate_iv',['../group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa',1,'crypto.h']]],
+ ['psa_5fcipher_5foperation_5ft',['psa_cipher_operation_t',['../group__cipher.html#ga1399de29db657e3737bb09927aae51fa',1,'crypto.h']]],
+ ['psa_5fcipher_5fset_5fiv',['psa_cipher_set_iv',['../group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42',1,'crypto.h']]],
+ ['psa_5fcipher_5fupdate',['psa_cipher_update',['../group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91',1,'crypto.h']]],
+ ['psa_5fcrypto_5fgenerator_5finit',['PSA_CRYPTO_GENERATOR_INIT',['../group__generators.html#ga4788b471385fc667876fbd8a0d3fe062',1,'crypto.h']]],
+ ['psa_5fcrypto_5fgenerator_5ft',['psa_crypto_generator_t',['../group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b',1,'crypto.h']]],
+ ['psa_5fcrypto_5finit',['psa_crypto_init',['../group__basic.html#ga2de150803fc2f7dc6101d5af7e921dd9',1,'crypto.h']]],
+ ['psa_5fdestroy_5fkey',['psa_destroy_key',['../group__key__management.html#ga2e9a60a9525ce6b3082a72df2080f0c5',1,'crypto.h']]],
+ ['psa_5fecc_5fcurve_5ft',['psa_ecc_curve_t',['../group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9',1,'crypto.h']]],
+ ['psa_5fecdsa_5fsignature_5fsize',['PSA_ECDSA_SIGNATURE_SIZE',['../group__asymmetric.html#ga10c472a35f04051add6b20cc228ffc11',1,'crypto.h']]],
+ ['psa_5ferror_5fbad_5fstate',['PSA_ERROR_BAD_STATE',['../group__basic.html#ga933d40fa2a591004f2e93aa91e11db84',1,'crypto.h']]],
+ ['psa_5ferror_5fbuffer_5ftoo_5fsmall',['PSA_ERROR_BUFFER_TOO_SMALL',['../group__basic.html#ga695025f4ec11249aee7ea3d0f65e01c8',1,'crypto.h']]],
+ ['psa_5ferror_5fcommunication_5ffailure',['PSA_ERROR_COMMUNICATION_FAILURE',['../group__basic.html#ga5cdb6948371d49e916106249020ea3f7',1,'crypto.h']]],
+ ['psa_5ferror_5fempty_5fslot',['PSA_ERROR_EMPTY_SLOT',['../group__basic.html#gaba00e3e6ceb2b12965a81e5ac02ae040',1,'crypto.h']]],
+ ['psa_5ferror_5fhardware_5ffailure',['PSA_ERROR_HARDWARE_FAILURE',['../group__basic.html#ga08b10e70fa5ff0b05c631d9f8f6b2c6b',1,'crypto.h']]],
+ ['psa_5ferror_5finsufficient_5fcapacity',['PSA_ERROR_INSUFFICIENT_CAPACITY',['../group__basic.html#gaf1fa61f72e9e5b4a848c991bea495767',1,'crypto.h']]],
+ ['psa_5ferror_5finsufficient_5fentropy',['PSA_ERROR_INSUFFICIENT_ENTROPY',['../group__basic.html#ga4deb59fec02297ec5d8b42178323f675',1,'crypto.h']]],
+ ['psa_5ferror_5finsufficient_5fmemory',['PSA_ERROR_INSUFFICIENT_MEMORY',['../group__basic.html#ga91b2ad8a867517a2651f1b076c5216e5',1,'crypto.h']]],
+ ['psa_5ferror_5finsufficient_5fstorage',['PSA_ERROR_INSUFFICIENT_STORAGE',['../group__basic.html#ga897a45eb206a6f6b7be7ffbe36f0d766',1,'crypto.h']]],
+ ['psa_5ferror_5finvalid_5fargument',['PSA_ERROR_INVALID_ARGUMENT',['../group__basic.html#ga798df25a505ebf931f7bec1f80f1f85f',1,'crypto.h']]],
+ ['psa_5ferror_5finvalid_5fpadding',['PSA_ERROR_INVALID_PADDING',['../group__basic.html#gabe29594edbfb152cf153975b0597ac48',1,'crypto.h']]],
+ ['psa_5ferror_5finvalid_5fsignature',['PSA_ERROR_INVALID_SIGNATURE',['../group__basic.html#ga35927f755d232c4766de600f2c49e9f2',1,'crypto.h']]],
+ ['psa_5ferror_5fnot_5fpermitted',['PSA_ERROR_NOT_PERMITTED',['../group__basic.html#ga4d1b8dd8526177a15a210b7afc1accb1',1,'crypto.h']]],
+ ['psa_5ferror_5fnot_5fsupported',['PSA_ERROR_NOT_SUPPORTED',['../group__basic.html#ga1dcc6d130633ed5db8942257581b55dd',1,'crypto.h']]],
+ ['psa_5ferror_5foccupied_5fslot',['PSA_ERROR_OCCUPIED_SLOT',['../group__basic.html#gac2fee3a51249fbea45360aaa911f3e58',1,'crypto.h']]],
+ ['psa_5ferror_5fstorage_5ffailure',['PSA_ERROR_STORAGE_FAILURE',['../group__basic.html#gadd169a1af2707862b95fb9df91dfc37d',1,'crypto.h']]],
+ ['psa_5ferror_5ftampering_5fdetected',['PSA_ERROR_TAMPERING_DETECTED',['../group__basic.html#ga2c5dda1485cb54f2385cb9c1279a7004',1,'crypto.h']]],
+ ['psa_5ferror_5funknown_5ferror',['PSA_ERROR_UNKNOWN_ERROR',['../group__basic.html#ga24d5fdcdd759f846f79d9e581c63a83f',1,'crypto.h']]],
+ ['psa_5fexport_5fkey',['psa_export_key',['../group__key__management.html#gaa67bc459b20028b268f3d75a05afe022',1,'crypto.h']]],
+ ['psa_5fexport_5fpublic_5fkey',['psa_export_public_key',['../group__key__management.html#ga7355b38f8eb9330db2786604f4a83a3b',1,'crypto.h']]],
+ ['psa_5fgenerate_5fkey',['psa_generate_key',['../group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10',1,'crypto.h']]],
+ ['psa_5fgenerate_5fkey_5fextra_5frsa',['psa_generate_key_extra_rsa',['../structpsa__generate__key__extra__rsa.html',1,'']]],
+ ['psa_5fgenerate_5frandom',['psa_generate_random',['../group__random.html#ga1985eae417dfbccedf50d5fff54ea8c5',1,'crypto.h']]],
+ ['psa_5fgenerator_5fabort',['psa_generator_abort',['../group__generators.html#ga563ca64537d90368899286b36d8cf7f3',1,'crypto.h']]],
+ ['psa_5fgenerator_5fimport_5fkey',['psa_generator_import_key',['../group__generators.html#ga06c1ba3d989827d909b4b01ffe983beb',1,'crypto.h']]],
+ ['psa_5fgenerator_5fread',['psa_generator_read',['../group__generators.html#gab5712ad29b78c2b170e64cc5bcfc1bce',1,'crypto.h']]],
+ ['psa_5fget_5fgenerator_5fcapacity',['psa_get_generator_capacity',['../group__generators.html#ga7453491e3b440193be2c5dccc2040fd2',1,'crypto.h']]],
+ ['psa_5fget_5fkey_5finformation',['psa_get_key_information',['../group__key__management.html#gaf105167657ab1d484cb4a51f93413717',1,'crypto.h']]],
+ ['psa_5fget_5fkey_5flifetime',['psa_get_key_lifetime',['../group__persistence.html#gaf0daaa1dba14dc324ca83dfe1495a5e2',1,'crypto.h']]],
+ ['psa_5fget_5fkey_5fpolicy',['psa_get_key_policy',['../group__policy.html#ga613f28712124f9149bd640614376ab5a',1,'crypto.h']]],
+ ['psa_5fhash_5fabort',['psa_hash_abort',['../group__hash.html#gab0b4d5f9912a615559497a467b532928',1,'crypto.h']]],
+ ['psa_5fhash_5ffinish',['psa_hash_finish',['../group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e',1,'crypto.h']]],
+ ['psa_5fhash_5fmax_5fsize',['PSA_HASH_MAX_SIZE',['../crypto__sizes_8h.html#a6ce1014efbbc0bcca286ef7f9a72cb29',1,'crypto_sizes.h']]],
+ ['psa_5fhash_5foperation_5ft',['psa_hash_operation_t',['../group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab',1,'crypto.h']]],
+ ['psa_5fhash_5fsetup',['psa_hash_setup',['../group__hash.html#ga8d72896cf70fc4d514c5c6b978912515',1,'crypto.h']]],
+ ['psa_5fhash_5fsize',['PSA_HASH_SIZE',['../group__hash.html#gaef340331ce3cba2b57e1fc5624bf1f99',1,'crypto.h']]],
+ ['psa_5fhash_5fupdate',['psa_hash_update',['../group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff',1,'crypto.h']]],
+ ['psa_5fhash_5fverify',['psa_hash_verify',['../group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0',1,'crypto.h']]],
+ ['psa_5fimport_5fkey',['psa_import_key',['../group__key__management.html#gace37363530e2525a2562f07ceec8efb5',1,'crypto.h']]],
+ ['psa_5fkey_5fderivation',['psa_key_derivation',['../group__derivation.html#ga1b6429f443a45e5f3209043abbbe8315',1,'crypto.h']]],
+ ['psa_5fkey_5flifetime_5fpersistent',['PSA_KEY_LIFETIME_PERSISTENT',['../group__persistence.html#ga3713a01c5fcd5f7eae46ff22ceaf6d02',1,'crypto.h']]],
+ ['psa_5fkey_5flifetime_5ft',['psa_key_lifetime_t',['../group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf',1,'crypto.h']]],
+ ['psa_5fkey_5flifetime_5fvolatile',['PSA_KEY_LIFETIME_VOLATILE',['../group__persistence.html#ga8b438870ba69489b685730d346455108',1,'crypto.h']]],
+ ['psa_5fkey_5flifetime_5fwrite_5fonce',['PSA_KEY_LIFETIME_WRITE_ONCE',['../group__persistence.html#gae6b8443238ef1900cf132550d7df557f',1,'crypto.h']]],
+ ['psa_5fkey_5fpolicy_5fget_5falgorithm',['psa_key_policy_get_algorithm',['../group__policy.html#gaadf16b89ace53e1d2cb5bcb0aef24c86',1,'crypto.h']]],
+ ['psa_5fkey_5fpolicy_5fget_5fusage',['psa_key_policy_get_usage',['../group__policy.html#ga7746662b7503e484774d0ecb5d8ac2ab',1,'crypto.h']]],
+ ['psa_5fkey_5fpolicy_5finit',['psa_key_policy_init',['../group__policy.html#gad49eb85e3fcbe70f763f511ac83e762e',1,'crypto.h']]],
+ ['psa_5fkey_5fpolicy_5fset_5fusage',['psa_key_policy_set_usage',['../group__policy.html#gac16792fd6d375a5f76d372090df40607',1,'crypto.h']]],
+ ['psa_5fkey_5fpolicy_5ft',['psa_key_policy_t',['../group__policy.html#gaf553efd409845b6d09ff25ce2ba36607',1,'crypto.h']]],
+ ['psa_5fkey_5fslot_5ft',['psa_key_slot_t',['../group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5faes',['PSA_KEY_TYPE_AES',['../group__crypto__types.html#ga6ee54579dcf278c677eda4bb1a29575e',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5farc4',['PSA_KEY_TYPE_ARC4',['../group__crypto__types.html#gae4d46e83f910dcaa126000a8ed03cde9',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fcamellia',['PSA_KEY_TYPE_CAMELLIA',['../group__crypto__types.html#gad8e5da742343fd5519f9d8a630c2ed81',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fderive',['PSA_KEY_TYPE_DERIVE',['../group__crypto__types.html#gae871b2357b8593f33bfd51abbf93ebb1',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fdes',['PSA_KEY_TYPE_DES',['../group__crypto__types.html#ga577562bfbbc691c820d55ec308333138',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fdsa_5fkeypair',['PSA_KEY_TYPE_DSA_KEYPAIR',['../group__crypto__types.html#ga011010ee28c20388f3d89fb27088ed62',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fdsa_5fpublic_5fkey',['PSA_KEY_TYPE_DSA_PUBLIC_KEY',['../group__crypto__types.html#ga5e7439c2905136366c3a876e62e5ddfc',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fecc_5fkeypair',['PSA_KEY_TYPE_ECC_KEYPAIR',['../group__crypto__types.html#gadf3ad65d157bf5282849c954bf3f51af',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fecc_5fpublic_5fkey',['PSA_KEY_TYPE_ECC_PUBLIC_KEY',['../group__crypto__types.html#gad54c03d3b47020e571a72cd01d978cf2',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fget_5fcurve',['PSA_KEY_TYPE_GET_CURVE',['../group__crypto__types.html#ga0c567210e6f80aa8f2aa87efa7a3a3f9',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fhmac',['PSA_KEY_TYPE_HMAC',['../group__crypto__types.html#ga92d989f4ca64abd00f463defd773a6f8',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fis_5fasymmetric',['PSA_KEY_TYPE_IS_ASYMMETRIC',['../group__crypto__types.html#gab138ae2ebf2905dfbaf4154db2620939',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fis_5fecc',['PSA_KEY_TYPE_IS_ECC',['../group__crypto__types.html#ga88e01fa06b585654689a99bcc06bbe66',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fis_5fkeypair',['PSA_KEY_TYPE_IS_KEYPAIR',['../group__crypto__types.html#gac14c6d6e1b2b7f4a92a7b757465cff29',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fis_5fpublic_5fkey',['PSA_KEY_TYPE_IS_PUBLIC_KEY',['../group__crypto__types.html#gac674a0f059bc0cb72b47f0c517b4f45b',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fis_5frsa',['PSA_KEY_TYPE_IS_RSA',['../group__crypto__types.html#ga0e1d8f241228e49c9cadadfb4579ef1a',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fis_5fvendor_5fdefined',['PSA_KEY_TYPE_IS_VENDOR_DEFINED',['../group__crypto__types.html#gadbe4c086a6562aefe344bc79e51bdfd3',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fkeypair_5fof_5fpublic_5fkey',['PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY',['../group__crypto__types.html#gaf09f1ca1de6a7e7cff0fe516f3f6c91d',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fnone',['PSA_KEY_TYPE_NONE',['../group__crypto__types.html#gafce7ab2b54ce97ea5bff73f13a9f3e5b',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fpublic_5fkey_5fof_5fkeypair',['PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR',['../group__crypto__types.html#gace08e46dd7cbf642d50d982a25d02bec',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fraw_5fdata',['PSA_KEY_TYPE_RAW_DATA',['../group__crypto__types.html#gaa97f92025533102616b32d571c940d80',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5frsa_5fkeypair',['PSA_KEY_TYPE_RSA_KEYPAIR',['../group__crypto__types.html#ga581f50687f5d650456925278948f2799',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5frsa_5fpublic_5fkey',['PSA_KEY_TYPE_RSA_PUBLIC_KEY',['../group__crypto__types.html#ga9ba0878f56c8bcd1995ac017a74f513b',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5ft',['psa_key_type_t',['../group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5fvendor_5fflag',['PSA_KEY_TYPE_VENDOR_FLAG',['../group__crypto__types.html#ga8dbaed2fdb1ebae8aa127ad3988516f7',1,'crypto.h']]],
+ ['psa_5fkey_5fusage_5fdecrypt',['PSA_KEY_USAGE_DECRYPT',['../group__policy.html#gac3f2d2e5983db1edde9f142ca9bf8e6a',1,'crypto.h']]],
+ ['psa_5fkey_5fusage_5fderive',['PSA_KEY_USAGE_DERIVE',['../group__policy.html#gaf19022acc5ef23cf12477f632b48a0b2',1,'crypto.h']]],
+ ['psa_5fkey_5fusage_5fencrypt',['PSA_KEY_USAGE_ENCRYPT',['../group__policy.html#ga75153b296d045d529d97203a6a995dad',1,'crypto.h']]],
+ ['psa_5fkey_5fusage_5fexport',['PSA_KEY_USAGE_EXPORT',['../group__policy.html#ga7dddccdd1303176e87a4d20c87b589ed',1,'crypto.h']]],
+ ['psa_5fkey_5fusage_5fsign',['PSA_KEY_USAGE_SIGN',['../group__policy.html#ga99b9f456cf59efc4b5579465407aef5a',1,'crypto.h']]],
+ ['psa_5fkey_5fusage_5ft',['psa_key_usage_t',['../group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25',1,'crypto.h']]],
+ ['psa_5fkey_5fusage_5fverify',['PSA_KEY_USAGE_VERIFY',['../group__policy.html#ga39b54ffd5958b69634607924fa53cea6',1,'crypto.h']]],
+ ['psa_5fmac_5fabort',['psa_mac_abort',['../group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd',1,'crypto.h']]],
+ ['psa_5fmac_5ffinal_5fsize',['PSA_MAC_FINAL_SIZE',['../crypto__sizes_8h.html#aa84c5fb384ac7cb1bfc52adde96588ee',1,'crypto_sizes.h']]],
+ ['psa_5fmac_5fmax_5fsize',['PSA_MAC_MAX_SIZE',['../crypto__sizes_8h.html#a4681cc4f6226883a2160122c562ca682',1,'crypto_sizes.h']]],
+ ['psa_5fmac_5foperation_5ft',['psa_mac_operation_t',['../group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37',1,'crypto.h']]],
+ ['psa_5fmac_5fsign_5ffinish',['psa_mac_sign_finish',['../group__MAC.html#gac22bc0125580c96724a09226cfbc97f2',1,'crypto.h']]],
+ ['psa_5fmac_5fsign_5fsetup',['psa_mac_sign_setup',['../group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177',1,'crypto.h']]],
+ ['psa_5fmac_5fupdate',['psa_mac_update',['../group__MAC.html#ga5560af371497babefe03c9da4e8a1c05',1,'crypto.h']]],
+ ['psa_5fmac_5fverify_5ffinish',['psa_mac_verify_finish',['../group__MAC.html#gac92b2930d6728e1be4d011c05d485822',1,'crypto.h']]],
+ ['psa_5fmac_5fverify_5fsetup',['psa_mac_verify_setup',['../group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d',1,'crypto.h']]],
+ ['psa_5fset_5fkey_5flifetime',['psa_set_key_lifetime',['../group__persistence.html#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8',1,'crypto.h']]],
+ ['psa_5fset_5fkey_5fpolicy',['psa_set_key_policy',['../group__policy.html#gad7faa7e64aa771f7441c44ceff21af19',1,'crypto.h']]],
+ ['psa_5fstatus_5ft',['psa_status_t',['../group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9',1,'crypto.h']]],
+ ['psa_5fsuccess',['PSA_SUCCESS',['../group__basic.html#ga4cc859e2c66ca381c7418db3527a65e1',1,'crypto.h']]]
+];
diff --git a/docs/html/search/all_9.html b/docs/html/search/all_9.html
new file mode 100644
index 0000000..f8abbbe
--- /dev/null
+++ b/docs/html/search/all_9.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_9.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_9.js b/docs/html/search/all_9.js
new file mode 100644
index 0000000..2b3e593
--- /dev/null
+++ b/docs/html/search/all_9.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['random_20generation',['Random generation',['../group__random.html',1,'']]]
+];
diff --git a/docs/html/search/all_a.html b/docs/html/search/all_a.html
new file mode 100644
index 0000000..9601fce
--- /dev/null
+++ b/docs/html/search/all_a.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_a.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/all_a.js b/docs/html/search/all_a.js
new file mode 100644
index 0000000..5161a09
--- /dev/null
+++ b/docs/html/search/all_a.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['symmetric_20ciphers',['Symmetric ciphers',['../group__cipher.html',1,'']]]
+];
diff --git a/docs/html/search/classes_0.html b/docs/html/search/classes_0.html
new file mode 100644
index 0000000..1c3e406
--- /dev/null
+++ b/docs/html/search/classes_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="classes_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/classes_0.js b/docs/html/search/classes_0.js
new file mode 100644
index 0000000..1d78234
--- /dev/null
+++ b/docs/html/search/classes_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['psa_5fgenerate_5fkey_5fextra_5frsa',['psa_generate_key_extra_rsa',['../structpsa__generate__key__extra__rsa.html',1,'']]]
+];
diff --git a/docs/html/search/close.png b/docs/html/search/close.png
new file mode 100644
index 0000000..9342d3d
--- /dev/null
+++ b/docs/html/search/close.png
Binary files differ
diff --git a/docs/html/search/defines_0.html b/docs/html/search/defines_0.html
new file mode 100644
index 0000000..5b25204
--- /dev/null
+++ b/docs/html/search/defines_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="defines_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/defines_0.js b/docs/html/search/defines_0.js
new file mode 100644
index 0000000..d55d6bd
--- /dev/null
+++ b/docs/html/search/defines_0.js
@@ -0,0 +1,12 @@
+var searchData=
+[
+ ['psa_5faead_5fdecrypt_5foutput_5fsize',['PSA_AEAD_DECRYPT_OUTPUT_SIZE',['../crypto__sizes_8h.html#a1d057796166c16eb673ad1997e48a60b',1,'crypto_sizes.h']]],
+ ['psa_5faead_5fencrypt_5foutput_5fsize',['PSA_AEAD_ENCRYPT_OUTPUT_SIZE',['../crypto__sizes_8h.html#a85667d47a7aa6c7b99a80e5273671266',1,'crypto_sizes.h']]],
+ ['psa_5fasymmetric_5fdecrypt_5foutput_5fsize',['PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE',['../crypto__sizes_8h.html#a61a246f3eac41989821d982e56fea6c1',1,'crypto_sizes.h']]],
+ ['psa_5fasymmetric_5fencrypt_5foutput_5fsize',['PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE',['../crypto__sizes_8h.html#a66ba3bd93e5ec52870ccc3848778bad8',1,'crypto_sizes.h']]],
+ ['psa_5fasymmetric_5fsign_5foutput_5fsize',['PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE',['../crypto__sizes_8h.html#a77565b9b4fe6d8730fd2120f4c8378ab',1,'crypto_sizes.h']]],
+ ['psa_5fasymmetric_5fsignature_5fmax_5fsize',['PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE',['../crypto__sizes_8h.html#ad755101764dba14589e5919ee41be7ca',1,'crypto_sizes.h']]],
+ ['psa_5fhash_5fmax_5fsize',['PSA_HASH_MAX_SIZE',['../crypto__sizes_8h.html#a6ce1014efbbc0bcca286ef7f9a72cb29',1,'crypto_sizes.h']]],
+ ['psa_5fmac_5ffinal_5fsize',['PSA_MAC_FINAL_SIZE',['../crypto__sizes_8h.html#aa84c5fb384ac7cb1bfc52adde96588ee',1,'crypto_sizes.h']]],
+ ['psa_5fmac_5fmax_5fsize',['PSA_MAC_MAX_SIZE',['../crypto__sizes_8h.html#a4681cc4f6226883a2160122c562ca682',1,'crypto_sizes.h']]]
+];
diff --git a/docs/html/search/files_0.html b/docs/html/search/files_0.html
new file mode 100644
index 0000000..4f272b8
--- /dev/null
+++ b/docs/html/search/files_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="files_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/files_0.js b/docs/html/search/files_0.js
new file mode 100644
index 0000000..270f99a
--- /dev/null
+++ b/docs/html/search/files_0.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['crypto_2eh',['crypto.h',['../crypto_8h.html',1,'']]],
+ ['crypto_5fsizes_2eh',['crypto_sizes.h',['../crypto__sizes_8h.html',1,'']]]
+];
diff --git a/docs/html/search/functions_0.html b/docs/html/search/functions_0.html
new file mode 100644
index 0000000..4e6d87d
--- /dev/null
+++ b/docs/html/search/functions_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="functions_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/functions_0.js b/docs/html/search/functions_0.js
new file mode 100644
index 0000000..be25492
--- /dev/null
+++ b/docs/html/search/functions_0.js
@@ -0,0 +1,48 @@
+var searchData=
+[
+ ['psa_5faead_5fdecrypt',['psa_aead_decrypt',['../group__aead.html#ga5b88ad2cfbf2e98039858416fa3ebd7a',1,'crypto.h']]],
+ ['psa_5faead_5fencrypt',['psa_aead_encrypt',['../group__aead.html#ga14e4068a3d328515a4884f3037904d54',1,'crypto.h']]],
+ ['psa_5fasymmetric_5fdecrypt',['psa_asymmetric_decrypt',['../group__asymmetric.html#ga3094be979f37aa2865c283167ba907e6',1,'crypto.h']]],
+ ['psa_5fasymmetric_5fencrypt',['psa_asymmetric_encrypt',['../group__asymmetric.html#ga3c0ba402bac217d623dba8320c2240c2',1,'crypto.h']]],
+ ['psa_5fasymmetric_5fsign',['psa_asymmetric_sign',['../group__asymmetric.html#ga48091460d1ead078d93caa3611aec976',1,'crypto.h']]],
+ ['psa_5fasymmetric_5fverify',['psa_asymmetric_verify',['../group__asymmetric.html#gaee3e92946c1c4b3dfa90879e2f7d1321',1,'crypto.h']]],
+ ['psa_5fcipher_5fabort',['psa_cipher_abort',['../group__cipher.html#gaad482cdca2098bca0620596aaa02eaa4',1,'crypto.h']]],
+ ['psa_5fcipher_5fdecrypt_5fsetup',['psa_cipher_decrypt_setup',['../group__cipher.html#ga8ce1efaa648d7e0dd00e878d655d2950',1,'crypto.h']]],
+ ['psa_5fcipher_5fencrypt_5fsetup',['psa_cipher_encrypt_setup',['../group__cipher.html#ga735c9d51b820e1d4cb45f2406ebfae98',1,'crypto.h']]],
+ ['psa_5fcipher_5ffinish',['psa_cipher_finish',['../group__cipher.html#ga1dcb58b8befe23f8a4d7a1d49c99249b',1,'crypto.h']]],
+ ['psa_5fcipher_5fgenerate_5fiv',['psa_cipher_generate_iv',['../group__cipher.html#ga44857cf5e0c3d134a3c560f8ff5b50aa',1,'crypto.h']]],
+ ['psa_5fcipher_5fset_5fiv',['psa_cipher_set_iv',['../group__cipher.html#ga1359b2101f31637496ce7cc36c6e3d42',1,'crypto.h']]],
+ ['psa_5fcipher_5fupdate',['psa_cipher_update',['../group__cipher.html#gafd0caea99cf1052527e4089d37f5ab91',1,'crypto.h']]],
+ ['psa_5fcrypto_5finit',['psa_crypto_init',['../group__basic.html#ga2de150803fc2f7dc6101d5af7e921dd9',1,'crypto.h']]],
+ ['psa_5fdestroy_5fkey',['psa_destroy_key',['../group__key__management.html#ga2e9a60a9525ce6b3082a72df2080f0c5',1,'crypto.h']]],
+ ['psa_5fexport_5fkey',['psa_export_key',['../group__key__management.html#gaa67bc459b20028b268f3d75a05afe022',1,'crypto.h']]],
+ ['psa_5fexport_5fpublic_5fkey',['psa_export_public_key',['../group__key__management.html#ga7355b38f8eb9330db2786604f4a83a3b',1,'crypto.h']]],
+ ['psa_5fgenerate_5fkey',['psa_generate_key',['../group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10',1,'crypto.h']]],
+ ['psa_5fgenerate_5frandom',['psa_generate_random',['../group__random.html#ga1985eae417dfbccedf50d5fff54ea8c5',1,'crypto.h']]],
+ ['psa_5fgenerator_5fabort',['psa_generator_abort',['../group__generators.html#ga563ca64537d90368899286b36d8cf7f3',1,'crypto.h']]],
+ ['psa_5fgenerator_5fimport_5fkey',['psa_generator_import_key',['../group__generators.html#ga06c1ba3d989827d909b4b01ffe983beb',1,'crypto.h']]],
+ ['psa_5fgenerator_5fread',['psa_generator_read',['../group__generators.html#gab5712ad29b78c2b170e64cc5bcfc1bce',1,'crypto.h']]],
+ ['psa_5fget_5fgenerator_5fcapacity',['psa_get_generator_capacity',['../group__generators.html#ga7453491e3b440193be2c5dccc2040fd2',1,'crypto.h']]],
+ ['psa_5fget_5fkey_5finformation',['psa_get_key_information',['../group__key__management.html#gaf105167657ab1d484cb4a51f93413717',1,'crypto.h']]],
+ ['psa_5fget_5fkey_5flifetime',['psa_get_key_lifetime',['../group__persistence.html#gaf0daaa1dba14dc324ca83dfe1495a5e2',1,'crypto.h']]],
+ ['psa_5fget_5fkey_5fpolicy',['psa_get_key_policy',['../group__policy.html#ga613f28712124f9149bd640614376ab5a',1,'crypto.h']]],
+ ['psa_5fhash_5fabort',['psa_hash_abort',['../group__hash.html#gab0b4d5f9912a615559497a467b532928',1,'crypto.h']]],
+ ['psa_5fhash_5ffinish',['psa_hash_finish',['../group__hash.html#ga4795fd06a0067b0adcd92e9627b8c97e',1,'crypto.h']]],
+ ['psa_5fhash_5fsetup',['psa_hash_setup',['../group__hash.html#ga8d72896cf70fc4d514c5c6b978912515',1,'crypto.h']]],
+ ['psa_5fhash_5fupdate',['psa_hash_update',['../group__hash.html#ga65b16ef97d7f650899b7db4b7d1112ff',1,'crypto.h']]],
+ ['psa_5fhash_5fverify',['psa_hash_verify',['../group__hash.html#ga7be923c5700c9c70ef77ee9b76d1a5c0',1,'crypto.h']]],
+ ['psa_5fimport_5fkey',['psa_import_key',['../group__key__management.html#gace37363530e2525a2562f07ceec8efb5',1,'crypto.h']]],
+ ['psa_5fkey_5fderivation',['psa_key_derivation',['../group__derivation.html#ga1b6429f443a45e5f3209043abbbe8315',1,'crypto.h']]],
+ ['psa_5fkey_5fpolicy_5fget_5falgorithm',['psa_key_policy_get_algorithm',['../group__policy.html#gaadf16b89ace53e1d2cb5bcb0aef24c86',1,'crypto.h']]],
+ ['psa_5fkey_5fpolicy_5fget_5fusage',['psa_key_policy_get_usage',['../group__policy.html#ga7746662b7503e484774d0ecb5d8ac2ab',1,'crypto.h']]],
+ ['psa_5fkey_5fpolicy_5finit',['psa_key_policy_init',['../group__policy.html#gad49eb85e3fcbe70f763f511ac83e762e',1,'crypto.h']]],
+ ['psa_5fkey_5fpolicy_5fset_5fusage',['psa_key_policy_set_usage',['../group__policy.html#gac16792fd6d375a5f76d372090df40607',1,'crypto.h']]],
+ ['psa_5fmac_5fabort',['psa_mac_abort',['../group__MAC.html#gacd8dd54855ba1bc0a03f104f252884fd',1,'crypto.h']]],
+ ['psa_5fmac_5fsign_5ffinish',['psa_mac_sign_finish',['../group__MAC.html#gac22bc0125580c96724a09226cfbc97f2',1,'crypto.h']]],
+ ['psa_5fmac_5fsign_5fsetup',['psa_mac_sign_setup',['../group__MAC.html#ga68ac2ad3253e9e27fcfbc788a4df8177',1,'crypto.h']]],
+ ['psa_5fmac_5fupdate',['psa_mac_update',['../group__MAC.html#ga5560af371497babefe03c9da4e8a1c05',1,'crypto.h']]],
+ ['psa_5fmac_5fverify_5ffinish',['psa_mac_verify_finish',['../group__MAC.html#gac92b2930d6728e1be4d011c05d485822',1,'crypto.h']]],
+ ['psa_5fmac_5fverify_5fsetup',['psa_mac_verify_setup',['../group__MAC.html#gac7d1c3d075ce1604a54cbbc9933fa39d',1,'crypto.h']]],
+ ['psa_5fset_5fkey_5flifetime',['psa_set_key_lifetime',['../group__persistence.html#ga1bd1ee6d00ebd9962fc6ad72cbd22ef8',1,'crypto.h']]],
+ ['psa_5fset_5fkey_5fpolicy',['psa_set_key_policy',['../group__policy.html#gad7faa7e64aa771f7441c44ceff21af19',1,'crypto.h']]]
+];
diff --git a/docs/html/search/groups_0.html b/docs/html/search/groups_0.html
new file mode 100644
index 0000000..1ede28d
--- /dev/null
+++ b/docs/html/search/groups_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/groups_0.js b/docs/html/search/groups_0.js
new file mode 100644
index 0000000..9e9cdcb
--- /dev/null
+++ b/docs/html/search/groups_0.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['authenticated_20encryption_20with_20associated_20data_20_28aead_29',['Authenticated encryption with associated data (AEAD)',['../group__aead.html',1,'']]],
+ ['asymmetric_20cryptography',['Asymmetric cryptography',['../group__asymmetric.html',1,'']]]
+];
diff --git a/docs/html/search/groups_1.html b/docs/html/search/groups_1.html
new file mode 100644
index 0000000..3c05216
--- /dev/null
+++ b/docs/html/search/groups_1.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/groups_1.js b/docs/html/search/groups_1.js
new file mode 100644
index 0000000..d379fe2
--- /dev/null
+++ b/docs/html/search/groups_1.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['basic_20definitions',['Basic definitions',['../group__basic.html',1,'']]]
+];
diff --git a/docs/html/search/groups_2.html b/docs/html/search/groups_2.html
new file mode 100644
index 0000000..7191495
--- /dev/null
+++ b/docs/html/search/groups_2.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/groups_2.js b/docs/html/search/groups_2.js
new file mode 100644
index 0000000..bb51584
--- /dev/null
+++ b/docs/html/search/groups_2.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['generators',['Generators',['../group__generators.html',1,'']]]
+];
diff --git a/docs/html/search/groups_3.html b/docs/html/search/groups_3.html
new file mode 100644
index 0000000..3af27ea
--- /dev/null
+++ b/docs/html/search/groups_3.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_3.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/groups_3.js b/docs/html/search/groups_3.js
new file mode 100644
index 0000000..f48be25
--- /dev/null
+++ b/docs/html/search/groups_3.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['implementation_2dspecific_20definitions',['Implementation-specific definitions',['../group__platform.html',1,'']]]
+];
diff --git a/docs/html/search/groups_4.html b/docs/html/search/groups_4.html
new file mode 100644
index 0000000..e7abc74
--- /dev/null
+++ b/docs/html/search/groups_4.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_4.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/groups_4.js b/docs/html/search/groups_4.js
new file mode 100644
index 0000000..93b7ff0
--- /dev/null
+++ b/docs/html/search/groups_4.js
@@ -0,0 +1,8 @@
+var searchData=
+[
+ ['key_20and_20algorithm_20types',['Key and algorithm types',['../group__crypto__types.html',1,'']]],
+ ['key_20derivation',['Key derivation',['../group__derivation.html',1,'']]],
+ ['key_20management',['Key management',['../group__key__management.html',1,'']]],
+ ['key_20lifetime',['Key lifetime',['../group__persistence.html',1,'']]],
+ ['key_20policies',['Key policies',['../group__policy.html',1,'']]]
+];
diff --git a/docs/html/search/groups_5.html b/docs/html/search/groups_5.html
new file mode 100644
index 0000000..edc563e
--- /dev/null
+++ b/docs/html/search/groups_5.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_5.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/groups_5.js b/docs/html/search/groups_5.js
new file mode 100644
index 0000000..6efdddb
--- /dev/null
+++ b/docs/html/search/groups_5.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+ ['message_20digests',['Message digests',['../group__hash.html',1,'']]],
+ ['message_20authentication_20codes',['Message authentication codes',['../group__MAC.html',1,'']]]
+];
diff --git a/docs/html/search/groups_6.html b/docs/html/search/groups_6.html
new file mode 100644
index 0000000..176b61a
--- /dev/null
+++ b/docs/html/search/groups_6.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_6.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/groups_6.js b/docs/html/search/groups_6.js
new file mode 100644
index 0000000..2b3e593
--- /dev/null
+++ b/docs/html/search/groups_6.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['random_20generation',['Random generation',['../group__random.html',1,'']]]
+];
diff --git a/docs/html/search/groups_7.html b/docs/html/search/groups_7.html
new file mode 100644
index 0000000..0b8fa02
--- /dev/null
+++ b/docs/html/search/groups_7.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="groups_7.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/groups_7.js b/docs/html/search/groups_7.js
new file mode 100644
index 0000000..5161a09
--- /dev/null
+++ b/docs/html/search/groups_7.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['symmetric_20ciphers',['Symmetric ciphers',['../group__cipher.html',1,'']]]
+];
diff --git a/docs/html/search/mag_sel.png b/docs/html/search/mag_sel.png
new file mode 100644
index 0000000..81f6040
--- /dev/null
+++ b/docs/html/search/mag_sel.png
Binary files differ
diff --git a/docs/html/search/nomatches.html b/docs/html/search/nomatches.html
new file mode 100644
index 0000000..b1ded27
--- /dev/null
+++ b/docs/html/search/nomatches.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="NoMatches">No Matches</div>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/search.css b/docs/html/search/search.css
new file mode 100644
index 0000000..3cf9df9
--- /dev/null
+++ b/docs/html/search/search.css
@@ -0,0 +1,271 @@
+/*---------------- Search Box */
+
+#FSearchBox {
+ float: left;
+}
+
+#MSearchBox {
+ white-space : nowrap;
+ float: none;
+ margin-top: 8px;
+ right: 0px;
+ width: 170px;
+ height: 24px;
+ z-index: 102;
+}
+
+#MSearchBox .left
+{
+ display:block;
+ position:absolute;
+ left:10px;
+ width:20px;
+ height:19px;
+ background:url('search_l.png') no-repeat;
+ background-position:right;
+}
+
+#MSearchSelect {
+ display:block;
+ position:absolute;
+ width:20px;
+ height:19px;
+}
+
+.left #MSearchSelect {
+ left:4px;
+}
+
+.right #MSearchSelect {
+ right:5px;
+}
+
+#MSearchField {
+ display:block;
+ position:absolute;
+ height:19px;
+ background:url('search_m.png') repeat-x;
+ border:none;
+ width:115px;
+ margin-left:20px;
+ padding-left:4px;
+ color: #909090;
+ outline: none;
+ font: 9pt Arial, Verdana, sans-serif;
+ -webkit-border-radius: 0px;
+}
+
+#FSearchBox #MSearchField {
+ margin-left:15px;
+}
+
+#MSearchBox .right {
+ display:block;
+ position:absolute;
+ right:10px;
+ top:8px;
+ width:20px;
+ height:19px;
+ background:url('search_r.png') no-repeat;
+ background-position:left;
+}
+
+#MSearchClose {
+ display: none;
+ position: absolute;
+ top: 4px;
+ background : none;
+ border: none;
+ margin: 0px 4px 0px 0px;
+ padding: 0px 0px;
+ outline: none;
+}
+
+.left #MSearchClose {
+ left: 6px;
+}
+
+.right #MSearchClose {
+ right: 2px;
+}
+
+.MSearchBoxActive #MSearchField {
+ color: #000000;
+}
+
+/*---------------- Search filter selection */
+
+#MSearchSelectWindow {
+ display: none;
+ position: absolute;
+ left: 0; top: 0;
+ border: 1px solid #90A5CE;
+ background-color: #F9FAFC;
+ z-index: 10001;
+ padding-top: 4px;
+ padding-bottom: 4px;
+ -moz-border-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+ -webkit-border-top-right-radius: 4px;
+ -webkit-border-bottom-left-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+.SelectItem {
+ font: 8pt Arial, Verdana, sans-serif;
+ padding-left: 2px;
+ padding-right: 12px;
+ border: 0px;
+}
+
+span.SelectionMark {
+ margin-right: 4px;
+ font-family: monospace;
+ outline-style: none;
+ text-decoration: none;
+}
+
+a.SelectItem {
+ display: block;
+ outline-style: none;
+ color: #000000;
+ text-decoration: none;
+ padding-left: 6px;
+ padding-right: 12px;
+}
+
+a.SelectItem:focus,
+a.SelectItem:active {
+ color: #000000;
+ outline-style: none;
+ text-decoration: none;
+}
+
+a.SelectItem:hover {
+ color: #FFFFFF;
+ background-color: #3D578C;
+ outline-style: none;
+ text-decoration: none;
+ cursor: pointer;
+ display: block;
+}
+
+/*---------------- Search results window */
+
+iframe#MSearchResults {
+ width: 60ex;
+ height: 15em;
+}
+
+#MSearchResultsWindow {
+ display: none;
+ position: absolute;
+ left: 0; top: 0;
+ border: 1px solid #000;
+ background-color: #EEF1F7;
+ z-index:10000;
+}
+
+/* ----------------------------------- */
+
+
+#SRIndex {
+ clear:both;
+ padding-bottom: 15px;
+}
+
+.SREntry {
+ font-size: 10pt;
+ padding-left: 1ex;
+}
+
+.SRPage .SREntry {
+ font-size: 8pt;
+ padding: 1px 5px;
+}
+
+body.SRPage {
+ margin: 5px 2px;
+}
+
+.SRChildren {
+ padding-left: 3ex; padding-bottom: .5em
+}
+
+.SRPage .SRChildren {
+ display: none;
+}
+
+.SRSymbol {
+ font-weight: bold;
+ color: #425E97;
+ font-family: Arial, Verdana, sans-serif;
+ text-decoration: none;
+ outline: none;
+}
+
+a.SRScope {
+ display: block;
+ color: #425E97;
+ font-family: Arial, Verdana, sans-serif;
+ text-decoration: none;
+ outline: none;
+}
+
+a.SRSymbol:focus, a.SRSymbol:active,
+a.SRScope:focus, a.SRScope:active {
+ text-decoration: underline;
+}
+
+span.SRScope {
+ padding-left: 4px;
+}
+
+.SRPage .SRStatus {
+ padding: 2px 5px;
+ font-size: 8pt;
+ font-style: italic;
+}
+
+.SRResult {
+ display: none;
+}
+
+DIV.searchresults {
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+/*---------------- External search page results */
+
+.searchresult {
+ background-color: #F0F3F8;
+}
+
+.pages b {
+ color: white;
+ padding: 5px 5px 3px 5px;
+ background-image: url("../tab_a.png");
+ background-repeat: repeat-x;
+ text-shadow: 0 1px 1px #000000;
+}
+
+.pages {
+ line-height: 17px;
+ margin-left: 4px;
+ text-decoration: none;
+}
+
+.hl {
+ font-weight: bold;
+}
+
+#searchresults {
+ margin-bottom: 20px;
+}
+
+.searchpages {
+ margin-top: 10px;
+}
+
diff --git a/docs/html/search/search.js b/docs/html/search/search.js
new file mode 100644
index 0000000..dedce3b
--- /dev/null
+++ b/docs/html/search/search.js
@@ -0,0 +1,791 @@
+function convertToId(search)
+{
+ var result = '';
+ for (i=0;i<search.length;i++)
+ {
+ var c = search.charAt(i);
+ var cn = c.charCodeAt(0);
+ if (c.match(/[a-z0-9\u0080-\uFFFF]/))
+ {
+ result+=c;
+ }
+ else if (cn<16)
+ {
+ result+="_0"+cn.toString(16);
+ }
+ else
+ {
+ result+="_"+cn.toString(16);
+ }
+ }
+ return result;
+}
+
+function getXPos(item)
+{
+ var x = 0;
+ if (item.offsetWidth)
+ {
+ while (item && item!=document.body)
+ {
+ x += item.offsetLeft;
+ item = item.offsetParent;
+ }
+ }
+ return x;
+}
+
+function getYPos(item)
+{
+ var y = 0;
+ if (item.offsetWidth)
+ {
+ while (item && item!=document.body)
+ {
+ y += item.offsetTop;
+ item = item.offsetParent;
+ }
+ }
+ return y;
+}
+
+/* A class handling everything associated with the search panel.
+
+ Parameters:
+ name - The name of the global variable that will be
+ storing this instance. Is needed to be able to set timeouts.
+ resultPath - path to use for external files
+*/
+function SearchBox(name, resultsPath, inFrame, label)
+{
+ if (!name || !resultsPath) { alert("Missing parameters to SearchBox."); }
+
+ // ---------- Instance variables
+ this.name = name;
+ this.resultsPath = resultsPath;
+ this.keyTimeout = 0;
+ this.keyTimeoutLength = 500;
+ this.closeSelectionTimeout = 300;
+ this.lastSearchValue = "";
+ this.lastResultsPage = "";
+ this.hideTimeout = 0;
+ this.searchIndex = 0;
+ this.searchActive = false;
+ this.insideFrame = inFrame;
+ this.searchLabel = label;
+
+ // ----------- DOM Elements
+
+ this.DOMSearchField = function()
+ { return document.getElementById("MSearchField"); }
+
+ this.DOMSearchSelect = function()
+ { return document.getElementById("MSearchSelect"); }
+
+ this.DOMSearchSelectWindow = function()
+ { return document.getElementById("MSearchSelectWindow"); }
+
+ this.DOMPopupSearchResults = function()
+ { return document.getElementById("MSearchResults"); }
+
+ this.DOMPopupSearchResultsWindow = function()
+ { return document.getElementById("MSearchResultsWindow"); }
+
+ this.DOMSearchClose = function()
+ { return document.getElementById("MSearchClose"); }
+
+ this.DOMSearchBox = function()
+ { return document.getElementById("MSearchBox"); }
+
+ // ------------ Event Handlers
+
+ // Called when focus is added or removed from the search field.
+ this.OnSearchFieldFocus = function(isActive)
+ {
+ this.Activate(isActive);
+ }
+
+ this.OnSearchSelectShow = function()
+ {
+ var searchSelectWindow = this.DOMSearchSelectWindow();
+ var searchField = this.DOMSearchSelect();
+
+ if (this.insideFrame)
+ {
+ var left = getXPos(searchField);
+ var top = getYPos(searchField);
+ left += searchField.offsetWidth + 6;
+ top += searchField.offsetHeight;
+
+ // show search selection popup
+ searchSelectWindow.style.display='block';
+ left -= searchSelectWindow.offsetWidth;
+ searchSelectWindow.style.left = left + 'px';
+ searchSelectWindow.style.top = top + 'px';
+ }
+ else
+ {
+ var left = getXPos(searchField);
+ var top = getYPos(searchField);
+ top += searchField.offsetHeight;
+
+ // show search selection popup
+ searchSelectWindow.style.display='block';
+ searchSelectWindow.style.left = left + 'px';
+ searchSelectWindow.style.top = top + 'px';
+ }
+
+ // stop selection hide timer
+ if (this.hideTimeout)
+ {
+ clearTimeout(this.hideTimeout);
+ this.hideTimeout=0;
+ }
+ return false; // to avoid "image drag" default event
+ }
+
+ this.OnSearchSelectHide = function()
+ {
+ this.hideTimeout = setTimeout(this.name +".CloseSelectionWindow()",
+ this.closeSelectionTimeout);
+ }
+
+ // Called when the content of the search field is changed.
+ this.OnSearchFieldChange = function(evt)
+ {
+ if (this.keyTimeout) // kill running timer
+ {
+ clearTimeout(this.keyTimeout);
+ this.keyTimeout = 0;
+ }
+
+ var e = (evt) ? evt : window.event; // for IE
+ if (e.keyCode==40 || e.keyCode==13)
+ {
+ if (e.shiftKey==1)
+ {
+ this.OnSearchSelectShow();
+ var win=this.DOMSearchSelectWindow();
+ for (i=0;i<win.childNodes.length;i++)
+ {
+ var child = win.childNodes[i]; // get span within a
+ if (child.className=='SelectItem')
+ {
+ child.focus();
+ return;
+ }
+ }
+ return;
+ }
+ else if (window.frames.MSearchResults.searchResults)
+ {
+ var elem = window.frames.MSearchResults.searchResults.NavNext(0);
+ if (elem) elem.focus();
+ }
+ }
+ else if (e.keyCode==27) // Escape out of the search field
+ {
+ this.DOMSearchField().blur();
+ this.DOMPopupSearchResultsWindow().style.display = 'none';
+ this.DOMSearchClose().style.display = 'none';
+ this.lastSearchValue = '';
+ this.Activate(false);
+ return;
+ }
+
+ // strip whitespaces
+ var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
+
+ if (searchValue != this.lastSearchValue) // search value has changed
+ {
+ if (searchValue != "") // non-empty search
+ {
+ // set timer for search update
+ this.keyTimeout = setTimeout(this.name + '.Search()',
+ this.keyTimeoutLength);
+ }
+ else // empty search field
+ {
+ this.DOMPopupSearchResultsWindow().style.display = 'none';
+ this.DOMSearchClose().style.display = 'none';
+ this.lastSearchValue = '';
+ }
+ }
+ }
+
+ this.SelectItemCount = function(id)
+ {
+ var count=0;
+ var win=this.DOMSearchSelectWindow();
+ for (i=0;i<win.childNodes.length;i++)
+ {
+ var child = win.childNodes[i]; // get span within a
+ if (child.className=='SelectItem')
+ {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ this.SelectItemSet = function(id)
+ {
+ var i,j=0;
+ var win=this.DOMSearchSelectWindow();
+ for (i=0;i<win.childNodes.length;i++)
+ {
+ var child = win.childNodes[i]; // get span within a
+ if (child.className=='SelectItem')
+ {
+ var node = child.firstChild;
+ if (j==id)
+ {
+ node.innerHTML='•';
+ }
+ else
+ {
+ node.innerHTML=' ';
+ }
+ j++;
+ }
+ }
+ }
+
+ // Called when an search filter selection is made.
+ // set item with index id as the active item
+ this.OnSelectItem = function(id)
+ {
+ this.searchIndex = id;
+ this.SelectItemSet(id);
+ var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
+ if (searchValue!="" && this.searchActive) // something was found -> do a search
+ {
+ this.Search();
+ }
+ }
+
+ this.OnSearchSelectKey = function(evt)
+ {
+ var e = (evt) ? evt : window.event; // for IE
+ if (e.keyCode==40 && this.searchIndex<this.SelectItemCount()) // Down
+ {
+ this.searchIndex++;
+ this.OnSelectItem(this.searchIndex);
+ }
+ else if (e.keyCode==38 && this.searchIndex>0) // Up
+ {
+ this.searchIndex--;
+ this.OnSelectItem(this.searchIndex);
+ }
+ else if (e.keyCode==13 || e.keyCode==27)
+ {
+ this.OnSelectItem(this.searchIndex);
+ this.CloseSelectionWindow();
+ this.DOMSearchField().focus();
+ }
+ return false;
+ }
+
+ // --------- Actions
+
+ // Closes the results window.
+ this.CloseResultsWindow = function()
+ {
+ this.DOMPopupSearchResultsWindow().style.display = 'none';
+ this.DOMSearchClose().style.display = 'none';
+ this.Activate(false);
+ }
+
+ this.CloseSelectionWindow = function()
+ {
+ this.DOMSearchSelectWindow().style.display = 'none';
+ }
+
+ // Performs a search.
+ this.Search = function()
+ {
+ this.keyTimeout = 0;
+
+ // strip leading whitespace
+ var searchValue = this.DOMSearchField().value.replace(/^ +/, "");
+
+ var code = searchValue.toLowerCase().charCodeAt(0);
+ var idxChar = searchValue.substr(0, 1).toLowerCase();
+ if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) // surrogate pair
+ {
+ idxChar = searchValue.substr(0, 2);
+ }
+
+ var resultsPage;
+ var resultsPageWithSearch;
+ var hasResultsPage;
+
+ var idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar);
+ if (idx!=-1)
+ {
+ var hexCode=idx.toString(16);
+ resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html';
+ resultsPageWithSearch = resultsPage+'?'+escape(searchValue);
+ hasResultsPage = true;
+ }
+ else // nothing available for this search term
+ {
+ resultsPage = this.resultsPath + '/nomatches.html';
+ resultsPageWithSearch = resultsPage;
+ hasResultsPage = false;
+ }
+
+ window.frames.MSearchResults.location = resultsPageWithSearch;
+ var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();
+
+ if (domPopupSearchResultsWindow.style.display!='block')
+ {
+ var domSearchBox = this.DOMSearchBox();
+ this.DOMSearchClose().style.display = 'inline';
+ if (this.insideFrame)
+ {
+ var domPopupSearchResults = this.DOMPopupSearchResults();
+ domPopupSearchResultsWindow.style.position = 'relative';
+ domPopupSearchResultsWindow.style.display = 'block';
+ var width = document.body.clientWidth - 8; // the -8 is for IE :-(
+ domPopupSearchResultsWindow.style.width = width + 'px';
+ domPopupSearchResults.style.width = width + 'px';
+ }
+ else
+ {
+ var domPopupSearchResults = this.DOMPopupSearchResults();
+ var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth;
+ var top = getYPos(domSearchBox) + 20; // domSearchBox.offsetHeight + 1;
+ domPopupSearchResultsWindow.style.display = 'block';
+ left -= domPopupSearchResults.offsetWidth;
+ domPopupSearchResultsWindow.style.top = top + 'px';
+ domPopupSearchResultsWindow.style.left = left + 'px';
+ }
+ }
+
+ this.lastSearchValue = searchValue;
+ this.lastResultsPage = resultsPage;
+ }
+
+ // -------- Activation Functions
+
+ // Activates or deactivates the search panel, resetting things to
+ // their default values if necessary.
+ this.Activate = function(isActive)
+ {
+ if (isActive || // open it
+ this.DOMPopupSearchResultsWindow().style.display == 'block'
+ )
+ {
+ this.DOMSearchBox().className = 'MSearchBoxActive';
+
+ var searchField = this.DOMSearchField();
+
+ if (searchField.value == this.searchLabel) // clear "Search" term upon entry
+ {
+ searchField.value = '';
+ this.searchActive = true;
+ }
+ }
+ else if (!isActive) // directly remove the panel
+ {
+ this.DOMSearchBox().className = 'MSearchBoxInactive';
+ this.DOMSearchField().value = this.searchLabel;
+ this.searchActive = false;
+ this.lastSearchValue = ''
+ this.lastResultsPage = '';
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+// The class that handles everything on the search results page.
+function SearchResults(name)
+{
+ // The number of matches from the last run of <Search()>.
+ this.lastMatchCount = 0;
+ this.lastKey = 0;
+ this.repeatOn = false;
+
+ // Toggles the visibility of the passed element ID.
+ this.FindChildElement = function(id)
+ {
+ var parentElement = document.getElementById(id);
+ var element = parentElement.firstChild;
+
+ while (element && element!=parentElement)
+ {
+ if (element.nodeName == 'DIV' && element.className == 'SRChildren')
+ {
+ return element;
+ }
+
+ if (element.nodeName == 'DIV' && element.hasChildNodes())
+ {
+ element = element.firstChild;
+ }
+ else if (element.nextSibling)
+ {
+ element = element.nextSibling;
+ }
+ else
+ {
+ do
+ {
+ element = element.parentNode;
+ }
+ while (element && element!=parentElement && !element.nextSibling);
+
+ if (element && element!=parentElement)
+ {
+ element = element.nextSibling;
+ }
+ }
+ }
+ }
+
+ this.Toggle = function(id)
+ {
+ var element = this.FindChildElement(id);
+ if (element)
+ {
+ if (element.style.display == 'block')
+ {
+ element.style.display = 'none';
+ }
+ else
+ {
+ element.style.display = 'block';
+ }
+ }
+ }
+
+ // Searches for the passed string. If there is no parameter,
+ // it takes it from the URL query.
+ //
+ // Always returns true, since other documents may try to call it
+ // and that may or may not be possible.
+ this.Search = function(search)
+ {
+ if (!search) // get search word from URL
+ {
+ search = window.location.search;
+ search = search.substring(1); // Remove the leading '?'
+ search = unescape(search);
+ }
+
+ search = search.replace(/^ +/, ""); // strip leading spaces
+ search = search.replace(/ +$/, ""); // strip trailing spaces
+ search = search.toLowerCase();
+ search = convertToId(search);
+
+ var resultRows = document.getElementsByTagName("div");
+ var matches = 0;
+
+ var i = 0;
+ while (i < resultRows.length)
+ {
+ var row = resultRows.item(i);
+ if (row.className == "SRResult")
+ {
+ var rowMatchName = row.id.toLowerCase();
+ rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_'
+
+ if (search.length<=rowMatchName.length &&
+ rowMatchName.substr(0, search.length)==search)
+ {
+ row.style.display = 'block';
+ matches++;
+ }
+ else
+ {
+ row.style.display = 'none';
+ }
+ }
+ i++;
+ }
+ document.getElementById("Searching").style.display='none';
+ if (matches == 0) // no results
+ {
+ document.getElementById("NoMatches").style.display='block';
+ }
+ else // at least one result
+ {
+ document.getElementById("NoMatches").style.display='none';
+ }
+ this.lastMatchCount = matches;
+ return true;
+ }
+
+ // return the first item with index index or higher that is visible
+ this.NavNext = function(index)
+ {
+ var focusItem;
+ while (1)
+ {
+ var focusName = 'Item'+index;
+ focusItem = document.getElementById(focusName);
+ if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
+ {
+ break;
+ }
+ else if (!focusItem) // last element
+ {
+ break;
+ }
+ focusItem=null;
+ index++;
+ }
+ return focusItem;
+ }
+
+ this.NavPrev = function(index)
+ {
+ var focusItem;
+ while (1)
+ {
+ var focusName = 'Item'+index;
+ focusItem = document.getElementById(focusName);
+ if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
+ {
+ break;
+ }
+ else if (!focusItem) // last element
+ {
+ break;
+ }
+ focusItem=null;
+ index--;
+ }
+ return focusItem;
+ }
+
+ this.ProcessKeys = function(e)
+ {
+ if (e.type == "keydown")
+ {
+ this.repeatOn = false;
+ this.lastKey = e.keyCode;
+ }
+ else if (e.type == "keypress")
+ {
+ if (!this.repeatOn)
+ {
+ if (this.lastKey) this.repeatOn = true;
+ return false; // ignore first keypress after keydown
+ }
+ }
+ else if (e.type == "keyup")
+ {
+ this.lastKey = 0;
+ this.repeatOn = false;
+ }
+ return this.lastKey!=0;
+ }
+
+ this.Nav = function(evt,itemIndex)
+ {
+ var e = (evt) ? evt : window.event; // for IE
+ if (e.keyCode==13) return true;
+ if (!this.ProcessKeys(e)) return false;
+
+ if (this.lastKey==38) // Up
+ {
+ var newIndex = itemIndex-1;
+ var focusItem = this.NavPrev(newIndex);
+ if (focusItem)
+ {
+ var child = this.FindChildElement(focusItem.parentNode.parentNode.id);
+ if (child && child.style.display == 'block') // children visible
+ {
+ var n=0;
+ var tmpElem;
+ while (1) // search for last child
+ {
+ tmpElem = document.getElementById('Item'+newIndex+'_c'+n);
+ if (tmpElem)
+ {
+ focusItem = tmpElem;
+ }
+ else // found it!
+ {
+ break;
+ }
+ n++;
+ }
+ }
+ }
+ if (focusItem)
+ {
+ focusItem.focus();
+ }
+ else // return focus to search field
+ {
+ parent.document.getElementById("MSearchField").focus();
+ }
+ }
+ else if (this.lastKey==40) // Down
+ {
+ var newIndex = itemIndex+1;
+ var focusItem;
+ var item = document.getElementById('Item'+itemIndex);
+ var elem = this.FindChildElement(item.parentNode.parentNode.id);
+ if (elem && elem.style.display == 'block') // children visible
+ {
+ focusItem = document.getElementById('Item'+itemIndex+'_c0');
+ }
+ if (!focusItem) focusItem = this.NavNext(newIndex);
+ if (focusItem) focusItem.focus();
+ }
+ else if (this.lastKey==39) // Right
+ {
+ var item = document.getElementById('Item'+itemIndex);
+ var elem = this.FindChildElement(item.parentNode.parentNode.id);
+ if (elem) elem.style.display = 'block';
+ }
+ else if (this.lastKey==37) // Left
+ {
+ var item = document.getElementById('Item'+itemIndex);
+ var elem = this.FindChildElement(item.parentNode.parentNode.id);
+ if (elem) elem.style.display = 'none';
+ }
+ else if (this.lastKey==27) // Escape
+ {
+ parent.searchBox.CloseResultsWindow();
+ parent.document.getElementById("MSearchField").focus();
+ }
+ else if (this.lastKey==13) // Enter
+ {
+ return true;
+ }
+ return false;
+ }
+
+ this.NavChild = function(evt,itemIndex,childIndex)
+ {
+ var e = (evt) ? evt : window.event; // for IE
+ if (e.keyCode==13) return true;
+ if (!this.ProcessKeys(e)) return false;
+
+ if (this.lastKey==38) // Up
+ {
+ if (childIndex>0)
+ {
+ var newIndex = childIndex-1;
+ document.getElementById('Item'+itemIndex+'_c'+newIndex).focus();
+ }
+ else // already at first child, jump to parent
+ {
+ document.getElementById('Item'+itemIndex).focus();
+ }
+ }
+ else if (this.lastKey==40) // Down
+ {
+ var newIndex = childIndex+1;
+ var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex);
+ if (!elem) // last child, jump to parent next parent
+ {
+ elem = this.NavNext(itemIndex+1);
+ }
+ if (elem)
+ {
+ elem.focus();
+ }
+ }
+ else if (this.lastKey==27) // Escape
+ {
+ parent.searchBox.CloseResultsWindow();
+ parent.document.getElementById("MSearchField").focus();
+ }
+ else if (this.lastKey==13) // Enter
+ {
+ return true;
+ }
+ return false;
+ }
+}
+
+function setKeyActions(elem,action)
+{
+ elem.setAttribute('onkeydown',action);
+ elem.setAttribute('onkeypress',action);
+ elem.setAttribute('onkeyup',action);
+}
+
+function setClassAttr(elem,attr)
+{
+ elem.setAttribute('class',attr);
+ elem.setAttribute('className',attr);
+}
+
+function createResults()
+{
+ var results = document.getElementById("SRResults");
+ for (var e=0; e<searchData.length; e++)
+ {
+ var id = searchData[e][0];
+ var srResult = document.createElement('div');
+ srResult.setAttribute('id','SR_'+id);
+ setClassAttr(srResult,'SRResult');
+ var srEntry = document.createElement('div');
+ setClassAttr(srEntry,'SREntry');
+ var srLink = document.createElement('a');
+ srLink.setAttribute('id','Item'+e);
+ setKeyActions(srLink,'return searchResults.Nav(event,'+e+')');
+ setClassAttr(srLink,'SRSymbol');
+ srLink.innerHTML = searchData[e][1][0];
+ srEntry.appendChild(srLink);
+ if (searchData[e][1].length==2) // single result
+ {
+ srLink.setAttribute('href',searchData[e][1][1][0]);
+ if (searchData[e][1][1][1])
+ {
+ srLink.setAttribute('target','_parent');
+ }
+ var srScope = document.createElement('span');
+ setClassAttr(srScope,'SRScope');
+ srScope.innerHTML = searchData[e][1][1][2];
+ srEntry.appendChild(srScope);
+ }
+ else // multiple results
+ {
+ srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")');
+ var srChildren = document.createElement('div');
+ setClassAttr(srChildren,'SRChildren');
+ for (var c=0; c<searchData[e][1].length-1; c++)
+ {
+ var srChild = document.createElement('a');
+ srChild.setAttribute('id','Item'+e+'_c'+c);
+ setKeyActions(srChild,'return searchResults.NavChild(event,'+e+','+c+')');
+ setClassAttr(srChild,'SRScope');
+ srChild.setAttribute('href',searchData[e][1][c+1][0]);
+ if (searchData[e][1][c+1][1])
+ {
+ srChild.setAttribute('target','_parent');
+ }
+ srChild.innerHTML = searchData[e][1][c+1][2];
+ srChildren.appendChild(srChild);
+ }
+ srEntry.appendChild(srChildren);
+ }
+ srResult.appendChild(srEntry);
+ results.appendChild(srResult);
+ }
+}
+
+function init_search()
+{
+ var results = document.getElementById("MSearchSelectWindow");
+ for (var key in indexSectionLabels)
+ {
+ var link = document.createElement('a');
+ link.setAttribute('class','SelectItem');
+ link.setAttribute('onclick','searchBox.OnSelectItem('+key+')');
+ link.href='javascript:void(0)';
+ link.innerHTML='<span class="SelectionMark"> </span>'+indexSectionLabels[key];
+ results.appendChild(link);
+ }
+ searchBox.OnSelectItem(0);
+}
+
diff --git a/docs/html/search/search_l.png b/docs/html/search/search_l.png
new file mode 100644
index 0000000..c872f4d
--- /dev/null
+++ b/docs/html/search/search_l.png
Binary files differ
diff --git a/docs/html/search/search_m.png b/docs/html/search/search_m.png
new file mode 100644
index 0000000..b429a16
--- /dev/null
+++ b/docs/html/search/search_m.png
Binary files differ
diff --git a/docs/html/search/search_r.png b/docs/html/search/search_r.png
new file mode 100644
index 0000000..97ee8b4
--- /dev/null
+++ b/docs/html/search/search_r.png
Binary files differ
diff --git a/docs/html/search/searchdata.js b/docs/html/search/searchdata.js
new file mode 100644
index 0000000..cb6e27d
--- /dev/null
+++ b/docs/html/search/searchdata.js
@@ -0,0 +1,36 @@
+var indexSectionsWithContent =
+{
+ 0: "abcegikmprs",
+ 1: "p",
+ 2: "c",
+ 3: "p",
+ 4: "e",
+ 5: "p",
+ 6: "p",
+ 7: "abgikmrs"
+};
+
+var indexSectionNames =
+{
+ 0: "all",
+ 1: "classes",
+ 2: "files",
+ 3: "functions",
+ 4: "variables",
+ 5: "typedefs",
+ 6: "defines",
+ 7: "groups"
+};
+
+var indexSectionLabels =
+{
+ 0: "All",
+ 1: "Classes",
+ 2: "Files",
+ 3: "Functions",
+ 4: "Variables",
+ 5: "Typedefs",
+ 6: "Macros",
+ 7: "Modules"
+};
+
diff --git a/docs/html/search/typedefs_0.html b/docs/html/search/typedefs_0.html
new file mode 100644
index 0000000..05722e1
--- /dev/null
+++ b/docs/html/search/typedefs_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="typedefs_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/typedefs_0.js b/docs/html/search/typedefs_0.js
new file mode 100644
index 0000000..05d29eb
--- /dev/null
+++ b/docs/html/search/typedefs_0.js
@@ -0,0 +1,15 @@
+var searchData=
+[
+ ['psa_5falgorithm_5ft',['psa_algorithm_t',['../group__crypto__types.html#gac2e4d47f1300d73c2f829a6d99252d69',1,'crypto.h']]],
+ ['psa_5fcipher_5foperation_5ft',['psa_cipher_operation_t',['../group__cipher.html#ga1399de29db657e3737bb09927aae51fa',1,'crypto.h']]],
+ ['psa_5fcrypto_5fgenerator_5ft',['psa_crypto_generator_t',['../group__generators.html#ga1f894c4fba202ef8e307d72caf489e3b',1,'crypto.h']]],
+ ['psa_5fecc_5fcurve_5ft',['psa_ecc_curve_t',['../group__crypto__types.html#ga4e8977c145cce5077c4bce7fec890ad9',1,'crypto.h']]],
+ ['psa_5fhash_5foperation_5ft',['psa_hash_operation_t',['../group__hash.html#ga3c4205d2ce66c4095fc5c78c25273fab',1,'crypto.h']]],
+ ['psa_5fkey_5flifetime_5ft',['psa_key_lifetime_t',['../group__persistence.html#ga6821ff6dd39dc2bc370ded760ad8b0cf',1,'crypto.h']]],
+ ['psa_5fkey_5fpolicy_5ft',['psa_key_policy_t',['../group__policy.html#gaf553efd409845b6d09ff25ce2ba36607',1,'crypto.h']]],
+ ['psa_5fkey_5fslot_5ft',['psa_key_slot_t',['../group__platform.html#gac3da92a6b8a7f0c01dc348f8e0432e4c',1,'crypto.h']]],
+ ['psa_5fkey_5ftype_5ft',['psa_key_type_t',['../group__crypto__types.html#ga578159487dfc7096cb191b0d2befe628',1,'crypto.h']]],
+ ['psa_5fkey_5fusage_5ft',['psa_key_usage_t',['../group__policy.html#ga7bb9de71337e0e98de843aa7f9b55f25',1,'crypto.h']]],
+ ['psa_5fmac_5foperation_5ft',['psa_mac_operation_t',['../group__MAC.html#ga78f0838b0c4e3db28b26355624d4bd37',1,'crypto.h']]],
+ ['psa_5fstatus_5ft',['psa_status_t',['../group__basic.html#ga05676e70ba5c6a7565aff3c36677c1f9',1,'crypto.h']]]
+];
diff --git a/docs/html/search/variables_0.html b/docs/html/search/variables_0.html
new file mode 100644
index 0000000..74ce807
--- /dev/null
+++ b/docs/html/search/variables_0.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+createResults();
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+--></script>
+</div>
+</body>
+</html>
diff --git a/docs/html/search/variables_0.js b/docs/html/search/variables_0.js
new file mode 100644
index 0000000..9ba7121
--- /dev/null
+++ b/docs/html/search/variables_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+ ['e',['e',['../structpsa__generate__key__extra__rsa.html#a53ccb9e4375f3c9af6e3ecfe111ce11d',1,'psa_generate_key_extra_rsa']]]
+];
diff --git a/docs/html/splitbar.png b/docs/html/splitbar.png
new file mode 100644
index 0000000..fe895f2
--- /dev/null
+++ b/docs/html/splitbar.png
Binary files differ
diff --git a/docs/html/structpsa__generate__key__extra__rsa-members.html b/docs/html/structpsa__generate__key__extra__rsa-members.html
new file mode 100644
index 0000000..2950178
--- /dev/null
+++ b/docs/html/structpsa__generate__key__extra__rsa-members.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+ <div class="headertitle">
+<div class="title">psa_generate_key_extra_rsa Member List</div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="structpsa__generate__key__extra__rsa.html">psa_generate_key_extra_rsa</a>, including all inherited members.</p>
+<table class="directory">
+ <tr class="even"><td class="entry"><a class="el" href="structpsa__generate__key__extra__rsa.html#a53ccb9e4375f3c9af6e3ecfe111ce11d">e</a></td><td class="entry"><a class="el" href="structpsa__generate__key__extra__rsa.html">psa_generate_key_extra_rsa</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/structpsa__generate__key__extra__rsa.html b/docs/html/structpsa__generate__key__extra__rsa.html
new file mode 100644
index 0000000..4ee65512
--- /dev/null
+++ b/docs/html/structpsa__generate__key__extra__rsa.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.13"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Platform Security Architecture — cryptography and keystore interface: psa_generate_key_extra_rsa Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">Platform Security Architecture — cryptography and keystore interface
+  <span id="projectnumber">Working draft</span>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.13 -->
+<script type="text/javascript">
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+$(function() {
+ initMenu('',true,false,'search.php','Search');
+ $(document).ready(function() { init_search(); });
+});
+</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+ onmouseover="return searchBox.OnSearchSelectShow()"
+ onmouseout="return searchBox.OnSearchSelectHide()"
+ onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0"
+ name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+ <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> |
+<a href="structpsa__generate__key__extra__rsa-members.html">List of all members</a> </div>
+ <div class="headertitle">
+<div class="title">psa_generate_key_extra_rsa Struct Reference<div class="ingroups"><a class="el" href="group__random.html">Random generation</a></div></div> </div>
+</div><!--header-->
+<div class="contents">
+
+<p><code>#include <<a class="el" href="crypto_8h_source.html">crypto.h</a>></code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a53ccb9e4375f3c9af6e3ecfe111ce11d"><td class="memItemLeft" align="right" valign="top">uint32_t </td><td class="memItemRight" valign="bottom"><a class="el" href="structpsa__generate__key__extra__rsa.html#a53ccb9e4375f3c9af6e3ecfe111ce11d">e</a></td></tr>
+<tr class="separator:a53ccb9e4375f3c9af6e3ecfe111ce11d"><td class="memSeparator" colspan="2"> </td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Extra parameters for RSA key generation.</p>
+<p>You may pass a pointer to a structure of this type as the <code>extra</code> parameter to <a class="el" href="group__random.html#gada1d701903f6b4de6b4c6a1d613c1b10" title="Generate a key or key pair. ">psa_generate_key()</a>. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="a53ccb9e4375f3c9af6e3ecfe111ce11d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a53ccb9e4375f3c9af6e3ecfe111ce11d">◆ </a></span>e</h2>
+
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">uint32_t psa_generate_key_extra_rsa::e</td>
+ </tr>
+ </table>
+</div><div class="memdoc">
+<p>Public exponent value. Default: 65537. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li>psa/<a class="el" href="crypto_8h_source.html">crypto.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.13
+</small></address>
+</body>
+</html>
diff --git a/docs/html/sync_off.png b/docs/html/sync_off.png
new file mode 100644
index 0000000..3b443fc
--- /dev/null
+++ b/docs/html/sync_off.png
Binary files differ
diff --git a/docs/html/sync_on.png b/docs/html/sync_on.png
new file mode 100644
index 0000000..e08320f
--- /dev/null
+++ b/docs/html/sync_on.png
Binary files differ
diff --git a/docs/html/tab_a.png b/docs/html/tab_a.png
new file mode 100644
index 0000000..3b725c4
--- /dev/null
+++ b/docs/html/tab_a.png
Binary files differ
diff --git a/docs/html/tab_b.png b/docs/html/tab_b.png
new file mode 100644
index 0000000..e2b4a86
--- /dev/null
+++ b/docs/html/tab_b.png
Binary files differ
diff --git a/docs/html/tab_h.png b/docs/html/tab_h.png
new file mode 100644
index 0000000..fd5cb70
--- /dev/null
+++ b/docs/html/tab_h.png
Binary files differ
diff --git a/docs/html/tab_s.png b/docs/html/tab_s.png
new file mode 100644
index 0000000..ab478c9
--- /dev/null
+++ b/docs/html/tab_s.png
Binary files differ
diff --git a/docs/html/tabs.css b/docs/html/tabs.css
new file mode 100644
index 0000000..bbde11e
--- /dev/null
+++ b/docs/html/tabs.css
@@ -0,0 +1 @@
+.sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:transparent}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0px/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sm-dox{background-image:url("tab_b.png")}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0px 12px;padding-right:43px;font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;font-size:13px;font-weight:bold;line-height:36px;text-decoration:none;text-shadow:0px 1px 1px rgba(255,255,255,0.9);color:#283A5D;outline:none}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox a.current{color:#D23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace !important;text-align:center;text-shadow:none;background:rgba(255,255,255,0.5);border-radius:5px}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{border-radius:0}.sm-dox ul{background:rgba(162,162,162,0.1)}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:white;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media (min-width: 768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-image:url("tab_b.png");line-height:36px}.sm-dox a span.sub-arrow{top:50%;margin-top:-2px;right:12px;width:0;height:0;border-width:4px;border-style:solid dashed dashed dashed;border-color:#283A5D transparent transparent transparent;background:transparent;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0px 12px;background-image:url("tab_s.png");background-repeat:no-repeat;background-position:right;border-radius:0 !important}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox a:hover span.sub-arrow{border-color:#fff transparent transparent transparent}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent #fff transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:#fff;border-radius:5px !important;box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-color:transparent transparent transparent #555;border-style:dashed dashed dashed solid}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:#555;background-image:none;border:0 !important;color:#555;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent #fff}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:#fff;height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #D23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#D23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent #555 transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:#555 transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:12px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:12px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px !important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a.disabled{background-image:url("tab_b.png")}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:#fff}}
diff --git a/include/mbedcrypto/aes.h b/include/mbedcrypto/aes.h
new file mode 100644
index 0000000..eecf76c
--- /dev/null
+++ b/include/mbedcrypto/aes.h
@@ -0,0 +1,415 @@
+/**
+ * \file aes.h
+ *
+ * \brief This file contains AES definitions and functions.
+ *
+ * The Advanced Encryption Standard (AES) specifies a FIPS-approved
+ * cryptographic algorithm that can be used to protect electronic
+ * data.
+ *
+ * The AES algorithm is a symmetric block cipher that can
+ * encrypt and decrypt information. For more information, see
+ * <em>FIPS Publication 197: Advanced Encryption Standard</em> and
+ * <em>ISO/IEC 18033-2:2006: Information technology -- Security
+ * techniques -- Encryption algorithms -- Part 2: Asymmetric
+ * ciphers</em>.
+ */
+
+/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_AES_H
+#define MBEDCRYPTO_AES_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* padlock.c and aesni.c rely on these values! */
+#define MBEDCRYPTO_AES_ENCRYPT 1 /**< AES encryption. */
+#define MBEDCRYPTO_AES_DECRYPT 0 /**< AES decryption. */
+
+/* Error codes in range 0x0020-0x0022 */
+#define MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
+#define MBEDCRYPTO_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
+
+/* Error codes in range 0x0023-0x0025 */
+#define MBEDCRYPTO_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */
+#define MBEDCRYPTO_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_AES_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief The AES context-type definition.
+ */
+typedef struct
+{
+ int nr; /*!< The number of rounds. */
+ uint32_t *rk; /*!< AES round keys. */
+ uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can
+ hold 32 extra Bytes, which can be used for
+ one of the following purposes:
+ <ul><li>Alignment if VIA padlock is
+ used.</li>
+ <li>Simplifying key expansion in the 256-bit
+ case by generating an extra round key.
+ </li></ul> */
+}
+mbedcrypto_aes_context;
+
+#else /* MBEDCRYPTO_AES_ALT */
+#include "aes_alt.h"
+#endif /* MBEDCRYPTO_AES_ALT */
+
+/**
+ * \brief This function initializes the specified AES context.
+ *
+ * It must be the first API called before using
+ * the context.
+ *
+ * \param ctx The AES context to initialize.
+ */
+void mbedcrypto_aes_init( mbedcrypto_aes_context *ctx );
+
+/**
+ * \brief This function releases and clears the specified AES context.
+ *
+ * \param ctx The AES context to clear.
+ */
+void mbedcrypto_aes_free( mbedcrypto_aes_context *ctx );
+
+/**
+ * \brief This function sets the encryption key.
+ *
+ * \param ctx The AES context to which the key should be bound.
+ * \param key The encryption key.
+ * \param keybits The size of data passed in bits. Valid options are:
+ * <ul><li>128 bits</li>
+ * <li>192 bits</li>
+ * <li>256 bits</li></ul>
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedcrypto_aes_setkey_enc( mbedcrypto_aes_context *ctx, const unsigned char *key,
+ unsigned int keybits );
+
+/**
+ * \brief This function sets the decryption key.
+ *
+ * \param ctx The AES context to which the key should be bound.
+ * \param key The decryption key.
+ * \param keybits The size of data passed. Valid options are:
+ * <ul><li>128 bits</li>
+ * <li>192 bits</li>
+ * <li>256 bits</li></ul>
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedcrypto_aes_setkey_dec( mbedcrypto_aes_context *ctx, const unsigned char *key,
+ unsigned int keybits );
+
+/**
+ * \brief This function performs an AES single-block encryption or
+ * decryption operation.
+ *
+ * It performs the operation defined in the \p mode parameter
+ * (encrypt or decrypt), on the input data buffer defined in
+ * the \p input parameter.
+ *
+ * mbedcrypto_aes_init(), and either mbedcrypto_aes_setkey_enc() or
+ * mbedcrypto_aes_setkey_dec() must be called before the first
+ * call to this API with the same context.
+ *
+ * \param ctx The AES context to use for encryption or decryption.
+ * \param mode The AES operation: #MBEDCRYPTO_AES_ENCRYPT or
+ * #MBEDCRYPTO_AES_DECRYPT.
+ * \param input The 16-Byte buffer holding the input data.
+ * \param output The 16-Byte buffer holding the output data.
+
+ * \return \c 0 on success.
+ */
+int mbedcrypto_aes_crypt_ecb( mbedcrypto_aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief This function performs an AES-CBC encryption or decryption operation
+ * on full blocks.
+ *
+ * It performs the operation defined in the \p mode
+ * parameter (encrypt/decrypt), on the input data buffer defined in
+ * the \p input parameter.
+ *
+ * It can be called as many times as needed, until all the input
+ * data is processed. mbedcrypto_aes_init(), and either
+ * mbedcrypto_aes_setkey_enc() or mbedcrypto_aes_setkey_dec() must be called
+ * before the first call to this API with the same context.
+ *
+ * \note This function operates on aligned blocks, that is, the input size
+ * must be a multiple of the AES block size of 16 Bytes.
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the same function again on the next
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If you need to retain the contents of the IV, you should
+ * either save it manually or use the cipher module instead.
+ *
+ *
+ * \param ctx The AES context to use for encryption or decryption.
+ * \param mode The AES operation: #MBEDCRYPTO_AES_ENCRYPT or
+ * #MBEDCRYPTO_AES_DECRYPT.
+ * \param length The length of the input data in Bytes. This must be a
+ * multiple of the block size (16 Bytes).
+ * \param iv Initialization vector (updated after use).
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_AES_INVALID_INPUT_LENGTH
+ * on failure.
+ */
+int mbedcrypto_aes_crypt_cbc( mbedcrypto_aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+/**
+ * \brief This function performs an AES-CFB128 encryption or decryption
+ * operation.
+ *
+ * It performs the operation defined in the \p mode
+ * parameter (encrypt or decrypt), on the input data buffer
+ * defined in the \p input parameter.
+ *
+ * For CFB, you must set up the context with mbedcrypto_aes_setkey_enc(),
+ * regardless of whether you are performing an encryption or decryption
+ * operation, that is, regardless of the \p mode parameter. This is
+ * because CFB mode uses the same key schedule for encryption and
+ * decryption.
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the same function again on the next
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If you need to retain the contents of the
+ * IV, you must either save it manually or use the cipher
+ * module instead.
+ *
+ *
+ * \param ctx The AES context to use for encryption or decryption.
+ * \param mode The AES operation: #MBEDCRYPTO_AES_ENCRYPT or
+ * #MBEDCRYPTO_AES_DECRYPT.
+ * \param length The length of the input data.
+ * \param iv_off The offset in IV (updated after use).
+ * \param iv The initialization vector (updated after use).
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_aes_crypt_cfb128( mbedcrypto_aes_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function performs an AES-CFB8 encryption or decryption
+ * operation.
+ *
+ * It performs the operation defined in the \p mode
+ * parameter (encrypt/decrypt), on the input data buffer defined
+ * in the \p input parameter.
+ *
+ * Due to the nature of CFB, you must use the same key schedule for
+ * both encryption and decryption operations. Therefore, you must
+ * use the context initialized with mbedcrypto_aes_setkey_enc() for
+ * both #MBEDCRYPTO_AES_ENCRYPT and #MBEDCRYPTO_AES_DECRYPT.
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the same function again on the next
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If you need to retain the contents of the
+ * IV, you should either save it manually or use the cipher
+ * module instead.
+ *
+ *
+ * \param ctx The AES context to use for encryption or decryption.
+ * \param mode The AES operation: #MBEDCRYPTO_AES_ENCRYPT or
+ * #MBEDCRYPTO_AES_DECRYPT
+ * \param length The length of the input data.
+ * \param iv The initialization vector (updated after use).
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_aes_crypt_cfb8( mbedcrypto_aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /*MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/**
+ * \brief This function performs an AES-CTR encryption or decryption
+ * operation.
+ *
+ * This function performs the operation defined in the \p mode
+ * parameter (encrypt/decrypt), on the input data buffer
+ * defined in the \p input parameter.
+ *
+ * Due to the nature of CTR, you must use the same key schedule
+ * for both encryption and decryption operations. Therefore, you
+ * must use the context initialized with mbedcrypto_aes_setkey_enc()
+ * for both #MBEDCRYPTO_AES_ENCRYPT and #MBEDCRYPTO_AES_DECRYPT.
+ *
+ * \warning You must keep the maximum use of your counter in mind.
+ *
+ * \param ctx The AES context to use for encryption or decryption.
+ * \param length The length of the input data.
+ * \param nc_off The offset in the current \p stream_block, for
+ * resuming within the current cipher stream. The
+ * offset pointer should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block The saved stream block for resuming. This is
+ * overwritten by the function.
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_aes_crypt_ctr( mbedcrypto_aes_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+/**
+ * \brief Internal AES block encryption function. This is only
+ * exposed to allow overriding it using
+ * \c MBEDCRYPTO_AES_ENCRYPT_ALT.
+ *
+ * \param ctx The AES context to use for encryption.
+ * \param input The plaintext block.
+ * \param output The output (ciphertext) block.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_internal_aes_encrypt( mbedcrypto_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief Internal AES block decryption function. This is only
+ * exposed to allow overriding it using see
+ * \c MBEDCRYPTO_AES_DECRYPT_ALT.
+ *
+ * \param ctx The AES context to use for decryption.
+ * \param input The ciphertext block.
+ * \param output The output (plaintext) block.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_internal_aes_decrypt( mbedcrypto_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief Deprecated internal AES block encryption function
+ * without return value.
+ *
+ * \deprecated Superseded by mbedcrypto_aes_encrypt_ext() in 2.5.0.
+ *
+ * \param ctx The AES context to use for encryption.
+ * \param input Plaintext block.
+ * \param output Output (ciphertext) block.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_aes_encrypt( mbedcrypto_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief Deprecated internal AES block decryption function
+ * without return value.
+ *
+ * \deprecated Superseded by mbedcrypto_aes_decrypt_ext() in 2.5.0.
+ *
+ * \param ctx The AES context to use for decryption.
+ * \param input Ciphertext block.
+ * \param output Output (plaintext) block.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_aes_decrypt( mbedcrypto_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief Checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedcrypto_aes_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aes.h */
diff --git a/include/mbedcrypto/aesni.h b/include/mbedcrypto/aesni.h
new file mode 100644
index 0000000..c68e360
--- /dev/null
+++ b/include/mbedcrypto/aesni.h
@@ -0,0 +1,112 @@
+/**
+ * \file aesni.h
+ *
+ * \brief AES-NI for hardware AES acceleration on some Intel processors
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_AESNI_H
+#define MBEDCRYPTO_AESNI_H
+
+#include "aes.h"
+
+#define MBEDCRYPTO_AESNI_AES 0x02000000u
+#define MBEDCRYPTO_AESNI_CLMUL 0x00000002u
+
+#if defined(MBEDCRYPTO_HAVE_ASM) && defined(__GNUC__) && \
+ ( defined(__amd64__) || defined(__x86_64__) ) && \
+ ! defined(MBEDCRYPTO_HAVE_X86_64)
+#define MBEDCRYPTO_HAVE_X86_64
+#endif
+
+#if defined(MBEDCRYPTO_HAVE_X86_64)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief AES-NI features detection routine
+ *
+ * \param what The feature to detect
+ * (MBEDCRYPTO_AESNI_AES or MBEDCRYPTO_AESNI_CLMUL)
+ *
+ * \return 1 if CPU has support for the feature, 0 otherwise
+ */
+int mbedcrypto_aesni_has_support( unsigned int what );
+
+/**
+ * \brief AES-NI AES-ECB block en(de)cryption
+ *
+ * \param ctx AES context
+ * \param mode MBEDCRYPTO_AES_ENCRYPT or MBEDCRYPTO_AES_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 on success (cannot fail)
+ */
+int mbedcrypto_aesni_crypt_ecb( mbedcrypto_aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+/**
+ * \brief GCM multiplication: c = a * b in GF(2^128)
+ *
+ * \param c Result
+ * \param a First operand
+ * \param b Second operand
+ *
+ * \note Both operands and result are bit strings interpreted as
+ * elements of GF(2^128) as per the GCM spec.
+ */
+void mbedcrypto_aesni_gcm_mult( unsigned char c[16],
+ const unsigned char a[16],
+ const unsigned char b[16] );
+
+/**
+ * \brief Compute decryption round keys from encryption round keys
+ *
+ * \param invkey Round keys for the equivalent inverse cipher
+ * \param fwdkey Original round keys (for encryption)
+ * \param nr Number of rounds (that is, number of round keys minus one)
+ */
+void mbedcrypto_aesni_inverse_key( unsigned char *invkey,
+ const unsigned char *fwdkey, int nr );
+
+/**
+ * \brief Perform key expansion (for encryption)
+ *
+ * \param rk Destination buffer where the round keys are written
+ * \param key Encryption key
+ * \param bits Key size in bits (must be 128, 192 or 256)
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH
+ */
+int mbedcrypto_aesni_setkey_enc( unsigned char *rk,
+ const unsigned char *key,
+ size_t bits );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_HAVE_X86_64 */
+
+#endif /* MBEDCRYPTO_AESNI_H */
diff --git a/include/mbedcrypto/arc4.h b/include/mbedcrypto/arc4.h
new file mode 100644
index 0000000..32c3abb
--- /dev/null
+++ b/include/mbedcrypto/arc4.h
@@ -0,0 +1,141 @@
+/**
+ * \file arc4.h
+ *
+ * \brief The ARCFOUR stream cipher
+ *
+ * \warning ARC4 is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers instead.
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+#ifndef MBEDCRYPTO_ARC4_H
+#define MBEDCRYPTO_ARC4_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#define MBEDCRYPTO_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_ARC4_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief ARC4 context structure
+ *
+ * \warning ARC4 is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers instead.
+ *
+ */
+typedef struct
+{
+ int x; /*!< permutation index */
+ int y; /*!< permutation index */
+ unsigned char m[256]; /*!< permutation table */
+}
+mbedcrypto_arc4_context;
+
+#else /* MBEDCRYPTO_ARC4_ALT */
+#include "arc4_alt.h"
+#endif /* MBEDCRYPTO_ARC4_ALT */
+
+/**
+ * \brief Initialize ARC4 context
+ *
+ * \param ctx ARC4 context to be initialized
+ *
+ * \warning ARC4 is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ *
+ */
+void mbedcrypto_arc4_init( mbedcrypto_arc4_context *ctx );
+
+/**
+ * \brief Clear ARC4 context
+ *
+ * \param ctx ARC4 context to be cleared
+ *
+ * \warning ARC4 is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ *
+ */
+void mbedcrypto_arc4_free( mbedcrypto_arc4_context *ctx );
+
+/**
+ * \brief ARC4 key schedule
+ *
+ * \param ctx ARC4 context to be setup
+ * \param key the secret key
+ * \param keylen length of the key, in bytes
+ *
+ * \warning ARC4 is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ *
+ */
+void mbedcrypto_arc4_setup( mbedcrypto_arc4_context *ctx, const unsigned char *key,
+ unsigned int keylen );
+
+/**
+ * \brief ARC4 cipher function
+ *
+ * \param ctx ARC4 context
+ * \param length length of the input data
+ * \param input buffer holding the input data
+ * \param output buffer for the output data
+ *
+ * \return 0 if successful
+ *
+ * \warning ARC4 is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ *
+ */
+int mbedcrypto_arc4_crypt( mbedcrypto_arc4_context *ctx, size_t length, const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ *
+ * \warning ARC4 is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ *
+ */
+int mbedcrypto_arc4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* arc4.h */
diff --git a/include/mbedcrypto/asn1.h b/include/mbedcrypto/asn1.h
new file mode 100644
index 0000000..d815c4d
--- /dev/null
+++ b/include/mbedcrypto/asn1.h
@@ -0,0 +1,358 @@
+/**
+ * \file asn1.h
+ *
+ * \brief Generic ASN.1 parsing
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_ASN1_H
+#define MBEDCRYPTO_ASN1_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#if defined(MBEDCRYPTO_BIGNUM_C)
+#include "bignum.h"
+#endif
+
+/**
+ * \addtogroup asn1_module
+ * \{
+ */
+
+/**
+ * \name ASN1 Error codes
+ * These error codes are OR'ed to X509 error codes for
+ * higher error granularity.
+ * ASN1 is a standard to specify data structures.
+ * \{
+ */
+#define MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */
+#define MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */
+#define MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */
+#define MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */
+#define MBEDCRYPTO_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */
+#define MBEDCRYPTO_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */
+#define MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */
+
+/* \} name */
+
+/**
+ * \name DER constants
+ * These constants comply with the DER encoded ASN.1 type tags.
+ * DER encoding uses hexadecimal representation.
+ * An example DER sequence is:\n
+ * - 0x02 -- tag indicating INTEGER
+ * - 0x01 -- length in octets
+ * - 0x05 -- value
+ * Such sequences are typically read into \c ::mbedcrypto_x509_buf.
+ * \{
+ */
+#define MBEDCRYPTO_ASN1_BOOLEAN 0x01
+#define MBEDCRYPTO_ASN1_INTEGER 0x02
+#define MBEDCRYPTO_ASN1_BIT_STRING 0x03
+#define MBEDCRYPTO_ASN1_OCTET_STRING 0x04
+#define MBEDCRYPTO_ASN1_NULL 0x05
+#define MBEDCRYPTO_ASN1_OID 0x06
+#define MBEDCRYPTO_ASN1_UTF8_STRING 0x0C
+#define MBEDCRYPTO_ASN1_SEQUENCE 0x10
+#define MBEDCRYPTO_ASN1_SET 0x11
+#define MBEDCRYPTO_ASN1_PRINTABLE_STRING 0x13
+#define MBEDCRYPTO_ASN1_T61_STRING 0x14
+#define MBEDCRYPTO_ASN1_IA5_STRING 0x16
+#define MBEDCRYPTO_ASN1_UTC_TIME 0x17
+#define MBEDCRYPTO_ASN1_GENERALIZED_TIME 0x18
+#define MBEDCRYPTO_ASN1_UNIVERSAL_STRING 0x1C
+#define MBEDCRYPTO_ASN1_BMP_STRING 0x1E
+#define MBEDCRYPTO_ASN1_PRIMITIVE 0x00
+#define MBEDCRYPTO_ASN1_CONSTRUCTED 0x20
+#define MBEDCRYPTO_ASN1_CONTEXT_SPECIFIC 0x80
+
+/*
+ * Bit masks for each of the components of an ASN.1 tag as specified in
+ * ITU X.690 (08/2015), section 8.1 "General rules for encoding",
+ * paragraph 8.1.2.2:
+ *
+ * Bit 8 7 6 5 1
+ * +-------+-----+------------+
+ * | Class | P/C | Tag number |
+ * +-------+-----+------------+
+ */
+#define MBEDCRYPTO_ASN1_TAG_CLASS_MASK 0xC0
+#define MBEDCRYPTO_ASN1_TAG_PC_MASK 0x20
+#define MBEDCRYPTO_ASN1_TAG_VALUE_MASK 0x1F
+
+/* \} name */
+/* \} addtogroup asn1_module */
+
+/** Returns the size of the binary string, without the trailing \\0 */
+#define MBEDCRYPTO_OID_SIZE(x) (sizeof(x) - 1)
+
+/**
+ * Compares an mbedcrypto_asn1_buf structure to a reference OID.
+ *
+ * Only works for 'defined' oid_str values (MBEDCRYPTO_OID_HMAC_SHA1), you cannot use a
+ * 'unsigned char *oid' here!
+ */
+#define MBEDCRYPTO_OID_CMP(oid_str, oid_buf) \
+ ( ( MBEDCRYPTO_OID_SIZE(oid_str) != (oid_buf)->len ) || \
+ memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Functions to parse ASN.1 data structures
+ * \{
+ */
+
+/**
+ * Type-length-value structure that allows for ASN1 using DER.
+ */
+typedef struct mbedcrypto_asn1_buf
+{
+ int tag; /**< ASN1 type, e.g. MBEDCRYPTO_ASN1_UTF8_STRING. */
+ size_t len; /**< ASN1 length, in octets. */
+ unsigned char *p; /**< ASN1 data, e.g. in ASCII. */
+}
+mbedcrypto_asn1_buf;
+
+/**
+ * Container for ASN1 bit strings.
+ */
+typedef struct mbedcrypto_asn1_bitstring
+{
+ size_t len; /**< ASN1 length, in octets. */
+ unsigned char unused_bits; /**< Number of unused bits at the end of the string */
+ unsigned char *p; /**< Raw ASN1 data for the bit string */
+}
+mbedcrypto_asn1_bitstring;
+
+/**
+ * Container for a sequence of ASN.1 items
+ */
+typedef struct mbedcrypto_asn1_sequence
+{
+ mbedcrypto_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */
+ struct mbedcrypto_asn1_sequence *next; /**< The next entry in the sequence. */
+}
+mbedcrypto_asn1_sequence;
+
+/**
+ * Container for a sequence or list of 'named' ASN.1 data items
+ */
+typedef struct mbedcrypto_asn1_named_data
+{
+ mbedcrypto_asn1_buf oid; /**< The object identifier. */
+ mbedcrypto_asn1_buf val; /**< The named value. */
+ struct mbedcrypto_asn1_named_data *next; /**< The next entry in the sequence. */
+ unsigned char next_merged; /**< Merge next item into the current one? */
+}
+mbedcrypto_asn1_named_data;
+
+/**
+ * \brief Get the length of an ASN.1 element.
+ * Updates the pointer to immediately behind the length.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param len The variable that will receive the value
+ *
+ * \return 0 if successful, MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA on reaching
+ * end of data, MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH if length is
+ * unparseable.
+ */
+int mbedcrypto_asn1_get_len( unsigned char **p,
+ const unsigned char *end,
+ size_t *len );
+
+/**
+ * \brief Get the tag and length of the tag. Check for the requested tag.
+ * Updates the pointer to immediately behind the tag and length.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param len The variable that will receive the length
+ * \param tag The expected tag
+ *
+ * \return 0 if successful, MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG if tag did
+ * not match requested tag, or another specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_tag( unsigned char **p,
+ const unsigned char *end,
+ size_t *len, int tag );
+
+/**
+ * \brief Retrieve a boolean ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param val The variable that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_bool( unsigned char **p,
+ const unsigned char *end,
+ int *val );
+
+/**
+ * \brief Retrieve an integer ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param val The variable that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_int( unsigned char **p,
+ const unsigned char *end,
+ int *val );
+
+/**
+ * \brief Retrieve a bitstring ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param bs The variable that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+ mbedcrypto_asn1_bitstring *bs);
+
+/**
+ * \brief Retrieve a bitstring ASN.1 tag without unused bits and its
+ * value.
+ * Updates the pointer to the beginning of the bit/octet string.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param len Length of the actual bit/octect string in bytes
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
+ size_t *len );
+
+/**
+ * \brief Parses and splits an ASN.1 "SEQUENCE OF <tag>"
+ * Updated the pointer to immediately behind the full sequence tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param cur First variable in the chain to fill
+ * \param tag Type of sequence
+ *
+ * \return 0 if successful or a specific ASN.1 error code.
+ */
+int mbedcrypto_asn1_get_sequence_of( unsigned char **p,
+ const unsigned char *end,
+ mbedcrypto_asn1_sequence *cur,
+ int tag);
+
+#if defined(MBEDCRYPTO_BIGNUM_C)
+/**
+ * \brief Retrieve a MPI value from an integer ASN.1 tag.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param X The MPI that will receive the value
+ *
+ * \return 0 if successful or a specific ASN.1 or MPI error code.
+ */
+int mbedcrypto_asn1_get_mpi( unsigned char **p,
+ const unsigned char *end,
+ mbedcrypto_mpi *X );
+#endif /* MBEDCRYPTO_BIGNUM_C */
+
+/**
+ * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence.
+ * Updates the pointer to immediately behind the full
+ * AlgorithmIdentifier.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param alg The buffer to receive the OID
+ * \param params The buffer to receive the params (if any)
+ *
+ * \return 0 if successful or a specific ASN.1 or MPI error code.
+ */
+int mbedcrypto_asn1_get_alg( unsigned char **p,
+ const unsigned char *end,
+ mbedcrypto_asn1_buf *alg, mbedcrypto_asn1_buf *params );
+
+/**
+ * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no
+ * params.
+ * Updates the pointer to immediately behind the full
+ * AlgorithmIdentifier.
+ *
+ * \param p The position in the ASN.1 data
+ * \param end End of data
+ * \param alg The buffer to receive the OID
+ *
+ * \return 0 if successful or a specific ASN.1 or MPI error code.
+ */
+int mbedcrypto_asn1_get_alg_null( unsigned char **p,
+ const unsigned char *end,
+ mbedcrypto_asn1_buf *alg );
+
+/**
+ * \brief Find a specific named_data entry in a sequence or list based on
+ * the OID.
+ *
+ * \param list The list to seek through
+ * \param oid The OID to look for
+ * \param len Size of the OID
+ *
+ * \return NULL if not found, or a pointer to the existing entry.
+ */
+mbedcrypto_asn1_named_data *mbedcrypto_asn1_find_named_data( mbedcrypto_asn1_named_data *list,
+ const char *oid, size_t len );
+
+/**
+ * \brief Free a mbedcrypto_asn1_named_data entry
+ *
+ * \param entry The named data entry to free
+ */
+void mbedcrypto_asn1_free_named_data( mbedcrypto_asn1_named_data *entry );
+
+/**
+ * \brief Free all entries in a mbedcrypto_asn1_named_data list
+ * Head will be set to NULL
+ *
+ * \param head Pointer to the head of the list of named data entries to free
+ */
+void mbedcrypto_asn1_free_named_data_list( mbedcrypto_asn1_named_data **head );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* asn1.h */
diff --git a/include/mbedcrypto/asn1write.h b/include/mbedcrypto/asn1write.h
new file mode 100644
index 0000000..cc134ce
--- /dev/null
+++ b/include/mbedcrypto/asn1write.h
@@ -0,0 +1,240 @@
+/**
+ * \file asn1write.h
+ *
+ * \brief ASN.1 buffer writing functionality
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_ASN1_WRITE_H
+#define MBEDCRYPTO_ASN1_WRITE_H
+
+#include "asn1.h"
+
+#define MBEDCRYPTO_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \
+ g += ret; } while( 0 )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Write a length field in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param len the length to write
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_len( unsigned char **p, unsigned char *start, size_t len );
+
+/**
+ * \brief Write a ASN.1 tag in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param tag the tag to write
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_tag( unsigned char **p, unsigned char *start,
+ unsigned char tag );
+
+/**
+ * \brief Write raw buffer data
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param buf data buffer to write
+ * \param size length of the data buffer
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
+ const unsigned char *buf, size_t size );
+
+#if defined(MBEDCRYPTO_BIGNUM_C)
+/**
+ * \brief Write a big number (MBEDCRYPTO_ASN1_INTEGER) in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param X the MPI to write
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedcrypto_mpi *X );
+#endif /* MBEDCRYPTO_BIGNUM_C */
+
+/**
+ * \brief Write a NULL tag (MBEDCRYPTO_ASN1_NULL) with zero data in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_null( unsigned char **p, unsigned char *start );
+
+/**
+ * \brief Write an OID tag (MBEDCRYPTO_ASN1_OID) and data in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param oid the OID to write
+ * \param oid_len length of the OID
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_oid( unsigned char **p, unsigned char *start,
+ const char *oid, size_t oid_len );
+
+/**
+ * \brief Write an AlgorithmIdentifier sequence in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param oid the OID of the algorithm
+ * \param oid_len length of the OID
+ * \param par_len length of parameters, which must be already written.
+ * If 0, NULL parameters are added
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
+ const char *oid, size_t oid_len,
+ size_t par_len );
+
+/**
+ * \brief Write a boolean tag (MBEDCRYPTO_ASN1_BOOLEAN) and value in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param boolean 0 or 1
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean );
+
+/**
+ * \brief Write an int tag (MBEDCRYPTO_ASN1_INTEGER) and value in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param val the integer value
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_int( unsigned char **p, unsigned char *start, int val );
+
+/**
+ * \brief Write a printable string tag (MBEDCRYPTO_ASN1_PRINTABLE_STRING) and
+ * value in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param text the text to write
+ * \param text_len length of the text
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_printable_string( unsigned char **p, unsigned char *start,
+ const char *text, size_t text_len );
+
+/**
+ * \brief Write an IA5 string tag (MBEDCRYPTO_ASN1_IA5_STRING) and
+ * value in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param text the text to write
+ * \param text_len length of the text
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+ const char *text, size_t text_len );
+
+/**
+ * \brief Write a bitstring tag (MBEDCRYPTO_ASN1_BIT_STRING) and
+ * value in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param buf the bitstring
+ * \param bits the total number of bits in the bitstring
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_bitstring( unsigned char **p, unsigned char *start,
+ const unsigned char *buf, size_t bits );
+
+/**
+ * \brief Write an octet string tag (MBEDCRYPTO_ASN1_OCTET_STRING) and
+ * value in ASN.1 format
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param buf data buffer to write
+ * \param size length of the data buffer
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_asn1_write_octet_string( unsigned char **p, unsigned char *start,
+ const unsigned char *buf, size_t size );
+
+/**
+ * \brief Create or find a specific named_data entry for writing in a
+ * sequence or list based on the OID. If not already in there,
+ * a new entry is added to the head of the list.
+ * Warning: Destructive behaviour for the val data!
+ *
+ * \param list Pointer to the location of the head of the list to seek
+ * through (will be updated in case of a new entry)
+ * \param oid The OID to look for
+ * \param oid_len Size of the OID
+ * \param val Data to store (can be NULL if you want to fill it by hand)
+ * \param val_len Minimum length of the data buffer needed
+ *
+ * \return NULL if if there was a memory allocation error, or a pointer
+ * to the new / existing entry.
+ */
+mbedcrypto_asn1_named_data *mbedcrypto_asn1_store_named_data( mbedcrypto_asn1_named_data **list,
+ const char *oid, size_t oid_len,
+ const unsigned char *val,
+ size_t val_len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_ASN1_WRITE_H */
diff --git a/include/mbedcrypto/base64.h b/include/mbedcrypto/base64.h
new file mode 100644
index 0000000..21b4622
--- /dev/null
+++ b/include/mbedcrypto/base64.h
@@ -0,0 +1,89 @@
+/**
+ * \file base64.h
+ *
+ * \brief RFC 1521 base64 encoding/decoding
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_BASE64_H
+#define MBEDCRYPTO_BASE64_H
+
+#include <stddef.h>
+
+#define MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */
+#define MBEDCRYPTO_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Encode a buffer into base64 format
+ *
+ * \param dst destination buffer
+ * \param dlen size of the destination buffer
+ * \param olen number of bytes written
+ * \param src source buffer
+ * \param slen amount of data to be encoded
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL.
+ * *olen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ * If that length cannot be represented, then no data is
+ * written to the buffer and *olen is set to the maximum
+ * length representable as a size_t.
+ *
+ * \note Call this function with dlen = 0 to obtain the
+ * required buffer size in *olen
+ */
+int mbedcrypto_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
+ const unsigned char *src, size_t slen );
+
+/**
+ * \brief Decode a base64-formatted buffer
+ *
+ * \param dst destination buffer (can be NULL for checking size)
+ * \param dlen size of the destination buffer
+ * \param olen number of bytes written
+ * \param src source buffer
+ * \param slen amount of data to be decoded
+ *
+ * \return 0 if successful, MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL, or
+ * MBEDCRYPTO_ERR_BASE64_INVALID_CHARACTER if the input data is
+ * not correct. *olen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with *dst = NULL or dlen = 0 to obtain
+ * the required buffer size in *olen
+ */
+int mbedcrypto_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
+ const unsigned char *src, size_t slen );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_base64_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* base64.h */
diff --git a/include/mbedcrypto/bignum.h b/include/mbedcrypto/bignum.h
new file mode 100644
index 0000000..ad989bb
--- /dev/null
+++ b/include/mbedcrypto/bignum.h
@@ -0,0 +1,772 @@
+/**
+ * \file bignum.h
+ *
+ * \brief Multi-precision integer library
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_BIGNUM_H
+#define MBEDCRYPTO_BIGNUM_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#if defined(MBEDCRYPTO_FS_IO)
+#include <stdio.h>
+#endif
+
+#define MBEDCRYPTO_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */
+#define MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */
+#define MBEDCRYPTO_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */
+#define MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */
+#define MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */
+#define MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */
+#define MBEDCRYPTO_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */
+
+#define MBEDCRYPTO_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 )
+
+/*
+ * Maximum size MPIs are allowed to grow to in number of limbs.
+ */
+#define MBEDCRYPTO_MPI_MAX_LIMBS 10000
+
+#if !defined(MBEDCRYPTO_MPI_WINDOW_SIZE)
+/*
+ * Maximum window size used for modular exponentiation. Default: 6
+ * Minimum value: 1. Maximum value: 6.
+ *
+ * Result is an array of ( 2 << MBEDCRYPTO_MPI_WINDOW_SIZE ) MPIs used
+ * for the sliding window calculation. (So 64 by default)
+ *
+ * Reduction in size, reduces speed.
+ */
+#define MBEDCRYPTO_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
+#endif /* !MBEDCRYPTO_MPI_WINDOW_SIZE */
+
+#if !defined(MBEDCRYPTO_MPI_MAX_SIZE)
+/*
+ * Maximum size of MPIs allowed in bits and bytes for user-MPIs.
+ * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )
+ *
+ * Note: Calculations can temporarily result in larger MPIs. So the number
+ * of limbs required (MBEDCRYPTO_MPI_MAX_LIMBS) is higher.
+ */
+#define MBEDCRYPTO_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */
+#endif /* !MBEDCRYPTO_MPI_MAX_SIZE */
+
+#define MBEDCRYPTO_MPI_MAX_BITS ( 8 * MBEDCRYPTO_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */
+
+/*
+ * When reading from files with mbedcrypto_mpi_read_file() and writing to files with
+ * mbedcrypto_mpi_write_file() the buffer should have space
+ * for a (short) label, the MPI (in the provided radix), the newline
+ * characters and the '\0'.
+ *
+ * By default we assume at least a 10 char label, a minimum radix of 10
+ * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).
+ * Autosized at compile time for at least a 10 char label, a minimum radix
+ * of 10 (decimal) for a number of MBEDCRYPTO_MPI_MAX_BITS size.
+ *
+ * This used to be statically sized to 1250 for a maximum of 4096 bit
+ * numbers (1234 decimal chars).
+ *
+ * Calculate using the formula:
+ * MBEDCRYPTO_MPI_RW_BUFFER_SIZE = ceil(MBEDCRYPTO_MPI_MAX_BITS / ln(10) * ln(2)) +
+ * LabelSize + 6
+ */
+#define MBEDCRYPTO_MPI_MAX_BITS_SCALE100 ( 100 * MBEDCRYPTO_MPI_MAX_BITS )
+#define MBEDCRYPTO_LN_2_DIV_LN_10_SCALE100 332
+#define MBEDCRYPTO_MPI_RW_BUFFER_SIZE ( ((MBEDCRYPTO_MPI_MAX_BITS_SCALE100 + MBEDCRYPTO_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDCRYPTO_LN_2_DIV_LN_10_SCALE100) + 10 + 6 )
+
+/*
+ * Define the base integer type, architecture-wise.
+ *
+ * 32 or 64-bit integer types can be forced regardless of the underlying
+ * architecture by defining MBEDCRYPTO_HAVE_INT32 or MBEDCRYPTO_HAVE_INT64
+ * respectively and undefining MBEDCRYPTO_HAVE_ASM.
+ *
+ * Double-width integers (e.g. 128-bit in 64-bit architectures) can be
+ * disabled by defining MBEDCRYPTO_NO_UDBL_DIVISION.
+ */
+#if !defined(MBEDCRYPTO_HAVE_INT32)
+ #if defined(_MSC_VER) && defined(_M_AMD64)
+ /* Always choose 64-bit when using MSC */
+ #if !defined(MBEDCRYPTO_HAVE_INT64)
+ #define MBEDCRYPTO_HAVE_INT64
+ #endif /* !MBEDCRYPTO_HAVE_INT64 */
+ typedef int64_t mbedcrypto_mpi_sint;
+ typedef uint64_t mbedcrypto_mpi_uint;
+ #elif defined(__GNUC__) && ( \
+ defined(__amd64__) || defined(__x86_64__) || \
+ defined(__ppc64__) || defined(__powerpc64__) || \
+ defined(__ia64__) || defined(__alpha__) || \
+ ( defined(__sparc__) && defined(__arch64__) ) || \
+ defined(__s390x__) || defined(__mips64) )
+ #if !defined(MBEDCRYPTO_HAVE_INT64)
+ #define MBEDCRYPTO_HAVE_INT64
+ #endif /* MBEDCRYPTO_HAVE_INT64 */
+ typedef int64_t mbedcrypto_mpi_sint;
+ typedef uint64_t mbedcrypto_mpi_uint;
+ #if !defined(MBEDCRYPTO_NO_UDBL_DIVISION)
+ /* mbedcrypto_t_udbl defined as 128-bit unsigned int */
+ typedef unsigned int mbedcrypto_t_udbl __attribute__((mode(TI)));
+ #define MBEDCRYPTO_HAVE_UDBL
+ #endif /* !MBEDCRYPTO_NO_UDBL_DIVISION */
+ #elif defined(__ARMCC_VERSION) && defined(__aarch64__)
+ /*
+ * __ARMCC_VERSION is defined for both armcc and armclang and
+ * __aarch64__ is only defined by armclang when compiling 64-bit code
+ */
+ #if !defined(MBEDCRYPTO_HAVE_INT64)
+ #define MBEDCRYPTO_HAVE_INT64
+ #endif /* !MBEDCRYPTO_HAVE_INT64 */
+ typedef int64_t mbedcrypto_mpi_sint;
+ typedef uint64_t mbedcrypto_mpi_uint;
+ #if !defined(MBEDCRYPTO_NO_UDBL_DIVISION)
+ /* mbedcrypto_t_udbl defined as 128-bit unsigned int */
+ typedef __uint128_t mbedcrypto_t_udbl;
+ #define MBEDCRYPTO_HAVE_UDBL
+ #endif /* !MBEDCRYPTO_NO_UDBL_DIVISION */
+ #elif defined(MBEDCRYPTO_HAVE_INT64)
+ /* Force 64-bit integers with unknown compiler */
+ typedef int64_t mbedcrypto_mpi_sint;
+ typedef uint64_t mbedcrypto_mpi_uint;
+ #endif
+#endif /* !MBEDCRYPTO_HAVE_INT32 */
+
+#if !defined(MBEDCRYPTO_HAVE_INT64)
+ /* Default to 32-bit compilation */
+ #if !defined(MBEDCRYPTO_HAVE_INT32)
+ #define MBEDCRYPTO_HAVE_INT32
+ #endif /* !MBEDCRYPTO_HAVE_INT32 */
+ typedef int32_t mbedcrypto_mpi_sint;
+ typedef uint32_t mbedcrypto_mpi_uint;
+ #if !defined(MBEDCRYPTO_NO_UDBL_DIVISION)
+ typedef uint64_t mbedcrypto_t_udbl;
+ #define MBEDCRYPTO_HAVE_UDBL
+ #endif /* !MBEDCRYPTO_NO_UDBL_DIVISION */
+#endif /* !MBEDCRYPTO_HAVE_INT64 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief MPI structure
+ */
+typedef struct
+{
+ int s; /*!< integer sign */
+ size_t n; /*!< total # of limbs */
+ mbedcrypto_mpi_uint *p; /*!< pointer to limbs */
+}
+mbedcrypto_mpi;
+
+/**
+ * \brief Initialize one MPI (make internal references valid)
+ * This just makes it ready to be set or freed,
+ * but does not define a value for the MPI.
+ *
+ * \param X One MPI to initialize.
+ */
+void mbedcrypto_mpi_init( mbedcrypto_mpi *X );
+
+/**
+ * \brief Unallocate one MPI
+ *
+ * \param X One MPI to unallocate.
+ */
+void mbedcrypto_mpi_free( mbedcrypto_mpi *X );
+
+/**
+ * \brief Enlarge to the specified number of limbs
+ *
+ * This function does nothing if the MPI is already large enough.
+ *
+ * \param X MPI to grow
+ * \param nblimbs The target number of limbs
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_grow( mbedcrypto_mpi *X, size_t nblimbs );
+
+/**
+ * \brief Resize down, keeping at least the specified number of limbs
+ *
+ * If \c X is smaller than \c nblimbs, it is resized up
+ * instead.
+ *
+ * \param X MPI to shrink
+ * \param nblimbs The minimum number of limbs to keep
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ * (this can only happen when resizing up).
+ */
+int mbedcrypto_mpi_shrink( mbedcrypto_mpi *X, size_t nblimbs );
+
+/**
+ * \brief Copy the contents of Y into X
+ *
+ * \param X Destination MPI. It is enlarged if necessary.
+ * \param Y Source MPI.
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_copy( mbedcrypto_mpi *X, const mbedcrypto_mpi *Y );
+
+/**
+ * \brief Swap the contents of X and Y
+ *
+ * \param X First MPI value
+ * \param Y Second MPI value
+ */
+void mbedcrypto_mpi_swap( mbedcrypto_mpi *X, mbedcrypto_mpi *Y );
+
+/**
+ * \brief Safe conditional assignement X = Y if assign is 1
+ *
+ * \param X MPI to conditionally assign to
+ * \param Y Value to be assigned
+ * \param assign 1: perform the assignment, 0: keep X's original value
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *
+ * \note This function is equivalent to
+ * if( assign ) mbedcrypto_mpi_copy( X, Y );
+ * except that it avoids leaking any information about whether
+ * the assignment was done or not (the above code may leak
+ * information through branch prediction and/or memory access
+ * patterns analysis).
+ */
+int mbedcrypto_mpi_safe_cond_assign( mbedcrypto_mpi *X, const mbedcrypto_mpi *Y, unsigned char assign );
+
+/**
+ * \brief Safe conditional swap X <-> Y if swap is 1
+ *
+ * \param X First mbedcrypto_mpi value
+ * \param Y Second mbedcrypto_mpi value
+ * \param assign 1: perform the swap, 0: keep X and Y's original values
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ *
+ * \note This function is equivalent to
+ * if( assign ) mbedcrypto_mpi_swap( X, Y );
+ * except that it avoids leaking any information about whether
+ * the assignment was done or not (the above code may leak
+ * information through branch prediction and/or memory access
+ * patterns analysis).
+ */
+int mbedcrypto_mpi_safe_cond_swap( mbedcrypto_mpi *X, mbedcrypto_mpi *Y, unsigned char assign );
+
+/**
+ * \brief Set value from integer
+ *
+ * \param X MPI to set
+ * \param z Value to use
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_lset( mbedcrypto_mpi *X, mbedcrypto_mpi_sint z );
+
+/**
+ * \brief Get a specific bit from X
+ *
+ * \param X MPI to use
+ * \param pos Zero-based index of the bit in X
+ *
+ * \return Either a 0 or a 1
+ */
+int mbedcrypto_mpi_get_bit( const mbedcrypto_mpi *X, size_t pos );
+
+/**
+ * \brief Set a bit of X to a specific value of 0 or 1
+ *
+ * \note Will grow X if necessary to set a bit to 1 in a not yet
+ * existing limb. Will not grow if bit should be set to 0
+ *
+ * \param X MPI to use
+ * \param pos Zero-based index of the bit in X
+ * \param val The value to set the bit to (0 or 1)
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
+ */
+int mbedcrypto_mpi_set_bit( mbedcrypto_mpi *X, size_t pos, unsigned char val );
+
+/**
+ * \brief Return the number of zero-bits before the least significant
+ * '1' bit
+ *
+ * Note: Thus also the zero-based index of the least significant '1' bit
+ *
+ * \param X MPI to use
+ */
+size_t mbedcrypto_mpi_lsb( const mbedcrypto_mpi *X );
+
+/**
+ * \brief Return the number of bits up to and including the most
+ * significant '1' bit'
+ *
+ * Note: Thus also the one-based index of the most significant '1' bit
+ *
+ * \param X MPI to use
+ */
+size_t mbedcrypto_mpi_bitlen( const mbedcrypto_mpi *X );
+
+/**
+ * \brief Return the total size in bytes
+ *
+ * \param X MPI to use
+ */
+size_t mbedcrypto_mpi_size( const mbedcrypto_mpi *X );
+
+/**
+ * \brief Import from an ASCII string
+ *
+ * \param X Destination MPI
+ * \param radix Input numeric base
+ * \param s Null-terminated string buffer
+ *
+ * \return 0 if successful, or a MBEDCRYPTO_ERR_MPI_XXX error code
+ */
+int mbedcrypto_mpi_read_string( mbedcrypto_mpi *X, int radix, const char *s );
+
+/**
+ * \brief Export into an ASCII string
+ *
+ * \param X Source MPI
+ * \param radix Output numeric base
+ * \param buf Buffer to write the string to
+ * \param buflen Length of buf
+ * \param olen Length of the string written, including final NUL byte
+ *
+ * \return 0 if successful, or a MBEDCRYPTO_ERR_MPI_XXX error code.
+ * *olen is always updated to reflect the amount
+ * of data that has (or would have) been written.
+ *
+ * \note Call this function with buflen = 0 to obtain the
+ * minimum required buffer size in *olen.
+ */
+int mbedcrypto_mpi_write_string( const mbedcrypto_mpi *X, int radix,
+ char *buf, size_t buflen, size_t *olen );
+
+#if defined(MBEDCRYPTO_FS_IO)
+/**
+ * \brief Read MPI from a line in an opened file
+ *
+ * \param X Destination MPI
+ * \param radix Input numeric base
+ * \param fin Input file handle
+ *
+ * \return 0 if successful, MBEDCRYPTO_ERR_MPI_BUFFER_TOO_SMALL if
+ * the file read buffer is too small or a
+ * MBEDCRYPTO_ERR_MPI_XXX error code
+ *
+ * \note On success, this function advances the file stream
+ * to the end of the current line or to EOF.
+ *
+ * The function returns 0 on an empty line.
+ *
+ * Leading whitespaces are ignored, as is a
+ * '0x' prefix for radix 16.
+ *
+ */
+int mbedcrypto_mpi_read_file( mbedcrypto_mpi *X, int radix, FILE *fin );
+
+/**
+ * \brief Write X into an opened file, or stdout if fout is NULL
+ *
+ * \param p Prefix, can be NULL
+ * \param X Source MPI
+ * \param radix Output numeric base
+ * \param fout Output file handle (can be NULL)
+ *
+ * \return 0 if successful, or a MBEDCRYPTO_ERR_MPI_XXX error code
+ *
+ * \note Set fout == NULL to print X on the console.
+ */
+int mbedcrypto_mpi_write_file( const char *p, const mbedcrypto_mpi *X, int radix, FILE *fout );
+#endif /* MBEDCRYPTO_FS_IO */
+
+/**
+ * \brief Import X from unsigned binary data, big endian
+ *
+ * \param X Destination MPI
+ * \param buf Input buffer
+ * \param buflen Input buffer size
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_read_binary( mbedcrypto_mpi *X, const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief Export X into unsigned binary data, big endian.
+ * Always fills the whole buffer, which will start with zeros
+ * if the number is smaller.
+ *
+ * \param X Source MPI
+ * \param buf Output buffer
+ * \param buflen Output buffer size
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ */
+int mbedcrypto_mpi_write_binary( const mbedcrypto_mpi *X, unsigned char *buf, size_t buflen );
+
+/**
+ * \brief Left-shift: X <<= count
+ *
+ * \param X MPI to shift
+ * \param count Amount to shift
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_shift_l( mbedcrypto_mpi *X, size_t count );
+
+/**
+ * \brief Right-shift: X >>= count
+ *
+ * \param X MPI to shift
+ * \param count Amount to shift
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_shift_r( mbedcrypto_mpi *X, size_t count );
+
+/**
+ * \brief Compare unsigned values
+ *
+ * \param X Left-hand MPI
+ * \param Y Right-hand MPI
+ *
+ * \return 1 if |X| is greater than |Y|,
+ * -1 if |X| is lesser than |Y| or
+ * 0 if |X| is equal to |Y|
+ */
+int mbedcrypto_mpi_cmp_abs( const mbedcrypto_mpi *X, const mbedcrypto_mpi *Y );
+
+/**
+ * \brief Compare signed values
+ *
+ * \param X Left-hand MPI
+ * \param Y Right-hand MPI
+ *
+ * \return 1 if X is greater than Y,
+ * -1 if X is lesser than Y or
+ * 0 if X is equal to Y
+ */
+int mbedcrypto_mpi_cmp_mpi( const mbedcrypto_mpi *X, const mbedcrypto_mpi *Y );
+
+/**
+ * \brief Compare signed values
+ *
+ * \param X Left-hand MPI
+ * \param z The integer value to compare to
+ *
+ * \return 1 if X is greater than z,
+ * -1 if X is lesser than z or
+ * 0 if X is equal to z
+ */
+int mbedcrypto_mpi_cmp_int( const mbedcrypto_mpi *X, mbedcrypto_mpi_sint z );
+
+/**
+ * \brief Unsigned addition: X = |A| + |B|
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_add_abs( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief Unsigned subtraction: X = |A| - |B|
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE if B is greater than A
+ */
+int mbedcrypto_mpi_sub_abs( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief Signed addition: X = A + B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_add_mpi( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief Signed subtraction: X = A - B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_sub_mpi( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief Signed addition: X = A + b
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to add
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_add_int( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b );
+
+/**
+ * \brief Signed subtraction: X = A - b
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The integer value to subtract
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_sub_int( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b );
+
+/**
+ * \brief Baseline multiplication: X = A * B
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_mul_mpi( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief Baseline multiplication: X = A * b
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param b The unsigned integer value to multiply with
+ *
+ * \note b is unsigned
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_mul_int( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, mbedcrypto_mpi_uint b );
+
+/**
+ * \brief Division by mbedcrypto_mpi: A = Q * B + R
+ *
+ * \param Q Destination MPI for the quotient
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ *
+ * \note Either Q or R can be NULL.
+ */
+int mbedcrypto_mpi_div_mpi( mbedcrypto_mpi *Q, mbedcrypto_mpi *R, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief Division by int: A = Q * b + R
+ *
+ * \param Q Destination MPI for the quotient
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param b Integer to divide by
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ *
+ * \note Either Q or R can be NULL.
+ */
+int mbedcrypto_mpi_div_int( mbedcrypto_mpi *Q, mbedcrypto_mpi *R, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b );
+
+/**
+ * \brief Modulo: R = A mod B
+ *
+ * \param R Destination MPI for the rest value
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO if B == 0,
+ * MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE if B < 0
+ */
+int mbedcrypto_mpi_mod_mpi( mbedcrypto_mpi *R, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief Modulo: r = A mod b
+ *
+ * \param r Destination mbedcrypto_mpi_uint
+ * \param A Left-hand MPI
+ * \param b Integer to divide by
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO if b == 0,
+ * MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE if b < 0
+ */
+int mbedcrypto_mpi_mod_int( mbedcrypto_mpi_uint *r, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b );
+
+/**
+ * \brief Sliding-window exponentiation: X = A^E mod N
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param E Exponent MPI
+ * \param N Modular MPI
+ * \param _RR Speed-up MPI used for recalculations
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA if N is negative or even or
+ * if E is negative
+ *
+ * \note _RR is used to avoid re-computing R*R mod N across
+ * multiple calls, which speeds up things a bit. It can
+ * be set to NULL if the extra performance is unneeded.
+ */
+int mbedcrypto_mpi_exp_mod( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *E, const mbedcrypto_mpi *N, mbedcrypto_mpi *_RR );
+
+/**
+ * \brief Fill an MPI X with size bytes of random
+ *
+ * \param X Destination MPI
+ * \param size Size in bytes
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ *
+ * \note The bytes obtained from the PRNG are interpreted
+ * as a big-endian representation of an MPI; this can
+ * be relevant in applications like deterministic ECDSA.
+ */
+int mbedcrypto_mpi_fill_random( mbedcrypto_mpi *X, size_t size,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Greatest common divisor: G = gcd(A, B)
+ *
+ * \param G Destination MPI
+ * \param A Left-hand MPI
+ * \param B Right-hand MPI
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedcrypto_mpi_gcd( mbedcrypto_mpi *G, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B );
+
+/**
+ * \brief Modular inverse: X = A^-1 mod N
+ *
+ * \param X Destination MPI
+ * \param A Left-hand MPI
+ * \param N Right-hand MPI
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA if N is <= 1,
+ MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N.
+ */
+int mbedcrypto_mpi_inv_mod( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *N );
+
+/**
+ * \brief Miller-Rabin primality test
+ *
+ * \param X MPI to check
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful (probably prime),
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE if X is not prime
+ */
+int mbedcrypto_mpi_is_prime( const mbedcrypto_mpi *X,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Prime number generation
+ *
+ * \param X Destination MPI
+ * \param nbits Required size of X in bits
+ * ( 3 <= nbits <= MBEDCRYPTO_MPI_MAX_BITS )
+ * \param dh_flag If 1, then (X-1)/2 will be prime too
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful (probably prime),
+ * MBEDCRYPTO_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
+ */
+int mbedcrypto_mpi_gen_prime( mbedcrypto_mpi *X, size_t nbits, int dh_flag,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_mpi_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* bignum.h */
diff --git a/include/mbedcrypto/blowfish.h b/include/mbedcrypto/blowfish.h
new file mode 100644
index 0000000..b11c2e8
--- /dev/null
+++ b/include/mbedcrypto/blowfish.h
@@ -0,0 +1,205 @@
+/**
+ * \file blowfish.h
+ *
+ * \brief Blowfish block cipher
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_BLOWFISH_H
+#define MBEDCRYPTO_BLOWFISH_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_BLOWFISH_ENCRYPT 1
+#define MBEDCRYPTO_BLOWFISH_DECRYPT 0
+#define MBEDCRYPTO_BLOWFISH_MAX_KEY_BITS 448
+#define MBEDCRYPTO_BLOWFISH_MIN_KEY_BITS 32
+#define MBEDCRYPTO_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */
+#define MBEDCRYPTO_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */
+
+#define MBEDCRYPTO_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */
+#define MBEDCRYPTO_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */
+#define MBEDCRYPTO_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_BLOWFISH_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief Blowfish context structure
+ */
+typedef struct
+{
+ uint32_t P[MBEDCRYPTO_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */
+ uint32_t S[4][256]; /*!< key dependent S-boxes */
+}
+mbedcrypto_blowfish_context;
+
+#else /* MBEDCRYPTO_BLOWFISH_ALT */
+#include "blowfish_alt.h"
+#endif /* MBEDCRYPTO_BLOWFISH_ALT */
+
+/**
+ * \brief Initialize Blowfish context
+ *
+ * \param ctx Blowfish context to be initialized
+ */
+void mbedcrypto_blowfish_init( mbedcrypto_blowfish_context *ctx );
+
+/**
+ * \brief Clear Blowfish context
+ *
+ * \param ctx Blowfish context to be cleared
+ */
+void mbedcrypto_blowfish_free( mbedcrypto_blowfish_context *ctx );
+
+/**
+ * \brief Blowfish key schedule
+ *
+ * \param ctx Blowfish context to be initialized
+ * \param key encryption key
+ * \param keybits must be between 32 and 448 bits
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_BLOWFISH_INVALID_KEY_LENGTH
+ */
+int mbedcrypto_blowfish_setkey( mbedcrypto_blowfish_context *ctx, const unsigned char *key,
+ unsigned int keybits );
+
+/**
+ * \brief Blowfish-ECB block encryption/decryption
+ *
+ * \param ctx Blowfish context
+ * \param mode MBEDCRYPTO_BLOWFISH_ENCRYPT or MBEDCRYPTO_BLOWFISH_DECRYPT
+ * \param input 8-byte input block
+ * \param output 8-byte output block
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_blowfish_crypt_ecb( mbedcrypto_blowfish_context *ctx,
+ int mode,
+ const unsigned char input[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+ unsigned char output[MBEDCRYPTO_BLOWFISH_BLOCKSIZE] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief Blowfish-CBC buffer encryption/decryption
+ * Length should be a multiple of the block
+ * size (8 bytes)
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the function same function again on the following
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If on the other hand you need to retain the contents of the
+ * IV, you should either save it manually or use the cipher
+ * module instead.
+ *
+ * \param ctx Blowfish context
+ * \param mode MBEDCRYPTO_BLOWFISH_ENCRYPT or MBEDCRYPTO_BLOWFISH_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or
+ * MBEDCRYPTO_ERR_BLOWFISH_INVALID_INPUT_LENGTH
+ */
+int mbedcrypto_blowfish_crypt_cbc( mbedcrypto_blowfish_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+/**
+ * \brief Blowfish CFB buffer encryption/decryption.
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the function same function again on the following
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If on the other hand you need to retain the contents of the
+ * IV, you should either save it manually or use the cipher
+ * module instead.
+ *
+ * \param ctx Blowfish context
+ * \param mode MBEDCRYPTO_BLOWFISH_ENCRYPT or MBEDCRYPTO_BLOWFISH_DECRYPT
+ * \param length length of the input data
+ * \param iv_off offset in IV (updated after use)
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_blowfish_crypt_cfb64( mbedcrypto_blowfish_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /*MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/**
+ * \brief Blowfish-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * \param ctx Blowfish context
+ * \param length The length of the data
+ * \param nc_off The offset in the current stream_block (for resuming
+ * within current cipher stream). The offset pointer to
+ * should be 0 at the start of a stream.
+ * \param nonce_counter The 64-bit nonce and counter.
+ * \param stream_block The saved stream-block for resuming. Is overwritten
+ * by the function.
+ * \param input The input data stream
+ * \param output The output data stream
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_blowfish_crypt_ctr( mbedcrypto_blowfish_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+ unsigned char stream_block[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* blowfish.h */
diff --git a/include/mbedcrypto/bn_mul.h b/include/mbedcrypto/bn_mul.h
new file mode 100644
index 0000000..7d70c2e
--- /dev/null
+++ b/include/mbedcrypto/bn_mul.h
@@ -0,0 +1,886 @@
+/**
+ * \file bn_mul.h
+ *
+ * \brief Multi-precision integer library
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * Multiply source vector [s] with b, add result
+ * to destination vector [d] and set carry c.
+ *
+ * Currently supports:
+ *
+ * . IA-32 (386+) . AMD64 / EM64T
+ * . IA-32 (SSE2) . Motorola 68000
+ * . PowerPC, 32-bit . MicroBlaze
+ * . PowerPC, 64-bit . TriCore
+ * . SPARC v8 . ARM v3+
+ * . Alpha . MIPS32
+ * . C, longlong . C, generic
+ */
+#ifndef MBEDCRYPTO_BN_MUL_H
+#define MBEDCRYPTO_BN_MUL_H
+
+#include "bignum.h"
+
+#if defined(MBEDCRYPTO_HAVE_ASM)
+
+#ifndef asm
+#define asm __asm
+#endif
+
+/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
+#if defined(__GNUC__) && \
+ ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
+#if defined(__i386__)
+
+#define MULADDC_INIT \
+ asm( \
+ "movl %%ebx, %0 \n\t" \
+ "movl %5, %%esi \n\t" \
+ "movl %6, %%edi \n\t" \
+ "movl %7, %%ecx \n\t" \
+ "movl %8, %%ebx \n\t"
+
+#define MULADDC_CORE \
+ "lodsl \n\t" \
+ "mull %%ebx \n\t" \
+ "addl %%ecx, %%eax \n\t" \
+ "adcl $0, %%edx \n\t" \
+ "addl (%%edi), %%eax \n\t" \
+ "adcl $0, %%edx \n\t" \
+ "movl %%edx, %%ecx \n\t" \
+ "stosl \n\t"
+
+#if defined(MBEDCRYPTO_HAVE_SSE2)
+
+#define MULADDC_HUIT \
+ "movd %%ecx, %%mm1 \n\t" \
+ "movd %%ebx, %%mm0 \n\t" \
+ "movd (%%edi), %%mm3 \n\t" \
+ "paddq %%mm3, %%mm1 \n\t" \
+ "movd (%%esi), %%mm2 \n\t" \
+ "pmuludq %%mm0, %%mm2 \n\t" \
+ "movd 4(%%esi), %%mm4 \n\t" \
+ "pmuludq %%mm0, %%mm4 \n\t" \
+ "movd 8(%%esi), %%mm6 \n\t" \
+ "pmuludq %%mm0, %%mm6 \n\t" \
+ "movd 12(%%esi), %%mm7 \n\t" \
+ "pmuludq %%mm0, %%mm7 \n\t" \
+ "paddq %%mm2, %%mm1 \n\t" \
+ "movd 4(%%edi), %%mm3 \n\t" \
+ "paddq %%mm4, %%mm3 \n\t" \
+ "movd 8(%%edi), %%mm5 \n\t" \
+ "paddq %%mm6, %%mm5 \n\t" \
+ "movd 12(%%edi), %%mm4 \n\t" \
+ "paddq %%mm4, %%mm7 \n\t" \
+ "movd %%mm1, (%%edi) \n\t" \
+ "movd 16(%%esi), %%mm2 \n\t" \
+ "pmuludq %%mm0, %%mm2 \n\t" \
+ "psrlq $32, %%mm1 \n\t" \
+ "movd 20(%%esi), %%mm4 \n\t" \
+ "pmuludq %%mm0, %%mm4 \n\t" \
+ "paddq %%mm3, %%mm1 \n\t" \
+ "movd 24(%%esi), %%mm6 \n\t" \
+ "pmuludq %%mm0, %%mm6 \n\t" \
+ "movd %%mm1, 4(%%edi) \n\t" \
+ "psrlq $32, %%mm1 \n\t" \
+ "movd 28(%%esi), %%mm3 \n\t" \
+ "pmuludq %%mm0, %%mm3 \n\t" \
+ "paddq %%mm5, %%mm1 \n\t" \
+ "movd 16(%%edi), %%mm5 \n\t" \
+ "paddq %%mm5, %%mm2 \n\t" \
+ "movd %%mm1, 8(%%edi) \n\t" \
+ "psrlq $32, %%mm1 \n\t" \
+ "paddq %%mm7, %%mm1 \n\t" \
+ "movd 20(%%edi), %%mm5 \n\t" \
+ "paddq %%mm5, %%mm4 \n\t" \
+ "movd %%mm1, 12(%%edi) \n\t" \
+ "psrlq $32, %%mm1 \n\t" \
+ "paddq %%mm2, %%mm1 \n\t" \
+ "movd 24(%%edi), %%mm5 \n\t" \
+ "paddq %%mm5, %%mm6 \n\t" \
+ "movd %%mm1, 16(%%edi) \n\t" \
+ "psrlq $32, %%mm1 \n\t" \
+ "paddq %%mm4, %%mm1 \n\t" \
+ "movd 28(%%edi), %%mm5 \n\t" \
+ "paddq %%mm5, %%mm3 \n\t" \
+ "movd %%mm1, 20(%%edi) \n\t" \
+ "psrlq $32, %%mm1 \n\t" \
+ "paddq %%mm6, %%mm1 \n\t" \
+ "movd %%mm1, 24(%%edi) \n\t" \
+ "psrlq $32, %%mm1 \n\t" \
+ "paddq %%mm3, %%mm1 \n\t" \
+ "movd %%mm1, 28(%%edi) \n\t" \
+ "addl $32, %%edi \n\t" \
+ "addl $32, %%esi \n\t" \
+ "psrlq $32, %%mm1 \n\t" \
+ "movd %%mm1, %%ecx \n\t"
+
+#define MULADDC_STOP \
+ "emms \n\t" \
+ "movl %4, %%ebx \n\t" \
+ "movl %%ecx, %1 \n\t" \
+ "movl %%edi, %2 \n\t" \
+ "movl %%esi, %3 \n\t" \
+ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "eax", "ecx", "edx", "esi", "edi" \
+ );
+
+#else
+
+#define MULADDC_STOP \
+ "movl %4, %%ebx \n\t" \
+ "movl %%ecx, %1 \n\t" \
+ "movl %%edi, %2 \n\t" \
+ "movl %%esi, %3 \n\t" \
+ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "eax", "ecx", "edx", "esi", "edi" \
+ );
+#endif /* SSE2 */
+#endif /* i386 */
+
+#if defined(__amd64__) || defined (__x86_64__)
+
+#define MULADDC_INIT \
+ asm( \
+ "xorq %%r8, %%r8 \n\t"
+
+#define MULADDC_CORE \
+ "movq (%%rsi), %%rax \n\t" \
+ "mulq %%rbx \n\t" \
+ "addq $8, %%rsi \n\t" \
+ "addq %%rcx, %%rax \n\t" \
+ "movq %%r8, %%rcx \n\t" \
+ "adcq $0, %%rdx \n\t" \
+ "nop \n\t" \
+ "addq %%rax, (%%rdi) \n\t" \
+ "adcq %%rdx, %%rcx \n\t" \
+ "addq $8, %%rdi \n\t"
+
+#define MULADDC_STOP \
+ : "+c" (c), "+D" (d), "+S" (s) \
+ : "b" (b) \
+ : "rax", "rdx", "r8" \
+ );
+
+#endif /* AMD64 */
+
+#if defined(__mc68020__) || defined(__mcpu32__)
+
+#define MULADDC_INIT \
+ asm( \
+ "movl %3, %%a2 \n\t" \
+ "movl %4, %%a3 \n\t" \
+ "movl %5, %%d3 \n\t" \
+ "movl %6, %%d2 \n\t" \
+ "moveq #0, %%d0 \n\t"
+
+#define MULADDC_CORE \
+ "movel %%a2@+, %%d1 \n\t" \
+ "mulul %%d2, %%d4:%%d1 \n\t" \
+ "addl %%d3, %%d1 \n\t" \
+ "addxl %%d0, %%d4 \n\t" \
+ "moveq #0, %%d3 \n\t" \
+ "addl %%d1, %%a3@+ \n\t" \
+ "addxl %%d4, %%d3 \n\t"
+
+#define MULADDC_STOP \
+ "movl %%d3, %0 \n\t" \
+ "movl %%a3, %1 \n\t" \
+ "movl %%a2, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \
+ );
+
+#define MULADDC_HUIT \
+ "movel %%a2@+, %%d1 \n\t" \
+ "mulul %%d2, %%d4:%%d1 \n\t" \
+ "addxl %%d3, %%d1 \n\t" \
+ "addxl %%d0, %%d4 \n\t" \
+ "addl %%d1, %%a3@+ \n\t" \
+ "movel %%a2@+, %%d1 \n\t" \
+ "mulul %%d2, %%d3:%%d1 \n\t" \
+ "addxl %%d4, %%d1 \n\t" \
+ "addxl %%d0, %%d3 \n\t" \
+ "addl %%d1, %%a3@+ \n\t" \
+ "movel %%a2@+, %%d1 \n\t" \
+ "mulul %%d2, %%d4:%%d1 \n\t" \
+ "addxl %%d3, %%d1 \n\t" \
+ "addxl %%d0, %%d4 \n\t" \
+ "addl %%d1, %%a3@+ \n\t" \
+ "movel %%a2@+, %%d1 \n\t" \
+ "mulul %%d2, %%d3:%%d1 \n\t" \
+ "addxl %%d4, %%d1 \n\t" \
+ "addxl %%d0, %%d3 \n\t" \
+ "addl %%d1, %%a3@+ \n\t" \
+ "movel %%a2@+, %%d1 \n\t" \
+ "mulul %%d2, %%d4:%%d1 \n\t" \
+ "addxl %%d3, %%d1 \n\t" \
+ "addxl %%d0, %%d4 \n\t" \
+ "addl %%d1, %%a3@+ \n\t" \
+ "movel %%a2@+, %%d1 \n\t" \
+ "mulul %%d2, %%d3:%%d1 \n\t" \
+ "addxl %%d4, %%d1 \n\t" \
+ "addxl %%d0, %%d3 \n\t" \
+ "addl %%d1, %%a3@+ \n\t" \
+ "movel %%a2@+, %%d1 \n\t" \
+ "mulul %%d2, %%d4:%%d1 \n\t" \
+ "addxl %%d3, %%d1 \n\t" \
+ "addxl %%d0, %%d4 \n\t" \
+ "addl %%d1, %%a3@+ \n\t" \
+ "movel %%a2@+, %%d1 \n\t" \
+ "mulul %%d2, %%d3:%%d1 \n\t" \
+ "addxl %%d4, %%d1 \n\t" \
+ "addxl %%d0, %%d3 \n\t" \
+ "addl %%d1, %%a3@+ \n\t" \
+ "addxl %%d0, %%d3 \n\t"
+
+#endif /* MC68000 */
+
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT \
+ asm( \
+ "ld r3, %3 \n\t" \
+ "ld r4, %4 \n\t" \
+ "ld r5, %5 \n\t" \
+ "ld r6, %6 \n\t" \
+ "addi r3, r3, -8 \n\t" \
+ "addi r4, r4, -8 \n\t" \
+ "addic r5, r5, 0 \n\t"
+
+#define MULADDC_CORE \
+ "ldu r7, 8(r3) \n\t" \
+ "mulld r8, r7, r6 \n\t" \
+ "mulhdu r9, r7, r6 \n\t" \
+ "adde r8, r8, r5 \n\t" \
+ "ld r7, 8(r4) \n\t" \
+ "addze r5, r9 \n\t" \
+ "addc r8, r8, r7 \n\t" \
+ "stdu r8, 8(r4) \n\t"
+
+#define MULADDC_STOP \
+ "addze r5, r5 \n\t" \
+ "addi r4, r4, 8 \n\t" \
+ "addi r3, r3, 8 \n\t" \
+ "std r5, %0 \n\t" \
+ "std r4, %1 \n\t" \
+ "std r3, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
+ );
+
+
+#else /* __MACH__ && __APPLE__ */
+
+#define MULADDC_INIT \
+ asm( \
+ "ld %%r3, %3 \n\t" \
+ "ld %%r4, %4 \n\t" \
+ "ld %%r5, %5 \n\t" \
+ "ld %%r6, %6 \n\t" \
+ "addi %%r3, %%r3, -8 \n\t" \
+ "addi %%r4, %%r4, -8 \n\t" \
+ "addic %%r5, %%r5, 0 \n\t"
+
+#define MULADDC_CORE \
+ "ldu %%r7, 8(%%r3) \n\t" \
+ "mulld %%r8, %%r7, %%r6 \n\t" \
+ "mulhdu %%r9, %%r7, %%r6 \n\t" \
+ "adde %%r8, %%r8, %%r5 \n\t" \
+ "ld %%r7, 8(%%r4) \n\t" \
+ "addze %%r5, %%r9 \n\t" \
+ "addc %%r8, %%r8, %%r7 \n\t" \
+ "stdu %%r8, 8(%%r4) \n\t"
+
+#define MULADDC_STOP \
+ "addze %%r5, %%r5 \n\t" \
+ "addi %%r4, %%r4, 8 \n\t" \
+ "addi %%r3, %%r3, 8 \n\t" \
+ "std %%r5, %0 \n\t" \
+ "std %%r4, %1 \n\t" \
+ "std %%r3, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
+ );
+
+#endif /* __MACH__ && __APPLE__ */
+
+#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT \
+ asm( \
+ "lwz r3, %3 \n\t" \
+ "lwz r4, %4 \n\t" \
+ "lwz r5, %5 \n\t" \
+ "lwz r6, %6 \n\t" \
+ "addi r3, r3, -4 \n\t" \
+ "addi r4, r4, -4 \n\t" \
+ "addic r5, r5, 0 \n\t"
+
+#define MULADDC_CORE \
+ "lwzu r7, 4(r3) \n\t" \
+ "mullw r8, r7, r6 \n\t" \
+ "mulhwu r9, r7, r6 \n\t" \
+ "adde r8, r8, r5 \n\t" \
+ "lwz r7, 4(r4) \n\t" \
+ "addze r5, r9 \n\t" \
+ "addc r8, r8, r7 \n\t" \
+ "stwu r8, 4(r4) \n\t"
+
+#define MULADDC_STOP \
+ "addze r5, r5 \n\t" \
+ "addi r4, r4, 4 \n\t" \
+ "addi r3, r3, 4 \n\t" \
+ "stw r5, %0 \n\t" \
+ "stw r4, %1 \n\t" \
+ "stw r3, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
+ );
+
+#else /* __MACH__ && __APPLE__ */
+
+#define MULADDC_INIT \
+ asm( \
+ "lwz %%r3, %3 \n\t" \
+ "lwz %%r4, %4 \n\t" \
+ "lwz %%r5, %5 \n\t" \
+ "lwz %%r6, %6 \n\t" \
+ "addi %%r3, %%r3, -4 \n\t" \
+ "addi %%r4, %%r4, -4 \n\t" \
+ "addic %%r5, %%r5, 0 \n\t"
+
+#define MULADDC_CORE \
+ "lwzu %%r7, 4(%%r3) \n\t" \
+ "mullw %%r8, %%r7, %%r6 \n\t" \
+ "mulhwu %%r9, %%r7, %%r6 \n\t" \
+ "adde %%r8, %%r8, %%r5 \n\t" \
+ "lwz %%r7, 4(%%r4) \n\t" \
+ "addze %%r5, %%r9 \n\t" \
+ "addc %%r8, %%r8, %%r7 \n\t" \
+ "stwu %%r8, 4(%%r4) \n\t"
+
+#define MULADDC_STOP \
+ "addze %%r5, %%r5 \n\t" \
+ "addi %%r4, %%r4, 4 \n\t" \
+ "addi %%r3, %%r3, 4 \n\t" \
+ "stw %%r5, %0 \n\t" \
+ "stw %%r4, %1 \n\t" \
+ "stw %%r3, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
+ );
+
+#endif /* __MACH__ && __APPLE__ */
+
+#endif /* PPC32 */
+
+/*
+ * The Sparc(64) assembly is reported to be broken.
+ * Disable it for now, until we're able to fix it.
+ */
+#if 0 && defined(__sparc__)
+#if defined(__sparc64__)
+
+#define MULADDC_INIT \
+ asm( \
+ "ldx %3, %%o0 \n\t" \
+ "ldx %4, %%o1 \n\t" \
+ "ld %5, %%o2 \n\t" \
+ "ld %6, %%o3 \n\t"
+
+#define MULADDC_CORE \
+ "ld [%%o0], %%o4 \n\t" \
+ "inc 4, %%o0 \n\t" \
+ "ld [%%o1], %%o5 \n\t" \
+ "umul %%o3, %%o4, %%o4 \n\t" \
+ "addcc %%o4, %%o2, %%o4 \n\t" \
+ "rd %%y, %%g1 \n\t" \
+ "addx %%g1, 0, %%g1 \n\t" \
+ "addcc %%o4, %%o5, %%o4 \n\t" \
+ "st %%o4, [%%o1] \n\t" \
+ "addx %%g1, 0, %%o2 \n\t" \
+ "inc 4, %%o1 \n\t"
+
+ #define MULADDC_STOP \
+ "st %%o2, %0 \n\t" \
+ "stx %%o1, %1 \n\t" \
+ "stx %%o0, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "g1", "o0", "o1", "o2", "o3", "o4", \
+ "o5" \
+ );
+
+#else /* __sparc64__ */
+
+#define MULADDC_INIT \
+ asm( \
+ "ld %3, %%o0 \n\t" \
+ "ld %4, %%o1 \n\t" \
+ "ld %5, %%o2 \n\t" \
+ "ld %6, %%o3 \n\t"
+
+#define MULADDC_CORE \
+ "ld [%%o0], %%o4 \n\t" \
+ "inc 4, %%o0 \n\t" \
+ "ld [%%o1], %%o5 \n\t" \
+ "umul %%o3, %%o4, %%o4 \n\t" \
+ "addcc %%o4, %%o2, %%o4 \n\t" \
+ "rd %%y, %%g1 \n\t" \
+ "addx %%g1, 0, %%g1 \n\t" \
+ "addcc %%o4, %%o5, %%o4 \n\t" \
+ "st %%o4, [%%o1] \n\t" \
+ "addx %%g1, 0, %%o2 \n\t" \
+ "inc 4, %%o1 \n\t"
+
+#define MULADDC_STOP \
+ "st %%o2, %0 \n\t" \
+ "st %%o1, %1 \n\t" \
+ "st %%o0, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "g1", "o0", "o1", "o2", "o3", "o4", \
+ "o5" \
+ );
+
+#endif /* __sparc64__ */
+#endif /* __sparc__ */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_INIT \
+ asm( \
+ "lwi r3, %3 \n\t" \
+ "lwi r4, %4 \n\t" \
+ "lwi r5, %5 \n\t" \
+ "lwi r6, %6 \n\t" \
+ "andi r7, r6, 0xffff \n\t" \
+ "bsrli r6, r6, 16 \n\t"
+
+#define MULADDC_CORE \
+ "lhui r8, r3, 0 \n\t" \
+ "addi r3, r3, 2 \n\t" \
+ "lhui r9, r3, 0 \n\t" \
+ "addi r3, r3, 2 \n\t" \
+ "mul r10, r9, r6 \n\t" \
+ "mul r11, r8, r7 \n\t" \
+ "mul r12, r9, r7 \n\t" \
+ "mul r13, r8, r6 \n\t" \
+ "bsrli r8, r10, 16 \n\t" \
+ "bsrli r9, r11, 16 \n\t" \
+ "add r13, r13, r8 \n\t" \
+ "add r13, r13, r9 \n\t" \
+ "bslli r10, r10, 16 \n\t" \
+ "bslli r11, r11, 16 \n\t" \
+ "add r12, r12, r10 \n\t" \
+ "addc r13, r13, r0 \n\t" \
+ "add r12, r12, r11 \n\t" \
+ "addc r13, r13, r0 \n\t" \
+ "lwi r10, r4, 0 \n\t" \
+ "add r12, r12, r10 \n\t" \
+ "addc r13, r13, r0 \n\t" \
+ "add r12, r12, r5 \n\t" \
+ "addc r5, r13, r0 \n\t" \
+ "swi r12, r4, 0 \n\t" \
+ "addi r4, r4, 4 \n\t"
+
+#define MULADDC_STOP \
+ "swi r5, %0 \n\t" \
+ "swi r4, %1 \n\t" \
+ "swi r3, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "r3", "r4" "r5", "r6", "r7", "r8", \
+ "r9", "r10", "r11", "r12", "r13" \
+ );
+
+#endif /* MicroBlaze */
+
+#if defined(__tricore__)
+
+#define MULADDC_INIT \
+ asm( \
+ "ld.a %%a2, %3 \n\t" \
+ "ld.a %%a3, %4 \n\t" \
+ "ld.w %%d4, %5 \n\t" \
+ "ld.w %%d1, %6 \n\t" \
+ "xor %%d5, %%d5 \n\t"
+
+#define MULADDC_CORE \
+ "ld.w %%d0, [%%a2+] \n\t" \
+ "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \
+ "ld.w %%d0, [%%a3] \n\t" \
+ "addx %%d2, %%d2, %%d0 \n\t" \
+ "addc %%d3, %%d3, 0 \n\t" \
+ "mov %%d4, %%d3 \n\t" \
+ "st.w [%%a3+], %%d2 \n\t"
+
+#define MULADDC_STOP \
+ "st.w %0, %%d4 \n\t" \
+ "st.a %1, %%a3 \n\t" \
+ "st.a %2, %%a2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "d0", "d1", "e2", "d4", "a2", "a3" \
+ );
+
+#endif /* TriCore */
+
+/*
+ * gcc -O0 by default uses r7 for the frame pointer, so it complains about our
+ * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately,
+ * passing that option is not easy when building with yotta.
+ *
+ * On the other hand, -fomit-frame-pointer is implied by any -Ox options with
+ * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by
+ * clang and armcc5 under the same conditions).
+ *
+ * So, only use the optimized assembly below for optimized build, which avoids
+ * the build error and is pretty reasonable anyway.
+ */
+#if defined(__GNUC__) && !defined(__OPTIMIZE__)
+#define MULADDC_CANNOT_USE_R7
+#endif
+
+#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7)
+
+#if defined(__thumb__) && !defined(__thumb2__)
+
+#define MULADDC_INIT \
+ asm( \
+ "ldr r0, %3 \n\t" \
+ "ldr r1, %4 \n\t" \
+ "ldr r2, %5 \n\t" \
+ "ldr r3, %6 \n\t" \
+ "lsr r7, r3, #16 \n\t" \
+ "mov r9, r7 \n\t" \
+ "lsl r7, r3, #16 \n\t" \
+ "lsr r7, r7, #16 \n\t" \
+ "mov r8, r7 \n\t"
+
+#define MULADDC_CORE \
+ "ldmia r0!, {r6} \n\t" \
+ "lsr r7, r6, #16 \n\t" \
+ "lsl r6, r6, #16 \n\t" \
+ "lsr r6, r6, #16 \n\t" \
+ "mov r4, r8 \n\t" \
+ "mul r4, r6 \n\t" \
+ "mov r3, r9 \n\t" \
+ "mul r6, r3 \n\t" \
+ "mov r5, r9 \n\t" \
+ "mul r5, r7 \n\t" \
+ "mov r3, r8 \n\t" \
+ "mul r7, r3 \n\t" \
+ "lsr r3, r6, #16 \n\t" \
+ "add r5, r5, r3 \n\t" \
+ "lsr r3, r7, #16 \n\t" \
+ "add r5, r5, r3 \n\t" \
+ "add r4, r4, r2 \n\t" \
+ "mov r2, #0 \n\t" \
+ "adc r5, r2 \n\t" \
+ "lsl r3, r6, #16 \n\t" \
+ "add r4, r4, r3 \n\t" \
+ "adc r5, r2 \n\t" \
+ "lsl r3, r7, #16 \n\t" \
+ "add r4, r4, r3 \n\t" \
+ "adc r5, r2 \n\t" \
+ "ldr r3, [r1] \n\t" \
+ "add r4, r4, r3 \n\t" \
+ "adc r2, r5 \n\t" \
+ "stmia r1!, {r4} \n\t"
+
+#define MULADDC_STOP \
+ "str r2, %0 \n\t" \
+ "str r1, %1 \n\t" \
+ "str r0, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "r0", "r1", "r2", "r3", "r4", "r5", \
+ "r6", "r7", "r8", "r9", "cc" \
+ );
+
+#else
+
+#define MULADDC_INIT \
+ asm( \
+ "ldr r0, %3 \n\t" \
+ "ldr r1, %4 \n\t" \
+ "ldr r2, %5 \n\t" \
+ "ldr r3, %6 \n\t"
+
+#define MULADDC_CORE \
+ "ldr r4, [r0], #4 \n\t" \
+ "mov r5, #0 \n\t" \
+ "ldr r6, [r1] \n\t" \
+ "umlal r2, r5, r3, r4 \n\t" \
+ "adds r7, r6, r2 \n\t" \
+ "adc r2, r5, #0 \n\t" \
+ "str r7, [r1], #4 \n\t"
+
+#define MULADDC_STOP \
+ "str r2, %0 \n\t" \
+ "str r1, %1 \n\t" \
+ "str r0, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "r0", "r1", "r2", "r3", "r4", "r5", \
+ "r6", "r7", "cc" \
+ );
+
+#endif /* Thumb */
+
+#endif /* ARMv3 */
+
+#if defined(__alpha__)
+
+#define MULADDC_INIT \
+ asm( \
+ "ldq $1, %3 \n\t" \
+ "ldq $2, %4 \n\t" \
+ "ldq $3, %5 \n\t" \
+ "ldq $4, %6 \n\t"
+
+#define MULADDC_CORE \
+ "ldq $6, 0($1) \n\t" \
+ "addq $1, 8, $1 \n\t" \
+ "mulq $6, $4, $7 \n\t" \
+ "umulh $6, $4, $6 \n\t" \
+ "addq $7, $3, $7 \n\t" \
+ "cmpult $7, $3, $3 \n\t" \
+ "ldq $5, 0($2) \n\t" \
+ "addq $7, $5, $7 \n\t" \
+ "cmpult $7, $5, $5 \n\t" \
+ "stq $7, 0($2) \n\t" \
+ "addq $2, 8, $2 \n\t" \
+ "addq $6, $3, $3 \n\t" \
+ "addq $5, $3, $3 \n\t"
+
+#define MULADDC_STOP \
+ "stq $3, %0 \n\t" \
+ "stq $2, %1 \n\t" \
+ "stq $1, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \
+ );
+#endif /* Alpha */
+
+#if defined(__mips__) && !defined(__mips64)
+
+#define MULADDC_INIT \
+ asm( \
+ "lw $10, %3 \n\t" \
+ "lw $11, %4 \n\t" \
+ "lw $12, %5 \n\t" \
+ "lw $13, %6 \n\t"
+
+#define MULADDC_CORE \
+ "lw $14, 0($10) \n\t" \
+ "multu $13, $14 \n\t" \
+ "addi $10, $10, 4 \n\t" \
+ "mflo $14 \n\t" \
+ "mfhi $9 \n\t" \
+ "addu $14, $12, $14 \n\t" \
+ "lw $15, 0($11) \n\t" \
+ "sltu $12, $14, $12 \n\t" \
+ "addu $15, $14, $15 \n\t" \
+ "sltu $14, $15, $14 \n\t" \
+ "addu $12, $12, $9 \n\t" \
+ "sw $15, 0($11) \n\t" \
+ "addu $12, $12, $14 \n\t" \
+ "addi $11, $11, 4 \n\t"
+
+#define MULADDC_STOP \
+ "sw $12, %0 \n\t" \
+ "sw $11, %1 \n\t" \
+ "sw $10, %2 \n\t" \
+ : "=m" (c), "=m" (d), "=m" (s) \
+ : "m" (s), "m" (d), "m" (c), "m" (b) \
+ : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \
+ );
+
+#endif /* MIPS */
+#endif /* GNUC */
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define MULADDC_INIT \
+ __asm mov esi, s \
+ __asm mov edi, d \
+ __asm mov ecx, c \
+ __asm mov ebx, b
+
+#define MULADDC_CORE \
+ __asm lodsd \
+ __asm mul ebx \
+ __asm add eax, ecx \
+ __asm adc edx, 0 \
+ __asm add eax, [edi] \
+ __asm adc edx, 0 \
+ __asm mov ecx, edx \
+ __asm stosd
+
+#if defined(MBEDCRYPTO_HAVE_SSE2)
+
+#define EMIT __asm _emit
+
+#define MULADDC_HUIT \
+ EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
+ EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x1F \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x6E EMIT 0x16 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
+ EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
+ EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
+ EMIT 0x0F EMIT 0x7E EMIT 0x0F \
+ EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
+ EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
+ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
+ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
+ EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
+ EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
+ EMIT 0x0F EMIT 0x7E EMIT 0xC9
+
+#define MULADDC_STOP \
+ EMIT 0x0F EMIT 0x77 \
+ __asm mov c, ecx \
+ __asm mov d, edi \
+ __asm mov s, esi \
+
+#else
+
+#define MULADDC_STOP \
+ __asm mov c, ecx \
+ __asm mov d, edi \
+ __asm mov s, esi \
+
+#endif /* SSE2 */
+#endif /* MSVC */
+
+#endif /* MBEDCRYPTO_HAVE_ASM */
+
+#if !defined(MULADDC_CORE)
+#if defined(MBEDCRYPTO_HAVE_UDBL)
+
+#define MULADDC_INIT \
+{ \
+ mbedcrypto_t_udbl r; \
+ mbedcrypto_mpi_uint r0, r1;
+
+#define MULADDC_CORE \
+ r = *(s++) * (mbedcrypto_t_udbl) b; \
+ r0 = (mbedcrypto_mpi_uint) r; \
+ r1 = (mbedcrypto_mpi_uint)( r >> biL ); \
+ r0 += c; r1 += (r0 < c); \
+ r0 += *d; r1 += (r0 < *d); \
+ c = r1; *(d++) = r0;
+
+#define MULADDC_STOP \
+}
+
+#else
+#define MULADDC_INIT \
+{ \
+ mbedcrypto_mpi_uint s0, s1, b0, b1; \
+ mbedcrypto_mpi_uint r0, r1, rx, ry; \
+ b0 = ( b << biH ) >> biH; \
+ b1 = ( b >> biH );
+
+#define MULADDC_CORE \
+ s0 = ( *s << biH ) >> biH; \
+ s1 = ( *s >> biH ); s++; \
+ rx = s0 * b1; r0 = s0 * b0; \
+ ry = s1 * b0; r1 = s1 * b1; \
+ r1 += ( rx >> biH ); \
+ r1 += ( ry >> biH ); \
+ rx <<= biH; ry <<= biH; \
+ r0 += rx; r1 += (r0 < rx); \
+ r0 += ry; r1 += (r0 < ry); \
+ r0 += c; r1 += (r0 < c); \
+ r0 += *d; r1 += (r0 < *d); \
+ c = r1; *(d++) = r0;
+
+#define MULADDC_STOP \
+}
+
+#endif /* C (generic) */
+#endif /* C (longlong) */
+
+#endif /* bn_mul.h */
diff --git a/include/mbedcrypto/camellia.h b/include/mbedcrypto/camellia.h
new file mode 100644
index 0000000..21607e2
--- /dev/null
+++ b/include/mbedcrypto/camellia.h
@@ -0,0 +1,229 @@
+/**
+ * \file camellia.h
+ *
+ * \brief Camellia block cipher
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_CAMELLIA_H
+#define MBEDCRYPTO_CAMELLIA_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_CAMELLIA_ENCRYPT 1
+#define MBEDCRYPTO_CAMELLIA_DECRYPT 0
+
+#define MBEDCRYPTO_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */
+#define MBEDCRYPTO_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */
+#define MBEDCRYPTO_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_CAMELLIA_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief CAMELLIA context structure
+ */
+typedef struct
+{
+ int nr; /*!< number of rounds */
+ uint32_t rk[68]; /*!< CAMELLIA round keys */
+}
+mbedcrypto_camellia_context;
+
+#else /* MBEDCRYPTO_CAMELLIA_ALT */
+#include "camellia_alt.h"
+#endif /* MBEDCRYPTO_CAMELLIA_ALT */
+
+/**
+ * \brief Initialize CAMELLIA context
+ *
+ * \param ctx CAMELLIA context to be initialized
+ */
+void mbedcrypto_camellia_init( mbedcrypto_camellia_context *ctx );
+
+/**
+ * \brief Clear CAMELLIA context
+ *
+ * \param ctx CAMELLIA context to be cleared
+ */
+void mbedcrypto_camellia_free( mbedcrypto_camellia_context *ctx );
+
+/**
+ * \brief CAMELLIA key schedule (encryption)
+ *
+ * \param ctx CAMELLIA context to be initialized
+ * \param key encryption key
+ * \param keybits must be 128, 192 or 256
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int mbedcrypto_camellia_setkey_enc( mbedcrypto_camellia_context *ctx, const unsigned char *key,
+ unsigned int keybits );
+
+/**
+ * \brief CAMELLIA key schedule (decryption)
+ *
+ * \param ctx CAMELLIA context to be initialized
+ * \param key decryption key
+ * \param keybits must be 128, 192 or 256
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_CAMELLIA_INVALID_KEY_LENGTH
+ */
+int mbedcrypto_camellia_setkey_dec( mbedcrypto_camellia_context *ctx, const unsigned char *key,
+ unsigned int keybits );
+
+/**
+ * \brief CAMELLIA-ECB block encryption/decryption
+ *
+ * \param ctx CAMELLIA context
+ * \param mode MBEDCRYPTO_CAMELLIA_ENCRYPT or MBEDCRYPTO_CAMELLIA_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_camellia_crypt_ecb( mbedcrypto_camellia_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief CAMELLIA-CBC buffer encryption/decryption
+ * Length should be a multiple of the block
+ * size (16 bytes)
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the function same function again on the following
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If on the other hand you need to retain the contents of the
+ * IV, you should either save it manually or use the cipher
+ * module instead.
+ *
+ * \param ctx CAMELLIA context
+ * \param mode MBEDCRYPTO_CAMELLIA_ENCRYPT or MBEDCRYPTO_CAMELLIA_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or
+ * MBEDCRYPTO_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int mbedcrypto_camellia_crypt_cbc( mbedcrypto_camellia_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+/**
+ * \brief CAMELLIA-CFB128 buffer encryption/decryption
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * mbedcrypto_camellia_setkey_enc() for both MBEDCRYPTO_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT.
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the function same function again on the following
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If on the other hand you need to retain the contents of the
+ * IV, you should either save it manually or use the cipher
+ * module instead.
+ *
+ * \param ctx CAMELLIA context
+ * \param mode MBEDCRYPTO_CAMELLIA_ENCRYPT or MBEDCRYPTO_CAMELLIA_DECRYPT
+ * \param length length of the input data
+ * \param iv_off offset in IV (updated after use)
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or
+ * MBEDCRYPTO_ERR_CAMELLIA_INVALID_INPUT_LENGTH
+ */
+int mbedcrypto_camellia_crypt_cfb128( mbedcrypto_camellia_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/**
+ * \brief CAMELLIA-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * Note: Due to the nature of CTR you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * mbedcrypto_camellia_setkey_enc() for both MBEDCRYPTO_CAMELLIA_ENCRYPT and MBEDCRYPTO_CAMELLIA_DECRYPT.
+ *
+ * \param ctx CAMELLIA context
+ * \param length The length of the data
+ * \param nc_off The offset in the current stream_block (for resuming
+ * within current cipher stream). The offset pointer to
+ * should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block The saved stream-block for resuming. Is overwritten
+ * by the function.
+ * \param input The input data stream
+ * \param output The output data stream
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_camellia_crypt_ctr( mbedcrypto_camellia_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_camellia_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* camellia.h */
diff --git a/include/mbedcrypto/ccm.h b/include/mbedcrypto/ccm.h
new file mode 100644
index 0000000..14e178e
--- /dev/null
+++ b/include/mbedcrypto/ccm.h
@@ -0,0 +1,178 @@
+/**
+ * \file ccm.h
+ *
+ * \brief This file provides an API for the CCM authenticated encryption
+ * mode for block ciphers.
+ *
+ * CCM combines Counter mode encryption with CBC-MAC authentication
+ * for 128-bit block ciphers.
+ *
+ * Input to CCM includes the following elements:
+ * <ul><li>Payload - data that is both authenticated and encrypted.</li>
+ * <li>Associated data (Adata) - data that is authenticated but not
+ * encrypted, For example, a header.</li>
+ * <li>Nonce - A unique value that is assigned to the payload and the
+ * associated data.</li></ul>
+ *
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_CCM_H
+#define MBEDCRYPTO_CCM_H
+
+#include "cipher.h"
+
+#define MBEDCRYPTO_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */
+#define MBEDCRYPTO_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
+#define MBEDCRYPTO_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_CCM_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief The CCM context-type definition. The CCM context is passed
+ * to the APIs called.
+ */
+typedef struct {
+ mbedcrypto_cipher_context_t cipher_ctx; /*!< The cipher context used. */
+}
+mbedcrypto_ccm_context;
+
+#else /* MBEDCRYPTO_CCM_ALT */
+#include "ccm_alt.h"
+#endif /* MBEDCRYPTO_CCM_ALT */
+
+/**
+ * \brief This function initializes the specified CCM context,
+ * to make references valid, and prepare the context
+ * for mbedcrypto_ccm_setkey() or mbedcrypto_ccm_free().
+ *
+ * \param ctx The CCM context to initialize.
+ */
+void mbedcrypto_ccm_init( mbedcrypto_ccm_context *ctx );
+
+/**
+ * \brief This function initializes the CCM context set in the
+ * \p ctx parameter and sets the encryption key.
+ *
+ * \param ctx The CCM context to initialize.
+ * \param cipher The 128-bit block cipher to use.
+ * \param key The encryption key.
+ * \param keybits The key size in bits. This must be acceptable by the cipher.
+ *
+ * \return \c 0 on success.
+ * \return A CCM or cipher-specific error code on failure.
+ */
+int mbedcrypto_ccm_setkey( mbedcrypto_ccm_context *ctx,
+ mbedcrypto_cipher_id_t cipher,
+ const unsigned char *key,
+ unsigned int keybits );
+
+/**
+ * \brief This function releases and clears the specified CCM context
+ * and underlying cipher sub-context.
+ *
+ * \param ctx The CCM context to clear.
+ */
+void mbedcrypto_ccm_free( mbedcrypto_ccm_context *ctx );
+
+/**
+ * \brief This function encrypts a buffer using CCM.
+ *
+ *
+ * \note The tag is written to a separate buffer. To concatenate
+ * the \p tag with the \p output, as done in <em>RFC-3610:
+ * Counter with CBC-MAC (CCM)</em>, use
+ * \p tag = \p output + \p length, and make sure that the
+ * output buffer is at least \p length + \p tag_len wide.
+ *
+ * \param ctx The CCM context to use for encryption.
+ * \param length The length of the input data in Bytes.
+ * \param iv Initialization vector (nonce).
+ * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
+ * \param add The additional data field.
+ * \param add_len The length of additional data in Bytes.
+ * Must be less than 2^16 - 2^8.
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ * Must be at least \p length Bytes wide.
+ * \param tag The buffer holding the tag.
+ * \param tag_len The length of the tag to generate in Bytes:
+ * 4, 6, 8, 10, 12, 14 or 16.
+ *
+ * \return \c 0 on success.
+ * \return A CCM or cipher-specific error code on failure.
+ */
+int mbedcrypto_ccm_encrypt_and_tag( mbedcrypto_ccm_context *ctx, size_t length,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *add, size_t add_len,
+ const unsigned char *input, unsigned char *output,
+ unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief This function performs a CCM authenticated decryption of a
+ * buffer.
+ *
+ * \param ctx The CCM context to use for decryption.
+ * \param length The length of the input data in Bytes.
+ * \param iv Initialization vector.
+ * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
+ * \param add The additional data field.
+ * \param add_len The length of additional data in Bytes.
+ * Must be less than 2^16 - 2^8.
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ * Must be at least \p length Bytes wide.
+ * \param tag The buffer holding the tag.
+ * \param tag_len The length of the tag in Bytes.
+ * 4, 6, 8, 10, 12, 14 or 16.
+ *
+ * \return \c 0 on success. This indicates that the message is authentic.
+ * \return #MBEDCRYPTO_ERR_CCM_AUTH_FAILED if the tag does not match.
+ * \return A cipher-specific error code on calculation failure.
+ */
+int mbedcrypto_ccm_auth_decrypt( mbedcrypto_ccm_context *ctx, size_t length,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *add, size_t add_len,
+ const unsigned char *input, unsigned char *output,
+ const unsigned char *tag, size_t tag_len );
+
+
+#if defined(MBEDCRYPTO_SELF_TEST) && defined(MBEDCRYPTO_AES_C)
+/**
+ * \brief The CCM checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedcrypto_ccm_self_test( int verbose );
+#endif /* MBEDCRYPTO_SELF_TEST && MBEDCRYPTO_AES_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_CCM_H */
diff --git a/include/mbedcrypto/certs.h b/include/mbedcrypto/certs.h
new file mode 100644
index 0000000..c4d27e9
--- /dev/null
+++ b/include/mbedcrypto/certs.h
@@ -0,0 +1,100 @@
+/**
+ * \file certs.h
+ *
+ * \brief Sample certificates and DHM parameters for testing
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_CERTS_H
+#define MBEDCRYPTO_CERTS_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(MBEDCRYPTO_PEM_PARSE_C)
+/* Concatenation of all CA certificates in PEM format if available */
+extern const char mbedcrypto_test_cas_pem[];
+extern const size_t mbedcrypto_test_cas_pem_len;
+#endif
+
+/* List of all CA certificates, terminated by NULL */
+extern const char * mbedcrypto_test_cas[];
+extern const size_t mbedcrypto_test_cas_len[];
+
+/*
+ * Convenience for users who just want a certificate:
+ * RSA by default, or ECDSA if RSA is not available
+ */
+extern const char * mbedcrypto_test_ca_crt;
+extern const size_t mbedcrypto_test_ca_crt_len;
+extern const char * mbedcrypto_test_ca_key;
+extern const size_t mbedcrypto_test_ca_key_len;
+extern const char * mbedcrypto_test_ca_pwd;
+extern const size_t mbedcrypto_test_ca_pwd_len;
+extern const char * mbedcrypto_test_srv_crt;
+extern const size_t mbedcrypto_test_srv_crt_len;
+extern const char * mbedcrypto_test_srv_key;
+extern const size_t mbedcrypto_test_srv_key_len;
+extern const char * mbedcrypto_test_cli_crt;
+extern const size_t mbedcrypto_test_cli_crt_len;
+extern const char * mbedcrypto_test_cli_key;
+extern const size_t mbedcrypto_test_cli_key_len;
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+extern const char mbedcrypto_test_ca_crt_ec[];
+extern const size_t mbedcrypto_test_ca_crt_ec_len;
+extern const char mbedcrypto_test_ca_key_ec[];
+extern const size_t mbedcrypto_test_ca_key_ec_len;
+extern const char mbedcrypto_test_ca_pwd_ec[];
+extern const size_t mbedcrypto_test_ca_pwd_ec_len;
+extern const char mbedcrypto_test_srv_crt_ec[];
+extern const size_t mbedcrypto_test_srv_crt_ec_len;
+extern const char mbedcrypto_test_srv_key_ec[];
+extern const size_t mbedcrypto_test_srv_key_ec_len;
+extern const char mbedcrypto_test_cli_crt_ec[];
+extern const size_t mbedcrypto_test_cli_crt_ec_len;
+extern const char mbedcrypto_test_cli_key_ec[];
+extern const size_t mbedcrypto_test_cli_key_ec_len;
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C)
+extern const char mbedcrypto_test_ca_crt_rsa[];
+extern const size_t mbedcrypto_test_ca_crt_rsa_len;
+extern const char mbedcrypto_test_ca_key_rsa[];
+extern const size_t mbedcrypto_test_ca_key_rsa_len;
+extern const char mbedcrypto_test_ca_pwd_rsa[];
+extern const size_t mbedcrypto_test_ca_pwd_rsa_len;
+extern const char mbedcrypto_test_srv_crt_rsa[];
+extern const size_t mbedcrypto_test_srv_crt_rsa_len;
+extern const char mbedcrypto_test_srv_key_rsa[];
+extern const size_t mbedcrypto_test_srv_key_rsa_len;
+extern const char mbedcrypto_test_cli_crt_rsa[];
+extern const size_t mbedcrypto_test_cli_crt_rsa_len;
+extern const char mbedcrypto_test_cli_key_rsa[];
+extern const size_t mbedcrypto_test_cli_key_rsa_len;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* certs.h */
diff --git a/include/mbedcrypto/check_config.h b/include/mbedcrypto/check_config.h
new file mode 100644
index 0000000..9948f0e
--- /dev/null
+++ b/include/mbedcrypto/check_config.h
@@ -0,0 +1,684 @@
+/**
+ * \file check_config.h
+ *
+ * \brief Consistency checks for configuration options
+ */
+/*
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * It is recommended to include this file from your config.h
+ * in order to catch dependency issues early.
+ */
+
+#ifndef MBEDCRYPTO_CHECK_CONFIG_H
+#define MBEDCRYPTO_CHECK_CONFIG_H
+
+/*
+ * We assume CHAR_BIT is 8 in many places. In practice, this is true on our
+ * target platforms, so not an issue, but let's just be extra sure.
+ */
+#include <limits.h>
+#if CHAR_BIT != 8
+#error "Mbed Crypto requires a platform with 8-bit chars"
+#endif
+
+#if defined(_WIN32)
+#if !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_C is required on Windows"
+#endif
+
+/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as
+ * it would confuse config.pl. */
+#if !defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT) && \
+ !defined(MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO)
+#define MBEDCRYPTO_PLATFORM_SNPRINTF_ALT
+#endif
+#endif /* _WIN32 */
+
+#if defined(TARGET_LIKE_MBED) && \
+ ( defined(MBEDCRYPTO_NET_C) || defined(MBEDCRYPTO_TIMING_C) )
+#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS"
+#endif
+
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING) && \
+ !defined(__GNUC__) && !defined(__clang__)
+#error "MBEDCRYPTO_DEPRECATED_WARNING only works with GCC and Clang"
+#endif
+
+#if defined(MBEDCRYPTO_HAVE_TIME_DATE) && !defined(MBEDCRYPTO_HAVE_TIME)
+#error "MBEDCRYPTO_HAVE_TIME_DATE without MBEDCRYPTO_HAVE_TIME does not make sense"
+#endif
+
+#if defined(MBEDCRYPTO_AESNI_C) && !defined(MBEDCRYPTO_HAVE_ASM)
+#error "MBEDCRYPTO_AESNI_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_CTR_DRBG_C) && !defined(MBEDCRYPTO_AES_C)
+#error "MBEDCRYPTO_CTR_DRBG_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_DHM_C) && !defined(MBEDCRYPTO_BIGNUM_C)
+#error "MBEDCRYPTO_DHM_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDCRYPTO_SSL_TRUNCATED_HMAC)
+#error "MBEDCRYPTO_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_CMAC_C) && \
+ !defined(MBEDCRYPTO_AES_C) && !defined(MBEDCRYPTO_DES_C)
+#error "MBEDCRYPTO_CMAC_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECDH_C) && !defined(MBEDCRYPTO_ECP_C)
+#error "MBEDCRYPTO_ECDH_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECDSA_C) && \
+ ( !defined(MBEDCRYPTO_ECP_C) || \
+ !defined(MBEDCRYPTO_ASN1_PARSE_C) || \
+ !defined(MBEDCRYPTO_ASN1_WRITE_C) )
+#error "MBEDCRYPTO_ECDSA_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECJPAKE_C) && \
+ ( !defined(MBEDCRYPTO_ECP_C) || !defined(MBEDCRYPTO_MD_C) )
+#error "MBEDCRYPTO_ECJPAKE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECDSA_DETERMINISTIC) && !defined(MBEDCRYPTO_HMAC_DRBG_C)
+#error "MBEDCRYPTO_ECDSA_DETERMINISTIC defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_C) && ( !defined(MBEDCRYPTO_BIGNUM_C) || ( \
+ !defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED) && \
+ !defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED) && \
+ !defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED) && \
+ !defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED) && \
+ !defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED) && \
+ !defined(MBEDCRYPTO_ECP_DP_BP256R1_ENABLED) && \
+ !defined(MBEDCRYPTO_ECP_DP_BP384R1_ENABLED) && \
+ !defined(MBEDCRYPTO_ECP_DP_BP512R1_ENABLED) && \
+ !defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED) && \
+ !defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED) && \
+ !defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED) ) )
+#error "MBEDCRYPTO_ECP_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ENTROPY_C) && (!defined(MBEDCRYPTO_SHA512_C) && \
+ !defined(MBEDCRYPTO_SHA256_C))
+#error "MBEDCRYPTO_ENTROPY_C defined, but not all prerequisites"
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_C) && defined(MBEDCRYPTO_SHA512_C) && \
+ defined(MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN) && (MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN > 64)
+#error "MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_C) && \
+ ( !defined(MBEDCRYPTO_SHA512_C) || defined(MBEDCRYPTO_ENTROPY_FORCE_SHA256) ) \
+ && defined(MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN) && (MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN > 32)
+#error "MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN value too high"
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_C) && \
+ defined(MBEDCRYPTO_ENTROPY_FORCE_SHA256) && !defined(MBEDCRYPTO_SHA256_C)
+#error "MBEDCRYPTO_ENTROPY_FORCE_SHA256 defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_TEST_NULL_ENTROPY) && \
+ ( !defined(MBEDCRYPTO_ENTROPY_C) || !defined(MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES) )
+#error "MBEDCRYPTO_TEST_NULL_ENTROPY defined, but not all prerequisites"
+#endif
+#if defined(MBEDCRYPTO_TEST_NULL_ENTROPY) && \
+ ( defined(MBEDCRYPTO_ENTROPY_NV_SEED) || defined(MBEDCRYPTO_ENTROPY_HARDWARE_ALT) || \
+ defined(MBEDCRYPTO_HAVEGE_C) )
+#error "MBEDCRYPTO_TEST_NULL_ENTROPY defined, but entropy sources too"
+#endif
+
+#if defined(MBEDCRYPTO_GCM_C) && ( \
+ !defined(MBEDCRYPTO_AES_C) && !defined(MBEDCRYPTO_CAMELLIA_C) )
+#error "MBEDCRYPTO_GCM_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_ADD_MIXED_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_ADD_MIXED_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_DOUBLE_JAC_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+#error "MBEDCRYPTO_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_HAVEGE_C) && !defined(MBEDCRYPTO_TIMING_C)
+#error "MBEDCRYPTO_HAVEGE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_HMAC_DRBG_C) && !defined(MBEDCRYPTO_MD_C)
+#error "MBEDCRYPTO_HMAC_DRBG_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \
+ ( !defined(MBEDCRYPTO_ECDH_C) || !defined(MBEDCRYPTO_X509_CRT_PARSE_C) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
+ ( !defined(MBEDCRYPTO_ECDH_C) || !defined(MBEDCRYPTO_X509_CRT_PARSE_C) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDCRYPTO_DHM_C)
+#error "MBEDCRYPTO_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \
+ !defined(MBEDCRYPTO_ECDH_C)
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
+ ( !defined(MBEDCRYPTO_DHM_C) || !defined(MBEDCRYPTO_RSA_C) || \
+ !defined(MBEDCRYPTO_X509_CRT_PARSE_C) || !defined(MBEDCRYPTO_PKCS1_V15) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
+ ( !defined(MBEDCRYPTO_ECDH_C) || !defined(MBEDCRYPTO_RSA_C) || \
+ !defined(MBEDCRYPTO_X509_CRT_PARSE_C) || !defined(MBEDCRYPTO_PKCS1_V15) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \
+ ( !defined(MBEDCRYPTO_ECDH_C) || !defined(MBEDCRYPTO_ECDSA_C) || \
+ !defined(MBEDCRYPTO_X509_CRT_PARSE_C) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_RSA_PSK_ENABLED) && \
+ ( !defined(MBEDCRYPTO_RSA_C) || !defined(MBEDCRYPTO_X509_CRT_PARSE_C) || \
+ !defined(MBEDCRYPTO_PKCS1_V15) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_RSA_ENABLED) && \
+ ( !defined(MBEDCRYPTO_RSA_C) || !defined(MBEDCRYPTO_X509_CRT_PARSE_C) || \
+ !defined(MBEDCRYPTO_PKCS1_V15) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+ ( !defined(MBEDCRYPTO_ECJPAKE_C) || !defined(MBEDCRYPTO_SHA256_C) || \
+ !defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED) )
+#error "MBEDCRYPTO_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C) && \
+ ( !defined(MBEDCRYPTO_PLATFORM_C) || !defined(MBEDCRYPTO_PLATFORM_MEMORY) )
+#error "MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PADLOCK_C) && !defined(MBEDCRYPTO_HAVE_ASM)
+#error "MBEDCRYPTO_PADLOCK_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PEM_PARSE_C) && !defined(MBEDCRYPTO_BASE64_C)
+#error "MBEDCRYPTO_PEM_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PEM_WRITE_C) && !defined(MBEDCRYPTO_BASE64_C)
+#error "MBEDCRYPTO_PEM_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PK_C) && \
+ ( !defined(MBEDCRYPTO_RSA_C) && !defined(MBEDCRYPTO_ECP_C) )
+#error "MBEDCRYPTO_PK_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PK_PARSE_C) && !defined(MBEDCRYPTO_PK_C)
+#error "MBEDCRYPTO_PK_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PK_WRITE_C) && !defined(MBEDCRYPTO_PK_C)
+#error "MBEDCRYPTO_PK_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PKCS11_C) && !defined(MBEDCRYPTO_PK_C)
+#error "MBEDCRYPTO_PKCS11_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_ALT) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_EXIT_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_MACRO) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_EXIT_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_MACRO) &&\
+ ( defined(MBEDCRYPTO_PLATFORM_STD_EXIT) ||\
+ defined(MBEDCRYPTO_PLATFORM_EXIT_ALT) )
+#error "MBEDCRYPTO_PLATFORM_EXIT_MACRO and MBEDCRYPTO_PLATFORM_STD_EXIT/MBEDCRYPTO_PLATFORM_EXIT_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_ALT) &&\
+ ( !defined(MBEDCRYPTO_PLATFORM_C) ||\
+ !defined(MBEDCRYPTO_HAVE_TIME) )
+#error "MBEDCRYPTO_PLATFORM_TIME_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_MACRO) &&\
+ ( !defined(MBEDCRYPTO_PLATFORM_C) ||\
+ !defined(MBEDCRYPTO_HAVE_TIME) )
+#error "MBEDCRYPTO_PLATFORM_TIME_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_TYPE_MACRO) &&\
+ ( !defined(MBEDCRYPTO_PLATFORM_C) ||\
+ !defined(MBEDCRYPTO_HAVE_TIME) )
+#error "MBEDCRYPTO_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_MACRO) &&\
+ ( defined(MBEDCRYPTO_PLATFORM_STD_TIME) ||\
+ defined(MBEDCRYPTO_PLATFORM_TIME_ALT) )
+#error "MBEDCRYPTO_PLATFORM_TIME_MACRO and MBEDCRYPTO_PLATFORM_STD_TIME/MBEDCRYPTO_PLATFORM_TIME_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_TYPE_MACRO) &&\
+ ( defined(MBEDCRYPTO_PLATFORM_STD_TIME) ||\
+ defined(MBEDCRYPTO_PLATFORM_TIME_ALT) )
+#error "MBEDCRYPTO_PLATFORM_TIME_TYPE_MACRO and MBEDCRYPTO_PLATFORM_STD_TIME/MBEDCRYPTO_PLATFORM_TIME_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_ALT) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_FPRINTF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_MACRO) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_MACRO) &&\
+ ( defined(MBEDCRYPTO_PLATFORM_STD_FPRINTF) ||\
+ defined(MBEDCRYPTO_PLATFORM_FPRINTF_ALT) )
+#error "MBEDCRYPTO_PLATFORM_FPRINTF_MACRO and MBEDCRYPTO_PLATFORM_STD_FPRINTF/MBEDCRYPTO_PLATFORM_FPRINTF_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FREE_MACRO) &&\
+ ( !defined(MBEDCRYPTO_PLATFORM_C) || !defined(MBEDCRYPTO_PLATFORM_MEMORY) )
+#error "MBEDCRYPTO_PLATFORM_FREE_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FREE_MACRO) &&\
+ defined(MBEDCRYPTO_PLATFORM_STD_FREE)
+#error "MBEDCRYPTO_PLATFORM_FREE_MACRO and MBEDCRYPTO_PLATFORM_STD_FREE cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_FREE_MACRO) && !defined(MBEDCRYPTO_PLATFORM_CALLOC_MACRO)
+#error "MBEDCRYPTO_PLATFORM_CALLOC_MACRO must be defined if MBEDCRYPTO_PLATFORM_FREE_MACRO is"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_CALLOC_MACRO) &&\
+ ( !defined(MBEDCRYPTO_PLATFORM_C) || !defined(MBEDCRYPTO_PLATFORM_MEMORY) )
+#error "MBEDCRYPTO_PLATFORM_CALLOC_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_CALLOC_MACRO) &&\
+ defined(MBEDCRYPTO_PLATFORM_STD_CALLOC)
+#error "MBEDCRYPTO_PLATFORM_CALLOC_MACRO and MBEDCRYPTO_PLATFORM_STD_CALLOC cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_CALLOC_MACRO) && !defined(MBEDCRYPTO_PLATFORM_FREE_MACRO)
+#error "MBEDCRYPTO_PLATFORM_FREE_MACRO must be defined if MBEDCRYPTO_PLATFORM_CALLOC_MACRO is"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_MEMORY) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_MEMORY defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_ALT) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_PRINTF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_MACRO) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_PRINTF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_MACRO) &&\
+ ( defined(MBEDCRYPTO_PLATFORM_STD_PRINTF) ||\
+ defined(MBEDCRYPTO_PLATFORM_PRINTF_ALT) )
+#error "MBEDCRYPTO_PLATFORM_PRINTF_MACRO and MBEDCRYPTO_PLATFORM_STD_PRINTF/MBEDCRYPTO_PLATFORM_PRINTF_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDCRYPTO_PLATFORM_C)
+#error "MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO) &&\
+ ( defined(MBEDCRYPTO_PLATFORM_STD_SNPRINTF) ||\
+ defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT) )
+#error "MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO and MBEDCRYPTO_PLATFORM_STD_SNPRINTF/MBEDCRYPTO_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_MEM_HDR) &&\
+ !defined(MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS)
+#error "MBEDCRYPTO_PLATFORM_STD_MEM_HDR defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_CALLOC) && !defined(MBEDCRYPTO_PLATFORM_MEMORY)
+#error "MBEDCRYPTO_PLATFORM_STD_CALLOC defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_CALLOC) && !defined(MBEDCRYPTO_PLATFORM_MEMORY)
+#error "MBEDCRYPTO_PLATFORM_STD_CALLOC defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_FREE) && !defined(MBEDCRYPTO_PLATFORM_MEMORY)
+#error "MBEDCRYPTO_PLATFORM_STD_FREE defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_EXIT) &&\
+ !defined(MBEDCRYPTO_PLATFORM_EXIT_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_EXIT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_TIME) &&\
+ ( !defined(MBEDCRYPTO_PLATFORM_TIME_ALT) ||\
+ !defined(MBEDCRYPTO_HAVE_TIME) )
+#error "MBEDCRYPTO_PLATFORM_STD_TIME defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_FPRINTF) &&\
+ !defined(MBEDCRYPTO_PLATFORM_FPRINTF_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_FPRINTF defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_PRINTF) &&\
+ !defined(MBEDCRYPTO_PLATFORM_PRINTF_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_PRINTF defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_SNPRINTF) &&\
+ !defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_SNPRINTF defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED) &&\
+ ( !defined(MBEDCRYPTO_PLATFORM_C) || !defined(MBEDCRYPTO_ENTROPY_C) )
+#error "MBEDCRYPTO_ENTROPY_NV_SEED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT) &&\
+ !defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+#error "MBEDCRYPTO_PLATFORM_NV_SEED_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ) &&\
+ !defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE) &&\
+ !defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT)
+#error "MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_READ_MACRO) &&\
+ ( defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ) ||\
+ defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT) )
+#error "MBEDCRYPTO_PLATFORM_NV_SEED_READ_MACRO and MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_WRITE_MACRO) &&\
+ ( defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE) ||\
+ defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT) )
+#error "MBEDCRYPTO_PLATFORM_NV_SEED_WRITE_MACRO and MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDCRYPTO_PSA_CRYPTO_C) && \
+ !( defined(MBEDCRYPTO_CTR_DRBG_C) && \
+ defined(MBEDCRYPTO_ENTROPY_C) )
+#error "MBEDCRYPTO_PSA_CRYPTO_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_PSA_CRYPTO_SPM) && !defined(MBEDCRYPTO_PSA_CRYPTO_C)
+#error "MBEDCRYPTO_PSA_CRYPTO_SPM defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C) && ( !defined(MBEDCRYPTO_BIGNUM_C) || \
+ !defined(MBEDCRYPTO_OID_C) )
+#error "MBEDCRYPTO_RSA_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C) && ( !defined(MBEDCRYPTO_PKCS1_V21) && \
+ !defined(MBEDCRYPTO_PKCS1_V15) )
+#error "MBEDCRYPTO_RSA_C defined, but none of the PKCS1 versions enabled"
+#endif
+
+#if defined(MBEDCRYPTO_X509_RSASSA_PSS_SUPPORT) && \
+ ( !defined(MBEDCRYPTO_RSA_C) || !defined(MBEDCRYPTO_PKCS1_V21) )
+#error "MBEDCRYPTO_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_PROTO_SSL3) && ( !defined(MBEDCRYPTO_MD5_C) || \
+ !defined(MBEDCRYPTO_SHA1_C) )
+#error "MBEDCRYPTO_SSL_PROTO_SSL3 defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_PROTO_TLS1) && ( !defined(MBEDCRYPTO_MD5_C) || \
+ !defined(MBEDCRYPTO_SHA1_C) )
+#error "MBEDCRYPTO_SSL_PROTO_TLS1 defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) && ( !defined(MBEDCRYPTO_MD5_C) || \
+ !defined(MBEDCRYPTO_SHA1_C) )
+#error "MBEDCRYPTO_SSL_PROTO_TLS1_1 defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_PROTO_TLS1_2) && ( !defined(MBEDCRYPTO_SHA1_C) && \
+ !defined(MBEDCRYPTO_SHA256_C) && !defined(MBEDCRYPTO_SHA512_C) )
+#error "MBEDCRYPTO_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_PROTO_DTLS) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1_2)
+#error "MBEDCRYPTO_SSL_PROTO_DTLS defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_CLI_C) && !defined(MBEDCRYPTO_SSL_TLS_C)
+#error "MBEDCRYPTO_SSL_CLI_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TLS_C) && ( !defined(MBEDCRYPTO_CIPHER_C) || \
+ !defined(MBEDCRYPTO_MD_C) )
+#error "MBEDCRYPTO_SSL_TLS_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_SRV_C) && !defined(MBEDCRYPTO_SSL_TLS_C)
+#error "MBEDCRYPTO_SSL_SRV_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TLS_C) && (!defined(MBEDCRYPTO_SSL_PROTO_SSL3) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1) && !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1_2))
+#error "MBEDCRYPTO_SSL_TLS_C defined, but no protocols are active"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TLS_C) && (defined(MBEDCRYPTO_SSL_PROTO_SSL3) && \
+ defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) && !defined(MBEDCRYPTO_SSL_PROTO_TLS1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TLS_C) && (defined(MBEDCRYPTO_SSL_PROTO_TLS1) && \
+ defined(MBEDCRYPTO_SSL_PROTO_TLS1_2) && !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TLS_C) && (defined(MBEDCRYPTO_SSL_PROTO_SSL3) && \
+ defined(MBEDCRYPTO_SSL_PROTO_TLS1_2) && (!defined(MBEDCRYPTO_SSL_PROTO_TLS1) || \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1)))
+#error "Illegal protocol selection"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDCRYPTO_SSL_PROTO_DTLS)
+#error "MBEDCRYPTO_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_DTLS_CLIENT_PORT_REUSE) && \
+ !defined(MBEDCRYPTO_SSL_DTLS_HELLO_VERIFY)
+#error "MBEDCRYPTO_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_DTLS_ANTI_REPLAY) && \
+ ( !defined(MBEDCRYPTO_SSL_TLS_C) || !defined(MBEDCRYPTO_SSL_PROTO_DTLS) )
+#error "MBEDCRYPTO_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_DTLS_BADMAC_LIMIT) && \
+ ( !defined(MBEDCRYPTO_SSL_TLS_C) || !defined(MBEDCRYPTO_SSL_PROTO_DTLS) )
+#error "MBEDCRYPTO_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_ENCRYPT_THEN_MAC) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1_2)
+#error "MBEDCRYPTO_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_EXTENDED_MASTER_SECRET) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1_1) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_TLS1_2)
+#error "MBEDCRYPTO_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_TICKET_C) && !defined(MBEDCRYPTO_CIPHER_C)
+#error "MBEDCRYPTO_SSL_TICKET_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_CBC_RECORD_SPLITTING) && \
+ !defined(MBEDCRYPTO_SSL_PROTO_SSL3) && !defined(MBEDCRYPTO_SSL_PROTO_TLS1)
+#error "MBEDCRYPTO_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_SSL_SERVER_NAME_INDICATION) && \
+ !defined(MBEDCRYPTO_X509_CRT_PARSE_C)
+#error "MBEDCRYPTO_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_PTHREAD)
+#if !defined(MBEDCRYPTO_THREADING_C) || defined(MBEDCRYPTO_THREADING_IMPL)
+#error "MBEDCRYPTO_THREADING_PTHREAD defined, but not all prerequisites"
+#endif
+#define MBEDCRYPTO_THREADING_IMPL
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_ALT)
+#if !defined(MBEDCRYPTO_THREADING_C) || defined(MBEDCRYPTO_THREADING_IMPL)
+#error "MBEDCRYPTO_THREADING_ALT defined, but not all prerequisites"
+#endif
+#define MBEDCRYPTO_THREADING_IMPL
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_C) && !defined(MBEDCRYPTO_THREADING_IMPL)
+#error "MBEDCRYPTO_THREADING_C defined, single threading implementation required"
+#endif
+#undef MBEDCRYPTO_THREADING_IMPL
+
+#if defined(MBEDCRYPTO_VERSION_FEATURES) && !defined(MBEDCRYPTO_VERSION_C)
+#error "MBEDCRYPTO_VERSION_FEATURES defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_USE_C) && ( !defined(MBEDCRYPTO_BIGNUM_C) || \
+ !defined(MBEDCRYPTO_OID_C) || !defined(MBEDCRYPTO_ASN1_PARSE_C) || \
+ !defined(MBEDCRYPTO_PK_PARSE_C) )
+#error "MBEDCRYPTO_X509_USE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CREATE_C) && ( !defined(MBEDCRYPTO_BIGNUM_C) || \
+ !defined(MBEDCRYPTO_OID_C) || !defined(MBEDCRYPTO_ASN1_WRITE_C) || \
+ !defined(MBEDCRYPTO_PK_WRITE_C) )
+#error "MBEDCRYPTO_X509_CREATE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CRT_PARSE_C) && ( !defined(MBEDCRYPTO_X509_USE_C) )
+#error "MBEDCRYPTO_X509_CRT_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CRL_PARSE_C) && ( !defined(MBEDCRYPTO_X509_USE_C) )
+#error "MBEDCRYPTO_X509_CRL_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CSR_PARSE_C) && ( !defined(MBEDCRYPTO_X509_USE_C) )
+#error "MBEDCRYPTO_X509_CSR_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CRT_WRITE_C) && ( !defined(MBEDCRYPTO_X509_CREATE_C) )
+#error "MBEDCRYPTO_X509_CRT_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_X509_CSR_WRITE_C) && ( !defined(MBEDCRYPTO_X509_CREATE_C) )
+#error "MBEDCRYPTO_X509_CSR_WRITE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDCRYPTO_HAVE_INT32) && defined(MBEDCRYPTO_HAVE_INT64)
+#error "MBEDCRYPTO_HAVE_INT32 and MBEDCRYPTO_HAVE_INT64 cannot be defined simultaneously"
+#endif /* MBEDCRYPTO_HAVE_INT32 && MBEDCRYPTO_HAVE_INT64 */
+
+#if ( defined(MBEDCRYPTO_HAVE_INT32) || defined(MBEDCRYPTO_HAVE_INT64) ) && \
+ defined(MBEDCRYPTO_HAVE_ASM)
+#error "MBEDCRYPTO_HAVE_INT32/MBEDCRYPTO_HAVE_INT64 and MBEDCRYPTO_HAVE_ASM cannot be defined simultaneously"
+#endif /* (MBEDCRYPTO_HAVE_INT32 || MBEDCRYPTO_HAVE_INT64) && MBEDCRYPTO_HAVE_ASM */
+
+/*
+ * Avoid warning from -pedantic. This is a convenient place for this
+ * workaround since this is included by every single file before the
+ * #if defined(MBEDCRYPTO_xxx_C) that results in emtpy translation units.
+ */
+typedef int mbedcrypto_iso_c_forbids_empty_translation_units;
+
+#endif /* MBEDCRYPTO_CHECK_CONFIG_H */
diff --git a/include/mbedcrypto/cipher.h b/include/mbedcrypto/cipher.h
new file mode 100644
index 0000000..43f8f68
--- /dev/null
+++ b/include/mbedcrypto/cipher.h
@@ -0,0 +1,773 @@
+/**
+ * \file cipher.h
+ *
+ * \brief This file contains an abstraction interface for use with the cipher
+ * primitives provided by the library. It provides a common interface to all of
+ * the available cipher operations.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_CIPHER_H
+#define MBEDCRYPTO_CIPHER_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#if defined(MBEDCRYPTO_GCM_C) || defined(MBEDCRYPTO_CCM_C)
+#define MBEDCRYPTO_CIPHER_MODE_AEAD
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+#define MBEDCRYPTO_CIPHER_MODE_WITH_PADDING
+#endif
+
+#if defined(MBEDCRYPTO_ARC4_C)
+#define MBEDCRYPTO_CIPHER_MODE_STREAM
+#endif
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#define MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */
+#define MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters. */
+#define MBEDCRYPTO_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */
+#define MBEDCRYPTO_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */
+#define MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */
+#define MBEDCRYPTO_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */
+#define MBEDCRYPTO_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */
+#define MBEDCRYPTO_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */
+
+#define MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */
+#define MBEDCRYPTO_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Supported cipher types.
+ *
+ * \warning RC4 and DES are considered weak ciphers and their use
+ * constitutes a security risk. Arm recommends considering stronger
+ * ciphers instead.
+ */
+typedef enum {
+ MBEDCRYPTO_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */
+ MBEDCRYPTO_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */
+ MBEDCRYPTO_CIPHER_ID_AES, /**< The AES cipher. */
+ MBEDCRYPTO_CIPHER_ID_DES, /**< The DES cipher. */
+ MBEDCRYPTO_CIPHER_ID_3DES, /**< The Triple DES cipher. */
+ MBEDCRYPTO_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */
+ MBEDCRYPTO_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */
+ MBEDCRYPTO_CIPHER_ID_ARC4, /**< The RC4 cipher. */
+} mbedcrypto_cipher_id_t;
+
+/**
+ * \brief Supported {cipher type, cipher mode} pairs.
+ *
+ * \warning RC4 and DES are considered weak ciphers and their use
+ * constitutes a security risk. Arm recommends considering stronger
+ * ciphers instead.
+ */
+typedef enum {
+ MBEDCRYPTO_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */
+ MBEDCRYPTO_CIPHER_NULL, /**< The identity stream cipher. */
+ MBEDCRYPTO_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */
+ MBEDCRYPTO_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */
+ MBEDCRYPTO_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */
+ MBEDCRYPTO_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */
+ MBEDCRYPTO_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */
+ MBEDCRYPTO_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */
+ MBEDCRYPTO_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */
+ MBEDCRYPTO_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */
+ MBEDCRYPTO_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */
+ MBEDCRYPTO_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */
+ MBEDCRYPTO_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */
+ MBEDCRYPTO_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */
+ MBEDCRYPTO_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */
+ MBEDCRYPTO_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */
+ MBEDCRYPTO_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */
+ MBEDCRYPTO_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */
+ MBEDCRYPTO_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */
+ MBEDCRYPTO_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */
+ MBEDCRYPTO_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */
+ MBEDCRYPTO_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */
+ MBEDCRYPTO_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */
+ MBEDCRYPTO_CIPHER_BLOWFISH_ECB, /**< Blowfish cipher with ECB mode. */
+ MBEDCRYPTO_CIPHER_BLOWFISH_CBC, /**< Blowfish cipher with CBC mode. */
+ MBEDCRYPTO_CIPHER_BLOWFISH_CFB64, /**< Blowfish cipher with CFB64 mode. */
+ MBEDCRYPTO_CIPHER_BLOWFISH_CTR, /**< Blowfish cipher with CTR mode. */
+ MBEDCRYPTO_CIPHER_ARC4_128, /**< RC4 cipher with 128-bit mode. */
+ MBEDCRYPTO_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */
+ MBEDCRYPTO_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */
+ MBEDCRYPTO_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */
+} mbedcrypto_cipher_type_t;
+
+/** Supported cipher modes. */
+typedef enum {
+ MBEDCRYPTO_MODE_NONE = 0, /**< None. */
+ MBEDCRYPTO_MODE_ECB, /**< The ECB cipher mode. */
+ MBEDCRYPTO_MODE_CBC, /**< The CBC cipher mode. */
+ MBEDCRYPTO_MODE_CFB, /**< The CFB cipher mode. */
+ MBEDCRYPTO_MODE_OFB, /**< The OFB cipher mode - unsupported. */
+ MBEDCRYPTO_MODE_CTR, /**< The CTR cipher mode. */
+ MBEDCRYPTO_MODE_GCM, /**< The GCM cipher mode. */
+ MBEDCRYPTO_MODE_STREAM, /**< The stream cipher mode. */
+ MBEDCRYPTO_MODE_CCM, /**< The CCM cipher mode. */
+} mbedcrypto_cipher_mode_t;
+
+/** Supported cipher padding types. */
+typedef enum {
+ MBEDCRYPTO_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */
+ MBEDCRYPTO_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */
+ MBEDCRYPTO_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */
+ MBEDCRYPTO_PADDING_ZEROS, /**< Zero padding (not reversible). */
+ MBEDCRYPTO_PADDING_NONE, /**< Never pad (full blocks only). */
+} mbedcrypto_cipher_padding_t;
+
+/** Type of operation. */
+typedef enum {
+ MBEDCRYPTO_OPERATION_NONE = -1,
+ MBEDCRYPTO_DECRYPT = 0,
+ MBEDCRYPTO_ENCRYPT,
+} mbedcrypto_operation_t;
+
+enum {
+ /** Undefined key length. */
+ MBEDCRYPTO_KEY_LENGTH_NONE = 0,
+ /** Key length, in bits (including parity), for DES keys. */
+ MBEDCRYPTO_KEY_LENGTH_DES = 64,
+ /** Key length in bits, including parity, for DES in two-key EDE. */
+ MBEDCRYPTO_KEY_LENGTH_DES_EDE = 128,
+ /** Key length in bits, including parity, for DES in three-key EDE. */
+ MBEDCRYPTO_KEY_LENGTH_DES_EDE3 = 192,
+};
+
+/** Maximum length of any IV, in Bytes. */
+#define MBEDCRYPTO_MAX_IV_LENGTH 16
+/** Maximum block size of any cipher, in Bytes. */
+#define MBEDCRYPTO_MAX_BLOCK_LENGTH 16
+
+/**
+ * Base cipher information (opaque struct).
+ */
+typedef struct mbedcrypto_cipher_base_t mbedcrypto_cipher_base_t;
+
+/**
+ * CMAC context (opaque struct).
+ */
+typedef struct mbedcrypto_cmac_context_t mbedcrypto_cmac_context_t;
+
+/**
+ * Cipher information. Allows calling cipher functions
+ * in a generic way.
+ */
+typedef struct {
+ /** Full cipher identifier. For example,
+ * MBEDCRYPTO_CIPHER_AES_256_CBC.
+ */
+ mbedcrypto_cipher_type_t type;
+
+ /** The cipher mode. For example, MBEDCRYPTO_MODE_CBC. */
+ mbedcrypto_cipher_mode_t mode;
+
+ /** The cipher key length, in bits. This is the
+ * default length for variable sized ciphers.
+ * Includes parity bits for ciphers like DES.
+ */
+ unsigned int key_bitlen;
+
+ /** Name of the cipher. */
+ const char * name;
+
+ /** IV or nonce size, in Bytes.
+ * For ciphers that accept variable IV sizes,
+ * this is the recommended size.
+ */
+ unsigned int iv_size;
+
+ /** Bitflag comprised of MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN and
+ * MBEDCRYPTO_CIPHER_VARIABLE_KEY_LEN indicating whether the
+ * cipher supports variable IV or variable key sizes, respectively.
+ */
+ int flags;
+
+ /** The block size, in Bytes. */
+ unsigned int block_size;
+
+ /** Struct for base cipher information and functions. */
+ const mbedcrypto_cipher_base_t *base;
+
+} mbedcrypto_cipher_info_t;
+
+/**
+ * Generic cipher context.
+ */
+typedef struct {
+ /** Information about the associated cipher. */
+ const mbedcrypto_cipher_info_t *cipher_info;
+
+ /** Key length to use. */
+ int key_bitlen;
+
+ /** Operation that the key of the context has been
+ * initialized for.
+ */
+ mbedcrypto_operation_t operation;
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_WITH_PADDING)
+ /** Padding functions to use, if relevant for
+ * the specific cipher mode.
+ */
+ void (*add_padding)( unsigned char *output, size_t olen, size_t data_len );
+ int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len );
+#endif
+
+ /** Buffer for input that has not been processed yet. */
+ unsigned char unprocessed_data[MBEDCRYPTO_MAX_BLOCK_LENGTH];
+
+ /** Number of Bytes that have not been processed yet. */
+ size_t unprocessed_len;
+
+ /** Current IV or NONCE_COUNTER for CTR-mode. */
+ unsigned char iv[MBEDCRYPTO_MAX_IV_LENGTH];
+
+ /** IV size in Bytes, for ciphers with variable-length IVs. */
+ size_t iv_size;
+
+ /** The cipher-specific context. */
+ void *cipher_ctx;
+
+#if defined(MBEDCRYPTO_CMAC_C)
+ /** CMAC-specific context. */
+ mbedcrypto_cmac_context_t *cmac_ctx;
+#endif
+} mbedcrypto_cipher_context_t;
+
+/**
+ * \brief This function retrieves the list of ciphers supported by the generic
+ * cipher module.
+ *
+ * \return A statically-allocated array of ciphers. The last entry
+ * is zero.
+ */
+const int *mbedcrypto_cipher_list( void );
+
+/**
+ * \brief This function retrieves the cipher-information
+ * structure associated with the given cipher name.
+ *
+ * \param cipher_name Name of the cipher to search for.
+ *
+ * \return The cipher information structure associated with the
+ * given \p cipher_name.
+ * \return NULL if the associated cipher information is not found.
+ */
+const mbedcrypto_cipher_info_t *mbedcrypto_cipher_info_from_string( const char *cipher_name );
+
+/**
+ * \brief This function retrieves the cipher-information
+ * structure associated with the given cipher type.
+ *
+ * \param cipher_type Type of the cipher to search for.
+ *
+ * \return The cipher information structure associated with the
+ * given \p cipher_type.
+ * \return NULL if the associated cipher information is not found.
+ */
+const mbedcrypto_cipher_info_t *mbedcrypto_cipher_info_from_type( const mbedcrypto_cipher_type_t cipher_type );
+
+/**
+ * \brief This function retrieves the cipher-information
+ * structure associated with the given cipher ID,
+ * key size and mode.
+ *
+ * \param cipher_id The ID of the cipher to search for. For example,
+ * #MBEDCRYPTO_CIPHER_ID_AES.
+ * \param key_bitlen The length of the key in bits.
+ * \param mode The cipher mode. For example, #MBEDCRYPTO_MODE_CBC.
+ *
+ * \return The cipher information structure associated with the
+ * given \p cipher_id.
+ * \return NULL if the associated cipher information is not found.
+ */
+const mbedcrypto_cipher_info_t *mbedcrypto_cipher_info_from_values( const mbedcrypto_cipher_id_t cipher_id,
+ int key_bitlen,
+ const mbedcrypto_cipher_mode_t mode );
+
+/**
+ * \brief This function initializes a \p cipher_context as NONE.
+ */
+void mbedcrypto_cipher_init( mbedcrypto_cipher_context_t *ctx );
+
+/**
+ * \brief This function frees and clears the cipher-specific
+ * context of \p ctx. Freeing \p ctx itself remains the
+ * responsibility of the caller.
+ */
+void mbedcrypto_cipher_free( mbedcrypto_cipher_context_t *ctx );
+
+
+/**
+ * \brief This function initializes and fills the cipher-context
+ * structure with the appropriate values. It also clears
+ * the structure.
+ *
+ * \param ctx The context to initialize. May not be NULL.
+ * \param cipher_info The cipher to use.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return #MBEDCRYPTO_ERR_CIPHER_ALLOC_FAILED if allocation of the
+ * cipher-specific context fails.
+ *
+ * \internal Currently, the function also clears the structure.
+ * In future versions, the caller will be required to call
+ * mbedcrypto_cipher_init() on the structure first.
+ */
+int mbedcrypto_cipher_setup( mbedcrypto_cipher_context_t *ctx, const mbedcrypto_cipher_info_t *cipher_info );
+
+/**
+ * \brief This function returns the block size of the given cipher.
+ *
+ * \param ctx The context of the cipher. Must be initialized.
+ *
+ * \return The size of the blocks of the cipher.
+ * \return 0 if \p ctx has not been initialized.
+ */
+static inline unsigned int mbedcrypto_cipher_get_block_size( const mbedcrypto_cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return 0;
+
+ return ctx->cipher_info->block_size;
+}
+
+/**
+ * \brief This function returns the mode of operation for
+ * the cipher. For example, MBEDCRYPTO_MODE_CBC.
+ *
+ * \param ctx The context of the cipher. Must be initialized.
+ *
+ * \return The mode of operation.
+ * \return #MBEDCRYPTO_MODE_NONE if \p ctx has not been initialized.
+ */
+static inline mbedcrypto_cipher_mode_t mbedcrypto_cipher_get_cipher_mode( const mbedcrypto_cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return MBEDCRYPTO_MODE_NONE;
+
+ return ctx->cipher_info->mode;
+}
+
+/**
+ * \brief This function returns the size of the IV or nonce
+ * of the cipher, in Bytes.
+ *
+ * \param ctx The context of the cipher. Must be initialized.
+ *
+ * \return The recommended IV size if no IV has been set.
+ * \return \c 0 for ciphers not using an IV or a nonce.
+ * \return The actual size if an IV has been set.
+ */
+static inline int mbedcrypto_cipher_get_iv_size( const mbedcrypto_cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return 0;
+
+ if( ctx->iv_size != 0 )
+ return (int) ctx->iv_size;
+
+ return (int) ctx->cipher_info->iv_size;
+}
+
+/**
+ * \brief This function returns the type of the given cipher.
+ *
+ * \param ctx The context of the cipher. Must be initialized.
+ *
+ * \return The type of the cipher.
+ * \return #MBEDCRYPTO_CIPHER_NONE if \p ctx has not been initialized.
+ */
+static inline mbedcrypto_cipher_type_t mbedcrypto_cipher_get_type( const mbedcrypto_cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return MBEDCRYPTO_CIPHER_NONE;
+
+ return ctx->cipher_info->type;
+}
+
+/**
+ * \brief This function returns the name of the given cipher
+ * as a string.
+ *
+ * \param ctx The context of the cipher. Must be initialized.
+ *
+ * \return The name of the cipher.
+ * \return NULL if \p ctx has not been not initialized.
+ */
+static inline const char *mbedcrypto_cipher_get_name( const mbedcrypto_cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return 0;
+
+ return ctx->cipher_info->name;
+}
+
+/**
+ * \brief This function returns the key length of the cipher.
+ *
+ * \param ctx The context of the cipher. Must be initialized.
+ *
+ * \return The key length of the cipher in bits.
+ * \return #MBEDCRYPTO_KEY_LENGTH_NONE if ctx \p has not been
+ * initialized.
+ */
+static inline int mbedcrypto_cipher_get_key_bitlen( const mbedcrypto_cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return MBEDCRYPTO_KEY_LENGTH_NONE;
+
+ return (int) ctx->cipher_info->key_bitlen;
+}
+
+/**
+ * \brief This function returns the operation of the given cipher.
+ *
+ * \param ctx The context of the cipher. Must be initialized.
+ *
+ * \return The type of operation: #MBEDCRYPTO_ENCRYPT or #MBEDCRYPTO_DECRYPT.
+ * \return #MBEDCRYPTO_OPERATION_NONE if \p ctx has not been initialized.
+ */
+static inline mbedcrypto_operation_t mbedcrypto_cipher_get_operation( const mbedcrypto_cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return MBEDCRYPTO_OPERATION_NONE;
+
+ return ctx->operation;
+}
+
+/**
+ * \brief This function sets the key to use with the given context.
+ *
+ * \param ctx The generic cipher context. May not be NULL. Must have
+ * been initialized using mbedcrypto_cipher_info_from_type()
+ * or mbedcrypto_cipher_info_from_string().
+ * \param key The key to use.
+ * \param key_bitlen The key length to use, in bits.
+ * \param operation The operation that the key will be used for:
+ * #MBEDCRYPTO_ENCRYPT or #MBEDCRYPTO_DECRYPT.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_setkey( mbedcrypto_cipher_context_t *ctx, const unsigned char *key,
+ int key_bitlen, const mbedcrypto_operation_t operation );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_WITH_PADDING)
+/**
+ * \brief This function sets the padding mode, for cipher modes
+ * that use padding.
+ *
+ * The default passing mode is PKCS7 padding.
+ *
+ * \param ctx The generic cipher context.
+ * \param mode The padding mode.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE
+ * if the selected padding mode is not supported.
+ * \return #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode
+ * does not support padding.
+ */
+int mbedcrypto_cipher_set_padding_mode( mbedcrypto_cipher_context_t *ctx, mbedcrypto_cipher_padding_t mode );
+#endif /* MBEDCRYPTO_CIPHER_MODE_WITH_PADDING */
+
+/**
+ * \brief This function sets the initialization vector (IV)
+ * or nonce.
+ *
+ * \note Some ciphers do not use IVs nor nonce. For these
+ * ciphers, this function has no effect.
+ *
+ * \param ctx The generic cipher context.
+ * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * \param iv_len The IV length for ciphers with variable-size IV.
+ * This parameter is discarded by ciphers with fixed-size IV.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ */
+int mbedcrypto_cipher_set_iv( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len );
+
+/**
+ * \brief This function resets the cipher state.
+ *
+ * \param ctx The generic cipher context.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ */
+int mbedcrypto_cipher_reset( mbedcrypto_cipher_context_t *ctx );
+
+#if defined(MBEDCRYPTO_GCM_C)
+/**
+ * \brief This function adds additional data for AEAD ciphers.
+ * Only supported with GCM. Must be called
+ * exactly once, after mbedcrypto_cipher_reset().
+ *
+ * \param ctx The generic cipher context.
+ * \param ad The additional data to use.
+ * \param ad_len the Length of \p ad.
+ *
+ * \return \c 0 on success.
+ * \return A specific error code on failure.
+ */
+int mbedcrypto_cipher_update_ad( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *ad, size_t ad_len );
+#endif /* MBEDCRYPTO_GCM_C */
+
+/**
+ * \brief The generic cipher update function. It encrypts or
+ * decrypts using the given cipher context. Writes as
+ * many block-sized blocks of data as possible to output.
+ * Any data that cannot be written immediately is either
+ * added to the next block, or flushed when
+ * mbedcrypto_cipher_finish() is called.
+ * Exception: For MBEDCRYPTO_MODE_ECB, expects a single block
+ * in size. For example, 16 Bytes for AES.
+ *
+ * \note If the underlying cipher is used in GCM mode, all calls
+ * to this function, except for the last one before
+ * mbedcrypto_cipher_finish(), must have \p ilen as a
+ * multiple of the block size of the cipher.
+ *
+ * \param ctx The generic cipher context.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ * \param output The buffer for the output data. Must be able to hold at
+ * least \p ilen + block_size. Must not be the same buffer
+ * as input.
+ * \param olen The length of the output data, to be updated with the
+ * actual number of Bytes written.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return #MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE on an
+ * unsupported mode for a cipher.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_update( mbedcrypto_cipher_context_t *ctx, const unsigned char *input,
+ size_t ilen, unsigned char *output, size_t *olen );
+
+/**
+ * \brief The generic cipher finalization function. If data still
+ * needs to be flushed from an incomplete block, the data
+ * contained in it is padded to the size of
+ * the last block, and written to the \p output buffer.
+ *
+ * \param ctx The generic cipher context.
+ * \param output The buffer to write data to. Needs block_size available.
+ * \param olen The length of the data written to the \p output buffer.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return #MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption
+ * expecting a full block but not receiving one.
+ * \return #MBEDCRYPTO_ERR_CIPHER_INVALID_PADDING on invalid padding
+ * while decrypting.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_finish( mbedcrypto_cipher_context_t *ctx,
+ unsigned char *output, size_t *olen );
+
+#if defined(MBEDCRYPTO_GCM_C)
+/**
+ * \brief This function writes a tag for AEAD ciphers.
+ * Only supported with GCM.
+ * Must be called after mbedcrypto_cipher_finish().
+ *
+ * \param ctx The generic cipher context.
+ * \param tag The buffer to write the tag to.
+ * \param tag_len The length of the tag to write.
+ *
+ * \return \c 0 on success.
+ * \return A specific error code on failure.
+ */
+int mbedcrypto_cipher_write_tag( mbedcrypto_cipher_context_t *ctx,
+ unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief This function checks the tag for AEAD ciphers.
+ * Only supported with GCM.
+ * Must be called after mbedcrypto_cipher_finish().
+ *
+ * \param ctx The generic cipher context.
+ * \param tag The buffer holding the tag.
+ * \param tag_len The length of the tag to check.
+ *
+ * \return \c 0 on success.
+ * \return A specific error code on failure.
+ */
+int mbedcrypto_cipher_check_tag( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *tag, size_t tag_len );
+#endif /* MBEDCRYPTO_GCM_C */
+
+/**
+ * \brief The generic all-in-one encryption/decryption function,
+ * for all ciphers except AEAD constructs.
+ *
+ * \param ctx The generic cipher context.
+ * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * \param iv_len The IV length for ciphers with variable-size IV.
+ * This parameter is discarded by ciphers with fixed-size
+ * IV.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ * \param output The buffer for the output data. Must be able to hold at
+ * least \p ilen + block_size. Must not be the same buffer
+ * as input.
+ * \param olen The length of the output data, to be updated with the
+ * actual number of Bytes written.
+ *
+ * \note Some ciphers do not use IVs nor nonce. For these
+ * ciphers, use \p iv = NULL and \p iv_len = 0.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return #MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption
+ * expecting a full block but not receiving one.
+ * \return #MBEDCRYPTO_ERR_CIPHER_INVALID_PADDING on invalid padding
+ * while decrypting.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_crypt( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_AEAD)
+/**
+ * \brief The generic autenticated encryption (AEAD) function.
+ *
+ * \param ctx The generic cipher context.
+ * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * \param iv_len The IV length for ciphers with variable-size IV.
+ * This parameter is discarded by ciphers with fixed-size IV.
+ * \param ad The additional data to authenticate.
+ * \param ad_len The length of \p ad.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ * \param output The buffer for the output data.
+ * Must be able to hold at least \p ilen.
+ * \param olen The length of the output data, to be updated with the
+ * actual number of Bytes written.
+ * \param tag The buffer for the authentication tag.
+ * \param tag_len The desired length of the authentication tag.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_auth_encrypt( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *ad, size_t ad_len,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen,
+ unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief The generic autenticated decryption (AEAD) function.
+ *
+ * \note If the data is not authentic, then the output buffer
+ * is zeroed out to prevent the unauthentic plaintext being
+ * used, making this interface safer.
+ *
+ * \param ctx The generic cipher context.
+ * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
+ * \param iv_len The IV length for ciphers with variable-size IV.
+ * This parameter is discarded by ciphers with fixed-size IV.
+ * \param ad The additional data to be authenticated.
+ * \param ad_len The length of \p ad.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ * \param output The buffer for the output data.
+ * Must be able to hold at least \p ilen.
+ * \param olen The length of the output data, to be updated with the
+ * actual number of Bytes written.
+ * \param tag The buffer holding the authentication tag.
+ * \param tag_len The length of the authentication tag.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return #MBEDCRYPTO_ERR_CIPHER_AUTH_FAILED if data is not authentic.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_auth_decrypt( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *ad, size_t ad_len,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen,
+ const unsigned char *tag, size_t tag_len );
+#endif /* MBEDCRYPTO_CIPHER_MODE_AEAD */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_CIPHER_H */
diff --git a/include/mbedcrypto/cipher_internal.h b/include/mbedcrypto/cipher_internal.h
new file mode 100644
index 0000000..3d4451b
--- /dev/null
+++ b/include/mbedcrypto/cipher_internal.h
@@ -0,0 +1,110 @@
+/**
+ * \file cipher_internal.h
+ *
+ * \brief Cipher wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_CIPHER_WRAP_H
+#define MBEDCRYPTO_CIPHER_WRAP_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Base cipher information. The non-mode specific functions and values.
+ */
+struct mbedcrypto_cipher_base_t
+{
+ /** Base Cipher type (e.g. MBEDCRYPTO_CIPHER_ID_AES) */
+ mbedcrypto_cipher_id_t cipher;
+
+ /** Encrypt using ECB */
+ int (*ecb_func)( void *ctx, mbedcrypto_operation_t mode,
+ const unsigned char *input, unsigned char *output );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ /** Encrypt using CBC */
+ int (*cbc_func)( void *ctx, mbedcrypto_operation_t mode, size_t length,
+ unsigned char *iv, const unsigned char *input,
+ unsigned char *output );
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ /** Encrypt using CFB (Full length) */
+ int (*cfb_func)( void *ctx, mbedcrypto_operation_t mode, size_t length, size_t *iv_off,
+ unsigned char *iv, const unsigned char *input,
+ unsigned char *output );
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ /** Encrypt using CTR */
+ int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
+ unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output );
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ /** Encrypt using STREAM */
+ int (*stream_func)( void *ctx, size_t length,
+ const unsigned char *input, unsigned char *output );
+#endif
+
+ /** Set key for encryption purposes */
+ int (*setkey_enc_func)( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen );
+
+ /** Set key for decryption purposes */
+ int (*setkey_dec_func)( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen);
+
+ /** Allocate a new context */
+ void * (*ctx_alloc_func)( void );
+
+ /** Free the given context */
+ void (*ctx_free_func)( void *ctx );
+
+};
+
+typedef struct
+{
+ mbedcrypto_cipher_type_t type;
+ const mbedcrypto_cipher_info_t *info;
+} mbedcrypto_cipher_definition_t;
+
+extern const mbedcrypto_cipher_definition_t mbedcrypto_cipher_definitions[];
+
+extern int mbedcrypto_cipher_supported[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_CIPHER_WRAP_H */
diff --git a/include/mbedcrypto/cmac.h b/include/mbedcrypto/cmac.h
new file mode 100644
index 0000000..4c697d1
--- /dev/null
+++ b/include/mbedcrypto/cmac.h
@@ -0,0 +1,206 @@
+/**
+ * \file cmac.h
+ *
+ * \brief This file contains CMAC definitions and functions.
+ *
+ * The Cipher-based Message Authentication Code (CMAC) Mode for
+ * Authentication is defined in <em>RFC-4493: The AES-CMAC Algorithm</em>.
+ */
+/*
+ * Copyright (C) 2015-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_CMAC_H
+#define MBEDCRYPTO_CMAC_H
+
+#include "mbedcrypto/cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MBEDCRYPTO_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */
+
+#define MBEDCRYPTO_AES_BLOCK_SIZE 16
+#define MBEDCRYPTO_DES3_BLOCK_SIZE 8
+
+#if defined(MBEDCRYPTO_AES_C)
+#define MBEDCRYPTO_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */
+#else
+#define MBEDCRYPTO_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */
+#endif
+
+#if !defined(MBEDCRYPTO_CMAC_ALT)
+
+/**
+ * The CMAC context structure.
+ */
+struct mbedcrypto_cmac_context_t
+{
+ /** The internal state of the CMAC algorithm. */
+ unsigned char state[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+
+ /** Unprocessed data - either data that was not block aligned and is still
+ * pending processing, or the final block. */
+ unsigned char unprocessed_block[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+
+ /** The length of data pending processing. */
+ size_t unprocessed_len;
+};
+
+#else /* !MBEDCRYPTO_CMAC_ALT */
+#include "cmac_alt.h"
+#endif /* !MBEDCRYPTO_CMAC_ALT */
+
+/**
+ * \brief This function sets the CMAC key, and prepares to authenticate
+ * the input data.
+ * Must be called with an initialized cipher context.
+ *
+ * \param ctx The cipher context used for the CMAC operation, initialized
+ * as one of the following types: MBEDCRYPTO_CIPHER_AES_128_ECB,
+ * MBEDCRYPTO_CIPHER_AES_192_ECB, MBEDCRYPTO_CIPHER_AES_256_ECB,
+ * or MBEDCRYPTO_CIPHER_DES_EDE3_ECB.
+ * \param key The CMAC key.
+ * \param keybits The length of the CMAC key in bits.
+ * Must be supported by the cipher.
+ *
+ * \return \c 0 on success.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedcrypto_cipher_cmac_starts( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *key, size_t keybits );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing CMAC
+ * computation.
+ *
+ * It is called between mbedcrypto_cipher_cmac_starts() or
+ * mbedcrypto_cipher_cmac_reset(), and mbedcrypto_cipher_cmac_finish().
+ * Can be called repeatedly.
+ *
+ * \param ctx The cipher context used for the CMAC operation.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA
+ * if parameter verification fails.
+ */
+int mbedcrypto_cipher_cmac_update( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *input, size_t ilen );
+
+/**
+ * \brief This function finishes the CMAC operation, and writes
+ * the result to the output buffer.
+ *
+ * It is called after mbedcrypto_cipher_cmac_update().
+ * It can be followed by mbedcrypto_cipher_cmac_reset() and
+ * mbedcrypto_cipher_cmac_update(), or mbedcrypto_cipher_free().
+ *
+ * \param ctx The cipher context used for the CMAC operation.
+ * \param output The output buffer for the CMAC checksum result.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA
+ * if parameter verification fails.
+ */
+int mbedcrypto_cipher_cmac_finish( mbedcrypto_cipher_context_t *ctx,
+ unsigned char *output );
+
+/**
+ * \brief This function prepares the authentication of another
+ * message with the same key as the previous CMAC
+ * operation.
+ *
+ * It is called after mbedcrypto_cipher_cmac_finish()
+ * and before mbedcrypto_cipher_cmac_update().
+ *
+ * \param ctx The cipher context used for the CMAC operation.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA
+ * if parameter verification fails.
+ */
+int mbedcrypto_cipher_cmac_reset( mbedcrypto_cipher_context_t *ctx );
+
+/**
+ * \brief This function calculates the full generic CMAC
+ * on the input buffer with the provided key.
+ *
+ * The function allocates the context, performs the
+ * calculation, and frees the context.
+ *
+ * The CMAC result is calculated as
+ * output = generic CMAC(cmac key, input buffer).
+ *
+ *
+ * \param cipher_info The cipher information.
+ * \param key The CMAC key.
+ * \param keylen The length of the CMAC key in bits.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ * \param output The buffer for the generic CMAC result.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA
+ * if parameter verification fails.
+ */
+int mbedcrypto_cipher_cmac( const mbedcrypto_cipher_info_t *cipher_info,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+#if defined(MBEDCRYPTO_AES_C)
+/**
+ * \brief This function implements the AES-CMAC-PRF-128 pseudorandom
+ * function, as defined in
+ * <em>RFC-4615: The Advanced Encryption Standard-Cipher-based
+ * Message Authentication Code-Pseudo-Random Function-128
+ * (AES-CMAC-PRF-128) Algorithm for the Internet Key
+ * Exchange Protocol (IKE).</em>
+ *
+ * \param key The key to use.
+ * \param key_len The key length in Bytes.
+ * \param input The buffer holding the input data.
+ * \param in_len The length of the input data in Bytes.
+ * \param output The buffer holding the generated 16 Bytes of
+ * pseudorandom output.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_aes_cmac_prf_128( const unsigned char *key, size_t key_len,
+ const unsigned char *input, size_t in_len,
+ unsigned char output[16] );
+#endif /* MBEDCRYPTO_AES_C */
+
+#if defined(MBEDCRYPTO_SELF_TEST) && ( defined(MBEDCRYPTO_AES_C) || defined(MBEDCRYPTO_DES_C) )
+/**
+ * \brief The CMAC checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedcrypto_cmac_self_test( int verbose );
+#endif /* MBEDCRYPTO_SELF_TEST && ( MBEDCRYPTO_AES_C || MBEDCRYPTO_DES_C ) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_CMAC_H */
diff --git a/include/mbedcrypto/config.h b/include/mbedcrypto/config.h
new file mode 100644
index 0000000..502b42f
--- /dev/null
+++ b/include/mbedcrypto/config.h
@@ -0,0 +1,1753 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration with all cryptography features and no X.509 or TLS.
+ *
+ * This configuration is intended to prototype the PSA reference implementation.
+ */
+/*
+ * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_CONFIG_H
+#define MBEDCRYPTO_CONFIG_H
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+
+/**
+ * \def MBEDCRYPTO_HAVE_ASM
+ *
+ * The compiler has support for asm().
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ * library/timing.c
+ * library/padlock.c
+ * include/mbedcrypto/bn_mul.h
+ *
+ * Comment to disable the use of assembly code.
+ */
+#define MBEDCRYPTO_HAVE_ASM
+
+/**
+ * \def MBEDCRYPTO_NO_UDBL_DIVISION
+ *
+ * The platform lacks support for double-width integer division (64-bit
+ * division on a 32-bit platform, 128-bit division on a 64-bit platform).
+ *
+ * Used in:
+ * include/mbedcrypto/bignum.h
+ * library/bignum.c
+ *
+ * The bignum code uses double-width division to speed up some operations.
+ * Double-width division is often implemented in software that needs to
+ * be linked with the program. The presence of a double-width integer
+ * type is usually detected automatically through preprocessor macros,
+ * but the automatic detection cannot know whether the code needs to
+ * and can be linked with an implementation of division for that type.
+ * By default division is assumed to be usable if the type is present.
+ * Uncomment this option to prevent the use of double-width division.
+ *
+ * Note that division for the native integer type is always required.
+ * Furthermore, a 64-bit type is always required even on a 32-bit
+ * platform, but it need not support multiplication or division. In some
+ * cases it is also desirable to disable some double-width operations. For
+ * example, if double-width division is implemented in software, disabling
+ * it can reduce code size in some embedded targets.
+ */
+//#define MBEDCRYPTO_NO_UDBL_DIVISION
+
+/**
+ * \def MBEDCRYPTO_HAVE_SSE2
+ *
+ * CPU supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ */
+//#define MBEDCRYPTO_HAVE_SSE2
+
+/**
+ * \def MBEDCRYPTO_PLATFORM_MEMORY
+ *
+ * Enable the memory allocation layer.
+ *
+ * By default Mbed Crypto uses the system-provided calloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling MBEDCRYPTO_PLATFORM_MEMORY without the
+ * MBEDCRYPTO_PLATFORM_{FREE,CALLOC}_MACROs will provide
+ * "mbedcrypto_platform_set_calloc_free()" allowing you to set an alternative calloc() and
+ * free() function pointer at runtime.
+ *
+ * Enabling MBEDCRYPTO_PLATFORM_MEMORY and specifying
+ * MBEDCRYPTO_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
+ * alternate function at compile time.
+ *
+ * Requires: MBEDCRYPTO_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
+ */
+//#define MBEDCRYPTO_PLATFORM_MEMORY
+
+/**
+ * \def MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS
+ *
+ * Do not assign standard functions in the platform layer (e.g. calloc() to
+ * MBEDCRYPTO_PLATFORM_STD_CALLOC and printf() to MBEDCRYPTO_PLATFORM_STD_PRINTF)
+ *
+ * This makes sure there are no linking errors on platforms that do not support
+ * these functions. You will HAVE to provide alternatives, either at runtime
+ * via the platform_set_xxx() functions or at compile time by setting
+ * the MBEDCRYPTO_PLATFORM_STD_XXX defines, or enabling a
+ * MBEDCRYPTO_PLATFORM_XXX_MACRO.
+ *
+ * Requires: MBEDCRYPTO_PLATFORM_C
+ *
+ * Uncomment to prevent default assignment of standard functions in the
+ * platform layer.
+ */
+//#define MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS
+
+/**
+ * \def MBEDCRYPTO_PLATFORM_EXIT_ALT
+ *
+ * MBEDCRYPTO_PLATFORM_XXX_ALT: Uncomment a macro to let Mbed Crypto support the
+ * function in the platform abstraction layer.
+ *
+ * Example: In case you uncomment MBEDCRYPTO_PLATFORM_PRINTF_ALT, Mbed Crypto will
+ * provide a function "mbedcrypto_platform_set_printf()" that allows you to set an
+ * alternative printf function pointer.
+ *
+ * All these define require MBEDCRYPTO_PLATFORM_C to be defined!
+ *
+ * \note MBEDCRYPTO_PLATFORM_SNPRINTF_ALT is required on Windows;
+ * it will be enabled automatically by check_config.h
+ *
+ * \warning MBEDCRYPTO_PLATFORM_XXX_ALT cannot be defined at the same time as
+ * MBEDCRYPTO_PLATFORM_XXX_MACRO!
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+//#define MBEDCRYPTO_PLATFORM_EXIT_ALT
+//#define MBEDCRYPTO_PLATFORM_FPRINTF_ALT
+//#define MBEDCRYPTO_PLATFORM_PRINTF_ALT
+//#define MBEDCRYPTO_PLATFORM_SNPRINTF_ALT
+//#define MBEDCRYPTO_PLATFORM_NV_SEED_ALT
+//#define MBEDCRYPTO_PLATFORM_SETUP_TEARDOWN_ALT
+
+/**
+ * \def MBEDCRYPTO_DEPRECATED_WARNING
+ *
+ * Mark deprecated functions so that they generate a warning if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * This only works with GCC and Clang. With other compilers, you may want to
+ * use MBEDCRYPTO_DEPRECATED_REMOVED
+ *
+ * Uncomment to get warnings on using deprecated functions.
+ */
+//#define MBEDCRYPTO_DEPRECATED_WARNING
+
+/**
+ * \def MBEDCRYPTO_DEPRECATED_REMOVED
+ *
+ * Remove deprecated functions so that they generate an error if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * Uncomment to get errors on using deprecated functions.
+ */
+//#define MBEDCRYPTO_DEPRECATED_REMOVED
+
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: Mbed Crypto feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def MBEDCRYPTO_AES_ALT
+ *
+ * MBEDCRYPTO__MODULE_NAME__ALT: Uncomment a macro to let Mbed Crypto use your
+ * alternate core implementation of a symmetric crypto, an arithmetic or hash
+ * module (e.g. platform specific assembly optimized implementations). Keep
+ * in mind that the function prototypes should remain the same.
+ *
+ * This replaces the whole module. If you only want to replace one of the
+ * functions, use one of the MBEDCRYPTO__FUNCTION_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDCRYPTO_AES_ALT, Mbed Crypto will no longer
+ * provide the "struct mbedcrypto_aes_context" definition and omit the base
+ * function declarations and implementations. "aes_alt.h" will be included from
+ * "aes.h" to include the new function definitions.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * module.
+ *
+ * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their
+ * use constitutes a security risk. If possible, we recommend
+ * avoiding dependencies on them, and considering stronger message
+ * digests and ciphers instead.
+ *
+ */
+//#define MBEDCRYPTO_AES_ALT
+//#define MBEDCRYPTO_ARC4_ALT
+//#define MBEDCRYPTO_BLOWFISH_ALT
+//#define MBEDCRYPTO_CAMELLIA_ALT
+//#define MBEDCRYPTO_CCM_ALT
+//#define MBEDCRYPTO_CMAC_ALT
+//#define MBEDCRYPTO_DES_ALT
+//#define MBEDCRYPTO_DHM_ALT
+//#define MBEDCRYPTO_ECJPAKE_ALT
+//#define MBEDCRYPTO_GCM_ALT
+//#define MBEDCRYPTO_MD2_ALT
+//#define MBEDCRYPTO_MD4_ALT
+//#define MBEDCRYPTO_MD5_ALT
+//#define MBEDCRYPTO_RIPEMD160_ALT
+//#define MBEDCRYPTO_RSA_ALT
+//#define MBEDCRYPTO_SHA1_ALT
+//#define MBEDCRYPTO_SHA256_ALT
+//#define MBEDCRYPTO_SHA512_ALT
+//#define MBEDCRYPTO_XTEA_ALT
+/*
+ * When replacing the elliptic curve module, pleace consider, that it is
+ * implemented with two .c files:
+ * - ecp.c
+ * - ecp_curves.c
+ * You can replace them very much like all the other MBEDCRYPTO__MODULE_NAME__ALT
+ * macros as described above. The only difference is that you have to make sure
+ * that you provide functionality for both .c files.
+ */
+//#define MBEDCRYPTO_ECP_ALT
+
+/**
+ * \def MBEDCRYPTO_MD2_PROCESS_ALT
+ *
+ * MBEDCRYPTO__FUNCTION_NAME__ALT: Uncomment a macro to let Mbed Crypto use you
+ * alternate core implementation of symmetric crypto or hash function. Keep in
+ * mind that function prototypes should remain the same.
+ *
+ * This replaces only one function. The header file from Mbed Crypto is still
+ * used, in contrast to the MBEDCRYPTO__MODULE_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDCRYPTO_SHA256_PROCESS_ALT, Mbed Crypto will
+ * no longer provide the mbedcrypto_sha1_process() function, but it will still provide
+ * the other function (using your mbedcrypto_sha1_process() function) and the definition
+ * of mbedcrypto_sha1_context, so your implementation of mbedcrypto_sha1_process must be compatible
+ * with this definition.
+ *
+ * \note Because of a signature change, the core AES encryption and decryption routines are
+ * currently named mbedcrypto_aes_internal_encrypt and mbedcrypto_aes_internal_decrypt,
+ * respectively. When setting up alternative implementations, these functions should
+ * be overriden, but the wrapper functions mbedcrypto_aes_decrypt and mbedcrypto_aes_encrypt
+ * must stay untouched.
+ *
+ * \note If you use the AES_xxx_ALT macros, then is is recommended to also set
+ * MBEDCRYPTO_AES_ROM_TABLES in order to help the linker garbage-collect the AES
+ * tables.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ *
+ * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use
+ * constitutes a security risk. If possible, we recommend avoiding
+ * dependencies on them, and considering stronger message digests
+ * and ciphers instead.
+ *
+ */
+//#define MBEDCRYPTO_MD2_PROCESS_ALT
+//#define MBEDCRYPTO_MD4_PROCESS_ALT
+//#define MBEDCRYPTO_MD5_PROCESS_ALT
+//#define MBEDCRYPTO_RIPEMD160_PROCESS_ALT
+//#define MBEDCRYPTO_SHA1_PROCESS_ALT
+//#define MBEDCRYPTO_SHA256_PROCESS_ALT
+//#define MBEDCRYPTO_SHA512_PROCESS_ALT
+//#define MBEDCRYPTO_DES_SETKEY_ALT
+//#define MBEDCRYPTO_DES_CRYPT_ECB_ALT
+//#define MBEDCRYPTO_DES3_CRYPT_ECB_ALT
+//#define MBEDCRYPTO_AES_SETKEY_ENC_ALT
+//#define MBEDCRYPTO_AES_SETKEY_DEC_ALT
+//#define MBEDCRYPTO_AES_ENCRYPT_ALT
+//#define MBEDCRYPTO_AES_DECRYPT_ALT
+//#define MBEDCRYPTO_ECDH_GEN_PUBLIC_ALT
+//#define MBEDCRYPTO_ECDH_COMPUTE_SHARED_ALT
+//#define MBEDCRYPTO_ECDSA_VERIFY_ALT
+//#define MBEDCRYPTO_ECDSA_SIGN_ALT
+//#define MBEDCRYPTO_ECDSA_GENKEY_ALT
+
+/**
+ * \def MBEDCRYPTO_ECP_INTERNAL_ALT
+ *
+ * Expose a part of the internal interface of the Elliptic Curve Point module.
+ *
+ * MBEDCRYPTO_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let Mbed Crypto use your
+ * alternative core implementation of elliptic curve arithmetic. Keep in mind
+ * that function prototypes should remain the same.
+ *
+ * This partially replaces one function. The header file from Mbed Crypto is still
+ * used, in contrast to the MBEDCRYPTO_ECP_ALT flag. The original implementation
+ * is still present and it is used for group structures not supported by the
+ * alternative.
+ *
+ * Any of these options become available by defining MBEDCRYPTO_ECP_INTERNAL_ALT
+ * and implementing the following functions:
+ * unsigned char mbedcrypto_internal_ecp_grp_capable(
+ * const mbedcrypto_ecp_group *grp )
+ * int mbedcrypto_internal_ecp_init( const mbedcrypto_ecp_group *grp )
+ * void mbedcrypto_internal_ecp_deinit( const mbedcrypto_ecp_group *grp )
+ * The mbedcrypto_internal_ecp_grp_capable function should return 1 if the
+ * replacement functions implement arithmetic for the given group and 0
+ * otherwise.
+ * The functions mbedcrypto_internal_ecp_init and mbedcrypto_internal_ecp_deinit are
+ * called before and after each point operation and provide an opportunity to
+ * implement optimized set up and tear down instructions.
+ *
+ * Example: In case you uncomment MBEDCRYPTO_ECP_INTERNAL_ALT and
+ * MBEDCRYPTO_ECP_DOUBLE_JAC_ALT, Mbed Crypto will still provide the ecp_double_jac
+ * function, but will use your mbedcrypto_internal_ecp_double_jac if the group is
+ * supported (your mbedcrypto_internal_ecp_grp_capable function returns 1 when
+ * receives it as an argument). If the group is not supported then the original
+ * implementation is used. The other functions and the definition of
+ * mbedcrypto_ecp_group and mbedcrypto_ecp_point will not change, so your
+ * implementation of mbedcrypto_internal_ecp_double_jac and
+ * mbedcrypto_internal_ecp_grp_capable must be compatible with this definition.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ */
+/* Required for all the functions in this section */
+//#define MBEDCRYPTO_ECP_INTERNAL_ALT
+/* Support for Weierstrass curves with Jacobi representation */
+//#define MBEDCRYPTO_ECP_RANDOMIZE_JAC_ALT
+//#define MBEDCRYPTO_ECP_ADD_MIXED_ALT
+//#define MBEDCRYPTO_ECP_DOUBLE_JAC_ALT
+//#define MBEDCRYPTO_ECP_NORMALIZE_JAC_MANY_ALT
+//#define MBEDCRYPTO_ECP_NORMALIZE_JAC_ALT
+/* Support for curves with Montgomery arithmetic */
+//#define MBEDCRYPTO_ECP_DOUBLE_ADD_MXZ_ALT
+//#define MBEDCRYPTO_ECP_RANDOMIZE_MXZ_ALT
+//#define MBEDCRYPTO_ECP_NORMALIZE_MXZ_ALT
+
+/**
+ * \def MBEDCRYPTO_TEST_NULL_ENTROPY
+ *
+ * Enables testing and use of Mbed Crypto without any configured entropy sources.
+ * This permits use of the library on platforms before an entropy source has
+ * been integrated (see for example the MBEDCRYPTO_ENTROPY_HARDWARE_ALT or the
+ * MBEDCRYPTO_ENTROPY_NV_SEED switches).
+ *
+ * WARNING! This switch MUST be disabled in production builds, and is suitable
+ * only for development.
+ * Enabling the switch negates any security provided by the library.
+ *
+ * Requires MBEDCRYPTO_ENTROPY_C, MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ */
+//#define MBEDCRYPTO_TEST_NULL_ENTROPY
+
+/**
+ * \def MBEDCRYPTO_ENTROPY_HARDWARE_ALT
+ *
+ * Uncomment this macro to let Mbed Crypto use your own implementation of a
+ * hardware entropy collector.
+ *
+ * Your function must be called \c mbedcrypto_hardware_poll(), have the same
+ * prototype as declared in entropy_poll.h, and accept NULL as first argument.
+ *
+ * Uncomment to use your own hardware entropy collector.
+ */
+//#define MBEDCRYPTO_ENTROPY_HARDWARE_ALT
+
+/**
+ * \def MBEDCRYPTO_AES_ROM_TABLES
+ *
+ * Use precomputed AES tables stored in ROM.
+ *
+ * Uncomment this macro to use precomputed AES tables stored in ROM.
+ * Comment this macro to generate AES tables in RAM at runtime.
+ *
+ * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb
+ * (or ~2kb if \c MBEDCRYPTO_AES_FEWER_TABLES is used) and reduces the
+ * initialization time before the first AES operation can be performed.
+ * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c
+ * MBEDCRYPTO_AES_FEWER_TABLES below is used), and potentially degraded
+ * performance if ROM access is slower than RAM access.
+ *
+ * This option is independent of \c MBEDCRYPTO_AES_FEWER_TABLES.
+ *
+ */
+//#define MBEDCRYPTO_AES_ROM_TABLES
+
+/**
+ * \def MBEDCRYPTO_AES_FEWER_TABLES
+ *
+ * Use less ROM/RAM for AES tables.
+ *
+ * Uncommenting this macro omits 75% of the AES tables from
+ * ROM / RAM (depending on the value of \c MBEDCRYPTO_AES_ROM_TABLES)
+ * by computing their values on the fly during operations
+ * (the tables are entry-wise rotations of one another).
+ *
+ * Tradeoff: Uncommenting this reduces the RAM / ROM footprint
+ * by ~6kb but at the cost of more arithmetic operations during
+ * runtime. Specifically, one has to compare 4 accesses within
+ * different tables to 4 accesses with additional arithmetic
+ * operations within the same table. The performance gain/loss
+ * depends on the system and memory details.
+ *
+ * This option is independent of \c MBEDCRYPTO_AES_ROM_TABLES.
+ *
+ */
+//#define MBEDCRYPTO_AES_FEWER_TABLES
+
+/**
+ * \def MBEDCRYPTO_CAMELLIA_SMALL_MEMORY
+ *
+ * Use less ROM for the Camellia implementation (saves about 768 bytes).
+ *
+ * Uncomment this macro to use less memory for Camellia.
+ */
+//#define MBEDCRYPTO_CAMELLIA_SMALL_MEMORY
+
+/**
+ * \def MBEDCRYPTO_CIPHER_MODE_CBC
+ *
+ * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
+ */
+#define MBEDCRYPTO_CIPHER_MODE_CBC
+
+/**
+ * \def MBEDCRYPTO_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+#define MBEDCRYPTO_CIPHER_MODE_CFB
+
+/**
+ * \def MBEDCRYPTO_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define MBEDCRYPTO_CIPHER_MODE_CTR
+
+/**
+ * \def MBEDCRYPTO_CIPHER_PADDING_PKCS7
+ *
+ * MBEDCRYPTO_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for
+ * specific padding modes in the cipher layer with cipher modes that support
+ * padding (e.g. CBC)
+ *
+ * If you disable all padding modes, only full blocks can be used with CBC.
+ *
+ * Enable padding modes in the cipher layer.
+ */
+#define MBEDCRYPTO_CIPHER_PADDING_PKCS7
+#define MBEDCRYPTO_CIPHER_PADDING_ONE_AND_ZEROS
+#define MBEDCRYPTO_CIPHER_PADDING_ZEROS_AND_LEN
+#define MBEDCRYPTO_CIPHER_PADDING_ZEROS
+
+/**
+ * \def MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED
+ *
+ * MBEDCRYPTO_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve
+ * module. By default all supported curves are enabled.
+ *
+ * Comment macros to disable the curve and functions for it
+ */
+#define MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED
+#define MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED
+#define MBEDCRYPTO_ECP_DP_BP256R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_BP384R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_BP512R1_ENABLED
+#define MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED
+#define MBEDCRYPTO_ECP_DP_CURVE448_ENABLED
+
+/**
+ * \def MBEDCRYPTO_ECP_NIST_OPTIM
+ *
+ * Enable specific 'modulo p' routines for each NIST prime.
+ * Depending on the prime and architecture, makes operations 4 to 8 times
+ * faster on the corresponding curve.
+ *
+ * Comment this macro to disable NIST curves optimisation.
+ */
+#define MBEDCRYPTO_ECP_NIST_OPTIM
+
+/**
+ * \def MBEDCRYPTO_ECDSA_DETERMINISTIC
+ *
+ * Enable deterministic ECDSA (RFC 6979).
+ * Standard ECDSA is "fragile" in the sense that lack of entropy when signing
+ * may result in a compromise of the long-term signing key. This is avoided by
+ * the deterministic variant.
+ *
+ * Requires: MBEDCRYPTO_HMAC_DRBG_C
+ *
+ * Comment this macro to disable deterministic ECDSA.
+ */
+#define MBEDCRYPTO_ECDSA_DETERMINISTIC
+
+/**
+ * \def MBEDCRYPTO_PK_PARSE_EC_EXTENDED
+ *
+ * Enhance support for reading EC keys using variants of SEC1 not allowed by
+ * RFC 5915 and RFC 5480.
+ *
+ * Currently this means parsing the SpecifiedECDomain choice of EC
+ * parameters (only known groups are supported, not arbitrary domains, to
+ * avoid validation issues).
+ *
+ * Disable if you only need to support RFC 5915 + 5480 key formats.
+ */
+#define MBEDCRYPTO_PK_PARSE_EC_EXTENDED
+
+/**
+ * \def MBEDCRYPTO_ERROR_STRERROR_DUMMY
+ *
+ * Enable a dummy error function to make use of mbedcrypto_strerror() in
+ * third party libraries easier when MBEDCRYPTO_ERROR_C is disabled
+ * (no effect when MBEDCRYPTO_ERROR_C is enabled).
+ *
+ * You can safely disable this if MBEDCRYPTO_ERROR_C is enabled, or if you're
+ * not using mbedcrypto_strerror() or error_strerror() in your application.
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * mbedcrypto_strerror()
+ */
+#define MBEDCRYPTO_ERROR_STRERROR_DUMMY
+
+/**
+ * \def MBEDCRYPTO_GENPRIME
+ *
+ * Enable the prime-number generation code.
+ *
+ * Requires: MBEDCRYPTO_BIGNUM_C
+ */
+#define MBEDCRYPTO_GENPRIME
+
+/**
+ * \def MBEDCRYPTO_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+#define MBEDCRYPTO_FS_IO
+
+/**
+ * \def MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * mbedcrypto_timing_hardclock and HAVEGE based poll functions.
+ *
+ * This is useful to have more control over the added entropy sources in an
+ * application.
+ *
+ * Uncomment this macro to prevent loading of default entropy functions.
+ */
+//#define MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES
+
+/**
+ * \def MBEDCRYPTO_NO_PLATFORM_ENTROPY
+ *
+ * Do not use built-in platform entropy functions.
+ * This is useful if your platform does not support
+ * standards like the /dev/urandom or Windows CryptoAPI.
+ *
+ * Uncomment this macro to disable the built-in platform entropy functions.
+ */
+//#define MBEDCRYPTO_NO_PLATFORM_ENTROPY
+
+/**
+ * \def MBEDCRYPTO_ENTROPY_FORCE_SHA256
+ *
+ * Force the entropy accumulator to use a SHA-256 accumulator instead of the
+ * default SHA-512 based one (if both are available).
+ *
+ * Requires: MBEDCRYPTO_SHA256_C
+ *
+ * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option
+ * if you have performance concerns.
+ *
+ * This option is only useful if both MBEDCRYPTO_SHA256_C and
+ * MBEDCRYPTO_SHA512_C are defined. Otherwise the available hash module is used.
+ */
+//#define MBEDCRYPTO_ENTROPY_FORCE_SHA256
+
+/**
+ * \def MBEDCRYPTO_ENTROPY_NV_SEED
+ *
+ * Enable the non-volatile (NV) seed file-based entropy source.
+ * (Also enables the NV seed read/write functions in the platform layer)
+ *
+ * This is crucial (if not required) on systems that do not have a
+ * cryptographic entropy source (in hardware or kernel) available.
+ *
+ * Requires: MBEDCRYPTO_ENTROPY_C, MBEDCRYPTO_PLATFORM_C
+ *
+ * \note The read/write functions that are used by the entropy source are
+ * determined in the platform layer, and can be modified at runtime and/or
+ * compile-time depending on the flags (MBEDCRYPTO_PLATFORM_NV_SEED_*) used.
+ *
+ * \note If you use the default implementation functions that read a seedfile
+ * with regular fopen(), please make sure you make a seedfile with the
+ * proper name (defined in MBEDCRYPTO_PLATFORM_STD_NV_SEED_FILE) and at
+ * least MBEDCRYPTO_ENTROPY_BLOCK_SIZE bytes in size that can be read from
+ * and written to or you will get an entropy source error! The default
+ * implementation will only use the first MBEDCRYPTO_ENTROPY_BLOCK_SIZE
+ * bytes from the file.
+ *
+ * \note The entropy collector will write to the seed file before entropy is
+ * given to an external source, to update it.
+ */
+//#define MBEDCRYPTO_ENTROPY_NV_SEED
+
+/**
+ * \def MBEDCRYPTO_MEMORY_DEBUG
+ *
+ * Enable debugging of buffer allocator memory issues. Automatically prints
+ * (to stderr) all (fatal) messages on memory allocation issues. Enables
+ * function for 'debug output' of allocated memory.
+ *
+ * Requires: MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C
+ *
+ * Uncomment this macro to let the buffer allocator print out error messages.
+ */
+//#define MBEDCRYPTO_MEMORY_DEBUG
+
+/**
+ * \def MBEDCRYPTO_MEMORY_BACKTRACE
+ *
+ * Include backtrace information with each allocated block.
+ *
+ * Requires: MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C
+ * GLIBC-compatible backtrace() an backtrace_symbols() support
+ *
+ * Uncomment this macro to include backtrace information
+ */
+//#define MBEDCRYPTO_MEMORY_BACKTRACE
+
+/**
+ * \def MBEDCRYPTO_PK_RSA_ALT_SUPPORT
+ *
+ * Support external private RSA keys (eg from a HSM) in the PK layer.
+ *
+ * Comment this macro to disable support for external private RSA keys.
+ */
+#define MBEDCRYPTO_PK_RSA_ALT_SUPPORT
+
+/**
+ * \def MBEDCRYPTO_PKCS1_V15
+ *
+ * Enable support for PKCS#1 v1.5 encoding.
+ *
+ * Requires: MBEDCRYPTO_RSA_C
+ *
+ * This enables support for PKCS#1 v1.5 operations.
+ */
+#define MBEDCRYPTO_PKCS1_V15
+
+/**
+ * \def MBEDCRYPTO_PKCS1_V21
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ *
+ * Requires: MBEDCRYPTO_MD_C, MBEDCRYPTO_RSA_C
+ *
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define MBEDCRYPTO_PKCS1_V21
+
+/**
+ * \def MBEDCRYPTO_PSA_CRYPTO_SPM
+ *
+ * When MBEDCRYPTO_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure
+ * Partition Manager) integration which separates the code into two parts: a
+ * NSPE (Non-Secure Process Environment) and an SPE (Secure Process
+ * Environment).
+ *
+ * Module: library/psa_crypto.c
+ * Requires: MBEDCRYPTO_PSA_CRYPTO_C
+ *
+ */
+//#define MBEDCRYPTO_PSA_CRYPTO_SPM
+
+/**
+ * \def MBEDCRYPTO_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+ */
+//#define MBEDCRYPTO_RSA_NO_CRT
+
+/**
+ * \def MBEDCRYPTO_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+#define MBEDCRYPTO_SELF_TEST
+
+/**
+ * \def MBEDCRYPTO_SHA256_SMALLER
+ *
+ * Enable an implementation of SHA-256 that has lower ROM footprint but also
+ * lower performance.
+ *
+ * The default implementation is meant to be a reasonnable compromise between
+ * performance and size. This version optimizes more aggressively for size at
+ * the expense of performance. Eg on Cortex-M4 it reduces the size of
+ * mbedcrypto_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
+ * 30%.
+ *
+ * Uncomment to enable the smaller implementation of SHA256.
+ */
+//#define MBEDCRYPTO_SHA256_SMALLER
+
+/**
+ * \def MBEDCRYPTO_THREADING_ALT
+ *
+ * Provide your own alternate threading implementation.
+ *
+ * Requires: MBEDCRYPTO_THREADING_C
+ *
+ * Uncomment this to allow your own alternate threading implementation.
+ */
+//#define MBEDCRYPTO_THREADING_ALT
+
+/**
+ * \def MBEDCRYPTO_THREADING_PTHREAD
+ *
+ * Enable the pthread wrapper layer for the threading layer.
+ *
+ * Requires: MBEDCRYPTO_THREADING_C
+ *
+ * Uncomment this to enable pthread mutexes.
+ */
+//#define MBEDCRYPTO_THREADING_PTHREAD
+
+/**
+ * \def MBEDCRYPTO_VERSION_FEATURES
+ *
+ * Allow run-time checking of compile-time enabled features. Thus allowing users
+ * to check at run-time if the library is for instance compiled with threading
+ * support via mbedcrypto_version_check_feature().
+ *
+ * Requires: MBEDCRYPTO_VERSION_C
+ *
+ * Comment this to disable run-time checking and save ROM space
+ */
+#define MBEDCRYPTO_VERSION_FEATURES
+
+/* \} name SECTION: Mbed Crypto feature support */
+
+/**
+ * \name SECTION: Mbed Crypto modules
+ *
+ * This section enables or disables entire modules in Mbed Crypto
+ * \{
+ */
+
+/**
+ * \def MBEDCRYPTO_AESNI_C
+ *
+ * Enable AES-NI support on x86-64.
+ *
+ * Module: library/aesni.c
+ * Caller: library/aes.c
+ *
+ * Requires: MBEDCRYPTO_HAVE_ASM
+ *
+ * This modules adds support for the AES-NI instructions on x86-64
+ */
+#define MBEDCRYPTO_AESNI_C
+
+/**
+ * \def MBEDCRYPTO_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module: library/aes.c
+ * Caller: library/ssl_tls.c
+ * library/pem.c
+ * library/ctr_drbg.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ * MBEDCRYPTO_TLS_RSA_WITH_AES_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_RSA_WITH_AES_256_CBC_SHA256
+ * MBEDCRYPTO_TLS_RSA_WITH_AES_256_CBC_SHA
+ * MBEDCRYPTO_TLS_RSA_WITH_AES_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_RSA_WITH_AES_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_RSA_WITH_AES_128_CBC_SHA
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ * MBEDCRYPTO_TLS_PSK_WITH_AES_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_PSK_WITH_AES_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_PSK_WITH_AES_256_CBC_SHA
+ * MBEDCRYPTO_TLS_PSK_WITH_AES_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_PSK_WITH_AES_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_PSK_WITH_AES_128_CBC_SHA
+ *
+ * PEM_PARSE uses AES for decrypting encrypted keys.
+ */
+#define MBEDCRYPTO_AES_C
+
+/**
+ * \def MBEDCRYPTO_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module: library/arc4.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_RC4_128_SHA
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ * MBEDCRYPTO_TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_RC4_128_SHA
+ * MBEDCRYPTO_TLS_RSA_WITH_RC4_128_SHA
+ * MBEDCRYPTO_TLS_RSA_WITH_RC4_128_MD5
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_RC4_128_SHA
+ * MBEDCRYPTO_TLS_PSK_WITH_RC4_128_SHA
+ *
+ * \warning ARC4 is considered a weak cipher and its use constitutes a
+ * security risk. If possible, we recommend avoidng dependencies on
+ * it, and considering stronger ciphers instead.
+ *
+ */
+#define MBEDCRYPTO_ARC4_C
+
+/**
+ * \def MBEDCRYPTO_ASN1_PARSE_C
+ *
+ * Enable the generic ASN1 parser.
+ *
+ * Module: library/asn1.c
+ * Caller: library/x509.c
+ * library/dhm.c
+ * library/pkcs12.c
+ * library/pkcs5.c
+ * library/pkparse.c
+ */
+#define MBEDCRYPTO_ASN1_PARSE_C
+
+/**
+ * \def MBEDCRYPTO_ASN1_WRITE_C
+ *
+ * Enable the generic ASN1 writer.
+ *
+ * Module: library/asn1write.c
+ * Caller: library/ecdsa.c
+ * library/pkwrite.c
+ * library/x509_create.c
+ * library/x509write_crt.c
+ * library/x509write_csr.c
+ */
+#define MBEDCRYPTO_ASN1_WRITE_C
+
+/**
+ * \def MBEDCRYPTO_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module: library/base64.c
+ * Caller: library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+#define MBEDCRYPTO_BASE64_C
+
+/**
+ * \def MBEDCRYPTO_BIGNUM_C
+ *
+ * Enable the multi-precision integer library.
+ *
+ * Module: library/bignum.c
+ * Caller: library/dhm.c
+ * library/ecp.c
+ * library/ecdsa.c
+ * library/rsa.c
+ * library/rsa_internal.c
+ * library/ssl_tls.c
+ *
+ * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support.
+ */
+#define MBEDCRYPTO_BIGNUM_C
+
+/**
+ * \def MBEDCRYPTO_BLOWFISH_C
+ *
+ * Enable the Blowfish block cipher.
+ *
+ * Module: library/blowfish.c
+ */
+#define MBEDCRYPTO_BLOWFISH_C
+
+/**
+ * \def MBEDCRYPTO_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module: library/camellia.c
+ * Caller: library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ * MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ * MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ * MBEDCRYPTO_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ * MBEDCRYPTO_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ * MBEDCRYPTO_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ * MBEDCRYPTO_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ */
+#define MBEDCRYPTO_CAMELLIA_C
+
+/**
+ * \def MBEDCRYPTO_CCM_C
+ *
+ * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
+ *
+ * Module: library/ccm.c
+ *
+ * Requires: MBEDCRYPTO_AES_C or MBEDCRYPTO_CAMELLIA_C
+ *
+ * This module enables the AES-CCM ciphersuites, if other requisites are
+ * enabled as well.
+ */
+#define MBEDCRYPTO_CCM_C
+
+/**
+ * \def MBEDCRYPTO_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module: library/cipher.c
+ * Caller: library/ssl_tls.c
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define MBEDCRYPTO_CIPHER_C
+
+/**
+ * \def MBEDCRYPTO_CMAC_C
+ *
+ * Enable the CMAC (Cipher-based Message Authentication Code) mode for block
+ * ciphers.
+ *
+ * Module: library/cmac.c
+ *
+ * Requires: MBEDCRYPTO_AES_C or MBEDCRYPTO_DES_C
+ *
+ */
+#define MBEDCRYPTO_CMAC_C
+
+/**
+ * \def MBEDCRYPTO_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-256-based random generator.
+ *
+ * Module: library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDCRYPTO_AES_C
+ *
+ * This module provides the CTR_DRBG AES-256 random number generator.
+ */
+#define MBEDCRYPTO_CTR_DRBG_C
+
+/**
+ * \def MBEDCRYPTO_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module: library/des.c
+ * Caller: library/pem.c
+ * library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ * MBEDCRYPTO_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ * MBEDCRYPTO_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ * MBEDCRYPTO_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ * MBEDCRYPTO_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ * MBEDCRYPTO_TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ * MBEDCRYPTO_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ * MBEDCRYPTO_TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *
+ * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers instead.
+ */
+#define MBEDCRYPTO_DES_C
+
+/**
+ * \def MBEDCRYPTO_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle module.
+ *
+ * Module: library/dhm.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * This module is used by the following key exchanges:
+ * DHE-RSA, DHE-PSK
+ *
+ * \warning Using DHE constitutes a security risk as it
+ * is not possible to validate custom DH parameters.
+ * If possible, it is recommended users should consider
+ * preferring other methods of key exchange.
+ * See dhm.h for more details.
+ *
+ */
+#define MBEDCRYPTO_DHM_C
+
+/**
+ * \def MBEDCRYPTO_ECDH_C
+ *
+ * Enable the elliptic curve Diffie-Hellman library.
+ *
+ * Module: library/ecdh.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * This module is used by the following key exchanges:
+ * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK
+ *
+ * Requires: MBEDCRYPTO_ECP_C
+ */
+#define MBEDCRYPTO_ECDH_C
+
+/**
+ * \def MBEDCRYPTO_ECDSA_C
+ *
+ * Enable the elliptic curve DSA library.
+ *
+ * Module: library/ecdsa.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ * ECDHE-ECDSA
+ *
+ * Requires: MBEDCRYPTO_ECP_C, MBEDCRYPTO_ASN1_WRITE_C, MBEDCRYPTO_ASN1_PARSE_C
+ */
+#define MBEDCRYPTO_ECDSA_C
+
+/**
+ * \def MBEDCRYPTO_ECJPAKE_C
+ *
+ * Enable the elliptic curve J-PAKE library.
+ *
+ * \warning This is currently experimental. EC J-PAKE support is based on the
+ * Thread v1.0.0 specification; incompatible changes to the specification
+ * might still happen. For this reason, this is disabled by default.
+ *
+ * Module: library/ecjpake.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ * ECJPAKE
+ *
+ * Requires: MBEDCRYPTO_ECP_C, MBEDCRYPTO_MD_C
+ */
+#define MBEDCRYPTO_ECJPAKE_C
+
+/**
+ * \def MBEDCRYPTO_ECP_C
+ *
+ * Enable the elliptic curve over GF(p) library.
+ *
+ * Module: library/ecp.c
+ * Caller: library/ecdh.c
+ * library/ecdsa.c
+ * library/ecjpake.c
+ *
+ * Requires: MBEDCRYPTO_BIGNUM_C and at least one MBEDCRYPTO_ECP_DP_XXX_ENABLED
+ */
+#define MBEDCRYPTO_ECP_C
+
+/**
+ * \def MBEDCRYPTO_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module: library/entropy.c
+ * Caller:
+ *
+ * Requires: MBEDCRYPTO_SHA512_C or MBEDCRYPTO_SHA256_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define MBEDCRYPTO_ENTROPY_C
+
+/**
+ * \def MBEDCRYPTO_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module: library/error.c
+ * Caller:
+ *
+ * This module enables mbedcrypto_strerror().
+ */
+#define MBEDCRYPTO_ERROR_C
+
+/**
+ * \def MBEDCRYPTO_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES.
+ *
+ * Module: library/gcm.c
+ *
+ * Requires: MBEDCRYPTO_AES_C or MBEDCRYPTO_CAMELLIA_C
+ *
+ * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other
+ * requisites are enabled as well.
+ */
+#define MBEDCRYPTO_GCM_C
+
+/**
+ * \def MBEDCRYPTO_HMAC_DRBG_C
+ *
+ * Enable the HMAC_DRBG random generator.
+ *
+ * Module: library/hmac_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDCRYPTO_MD_C
+ *
+ * Uncomment to enable the HMAC_DRBG random number geerator.
+ */
+#define MBEDCRYPTO_HMAC_DRBG_C
+
+/**
+ * \def MBEDCRYPTO_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module: library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define MBEDCRYPTO_MD_C
+
+/**
+ * \def MBEDCRYPTO_MD2_C
+ *
+ * Enable the MD2 hash algorithm.
+ *
+ * Module: library/md2.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+ * \warning MD2 is considered a weak message digest and its use constitutes a
+ * security risk. If possible, we recommend avoiding dependencies on
+ * it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDCRYPTO_MD2_C
+
+/**
+ * \def MBEDCRYPTO_MD4_C
+ *
+ * Enable the MD4 hash algorithm.
+ *
+ * Module: library/md4.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+ * \warning MD4 is considered a weak message digest and its use constitutes a
+ * security risk. If possible, we recommend avoiding dependencies on
+ * it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDCRYPTO_MD4_C
+
+/**
+ * \def MBEDCRYPTO_MD5_C
+ *
+ * Enable the MD5 hash algorithm.
+ *
+ * Module: library/md5.c
+ * Caller: library/md.c
+ * library/pem.c
+ * library/ssl_tls.c
+ *
+ * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2
+ * depending on the handshake parameters. Further, it is used for checking
+ * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded
+ * encrypted keys.
+ *
+ * \warning MD5 is considered a weak message digest and its use constitutes a
+ * security risk. If possible, we recommend avoiding dependencies on
+ * it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDCRYPTO_MD5_C
+
+/**
+ * \def MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C
+ *
+ * Enable the buffer allocator implementation that makes use of a (stack)
+ * based buffer to 'allocate' dynamic memory. (replaces calloc() and free()
+ * calls)
+ *
+ * Module: library/memory_buffer_alloc.c
+ *
+ * Requires: MBEDCRYPTO_PLATFORM_C
+ * MBEDCRYPTO_PLATFORM_MEMORY (to use it within Mbed Crypto)
+ *
+ * Enable this module to enable the buffer memory allocator.
+ */
+//#define MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C
+
+/**
+ * \def MBEDCRYPTO_OID_C
+ *
+ * Enable the OID database.
+ *
+ * Module: library/oid.c
+ * Caller: library/asn1write.c
+ * library/pkcs5.c
+ * library/pkparse.c
+ * library/pkwrite.c
+ * library/rsa.c
+ * library/x509.c
+ * library/x509_create.c
+ * library/x509_crl.c
+ * library/x509_crt.c
+ * library/x509_csr.c
+ * library/x509write_crt.c
+ * library/x509write_csr.c
+ *
+ * This modules translates between OIDs and internal values.
+ */
+#define MBEDCRYPTO_OID_C
+
+/**
+ * \def MBEDCRYPTO_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module: library/padlock.c
+ * Caller: library/aes.c
+ *
+ * Requires: MBEDCRYPTO_HAVE_ASM
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+//#define MBEDCRYPTO_PADLOCK_C
+
+/**
+ * \def MBEDCRYPTO_PEM_PARSE_C
+ *
+ * Enable PEM decoding / parsing.
+ *
+ * Module: library/pem.c
+ * Caller: library/dhm.c
+ * library/pkparse.c
+ * library/x509_crl.c
+ * library/x509_crt.c
+ * library/x509_csr.c
+ *
+ * Requires: MBEDCRYPTO_BASE64_C
+ *
+ * This modules adds support for decoding / parsing PEM files.
+ */
+#define MBEDCRYPTO_PEM_PARSE_C
+
+/**
+ * \def MBEDCRYPTO_PEM_WRITE_C
+ *
+ * Enable PEM encoding / writing.
+ *
+ * Module: library/pem.c
+ * Caller: library/pkwrite.c
+ * library/x509write_crt.c
+ * library/x509write_csr.c
+ *
+ * Requires: MBEDCRYPTO_BASE64_C
+ *
+ * This modules adds support for encoding / writing PEM files.
+ */
+#define MBEDCRYPTO_PEM_WRITE_C
+
+/**
+ * \def MBEDCRYPTO_PK_C
+ *
+ * Enable the generic public (asymetric) key layer.
+ *
+ * Module: library/pk.c
+ * Caller: library/ssl_tls.c
+ * library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * Requires: MBEDCRYPTO_RSA_C or MBEDCRYPTO_ECP_C
+ *
+ * Uncomment to enable generic public key wrappers.
+ */
+#define MBEDCRYPTO_PK_C
+
+/**
+ * \def MBEDCRYPTO_PK_PARSE_C
+ *
+ * Enable the generic public (asymetric) key parser.
+ *
+ * Module: library/pkparse.c
+ * Caller: library/x509_crt.c
+ * library/x509_csr.c
+ *
+ * Requires: MBEDCRYPTO_PK_C
+ *
+ * Uncomment to enable generic public key parse functions.
+ */
+#define MBEDCRYPTO_PK_PARSE_C
+
+/**
+ * \def MBEDCRYPTO_PK_WRITE_C
+ *
+ * Enable the generic public (asymetric) key writer.
+ *
+ * Module: library/pkwrite.c
+ * Caller: library/x509write.c
+ *
+ * Requires: MBEDCRYPTO_PK_C
+ *
+ * Uncomment to enable generic public key write functions.
+ */
+#define MBEDCRYPTO_PK_WRITE_C
+
+/**
+ * \def MBEDCRYPTO_PKCS5_C
+ *
+ * Enable PKCS#5 functions.
+ *
+ * Module: library/pkcs5.c
+ *
+ * Requires: MBEDCRYPTO_MD_C
+ *
+ * This module adds support for the PKCS#5 functions.
+ */
+#define MBEDCRYPTO_PKCS5_C
+
+/**
+ * \def MBEDCRYPTO_PKCS11_C
+ *
+ * Enable wrapper for PKCS#11 smartcard support.
+ *
+ * Module: library/pkcs11.c
+ * Caller: library/pk.c
+ *
+ * Requires: MBEDCRYPTO_PK_C
+ *
+ * This module enables SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+ */
+//#define MBEDCRYPTO_PKCS11_C
+
+/**
+ * \def MBEDCRYPTO_PKCS12_C
+ *
+ * Enable PKCS#12 PBE functions.
+ * Adds algorithms for parsing PKCS#8 encrypted private keys
+ *
+ * Module: library/pkcs12.c
+ * Caller: library/pkparse.c
+ *
+ * Requires: MBEDCRYPTO_ASN1_PARSE_C, MBEDCRYPTO_CIPHER_C, MBEDCRYPTO_MD_C
+ * Can use: MBEDCRYPTO_ARC4_C
+ *
+ * This module enables PKCS#12 functions.
+ */
+#define MBEDCRYPTO_PKCS12_C
+
+/**
+ * \def MBEDCRYPTO_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit().
+ *
+ * Enabling MBEDCRYPTO_PLATFORM_C enables to use of MBEDCRYPTO_PLATFORM_XXX_ALT
+ * or MBEDCRYPTO_PLATFORM_XXX_MACRO directives, allowing the functions mentioned
+ * above to be specified at runtime or compile time respectively.
+ *
+ * \note This abstraction layer must be enabled on Windows (including MSYS2)
+ * as other module rely on it for a fixed snprintf implementation.
+ *
+ * Module: library/platform.c
+ * Caller: Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+#define MBEDCRYPTO_PLATFORM_C
+
+/**
+ * \def MBEDCRYPTO_PSA_CRYPTO_C
+ *
+ * Enable the Platform Security Architecture cryptography API.
+ *
+ * Module: library/psa_crypto.c
+ *
+ * Requires: MBEDCRYPTO_CTR_DRBG_C, MBEDCRYPTO_ENTROPY_C
+ *
+ */
+#define MBEDCRYPTO_PSA_CRYPTO_C
+
+/**
+ * \def MBEDCRYPTO_RIPEMD160_C
+ *
+ * Enable the RIPEMD-160 hash algorithm.
+ *
+ * Module: library/ripemd160.c
+ * Caller: library/md.c
+ *
+ */
+#define MBEDCRYPTO_RIPEMD160_C
+
+/**
+ * \def MBEDCRYPTO_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module: library/rsa.c
+ * library/rsa_internal.c
+ * Caller: library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ * library/x509.c
+ *
+ * This module is used by the following key exchanges:
+ * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK
+ *
+ * Requires: MBEDCRYPTO_BIGNUM_C, MBEDCRYPTO_OID_C
+ */
+#define MBEDCRYPTO_RSA_C
+
+/**
+ * \def MBEDCRYPTO_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module: library/sha1.c
+ * Caller: library/md.c
+ * library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ * library/x509write_crt.c
+ *
+ * This module is required for SSL/TLS up to version 1.1, for TLS 1.2
+ * depending on the handshake parameters, and for SHA1-signed certificates.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use constitutes
+ * a security risk. If possible, we recommend avoiding dependencies
+ * on it, and considering stronger message digests instead.
+ *
+ */
+#define MBEDCRYPTO_SHA1_C
+
+/**
+ * \def MBEDCRYPTO_SHA256_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module: library/sha256.c
+ * Caller: library/entropy.c
+ * library/md.c
+ * library/ssl_cli.c
+ * library/ssl_srv.c
+ * library/ssl_tls.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ * This module is required for the SSL/TLS 1.2 PRF function.
+ */
+#define MBEDCRYPTO_SHA256_C
+
+/**
+ * \def MBEDCRYPTO_SHA512_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module: library/sha512.c
+ * Caller: library/entropy.c
+ * library/md.c
+ * library/ssl_cli.c
+ * library/ssl_srv.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define MBEDCRYPTO_SHA512_C
+
+/**
+ * \def MBEDCRYPTO_THREADING_C
+ *
+ * Enable the threading abstraction layer.
+ * By default Mbed Crypto assumes it is used in a non-threaded environment or that
+ * contexts are not shared between threads. If you do intend to use contexts
+ * between threads, you will need to enable this layer to prevent race
+ * conditions. See also our Knowledge Base article about threading:
+ * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading
+ *
+ * Module: library/threading.c
+ *
+ * This allows different threading implementations (self-implemented or
+ * provided).
+ *
+ * You will have to enable either MBEDCRYPTO_THREADING_ALT or
+ * MBEDCRYPTO_THREADING_PTHREAD.
+ *
+ * Enable this layer to allow use of mutexes within Mbed Crypto
+ */
+//#define MBEDCRYPTO_THREADING_C
+
+/**
+ * \def MBEDCRYPTO_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module: library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define MBEDCRYPTO_VERSION_C
+
+/**
+ * \def MBEDCRYPTO_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module: library/xtea.c
+ * Caller:
+ */
+#define MBEDCRYPTO_XTEA_C
+
+/* \} name SECTION: Mbed Crypto modules */
+
+/**
+ * \name SECTION: Module configuration options
+ *
+ * This section allows for the setting of module specific sizes and
+ * configuration options. The default values are already present in the
+ * relevant header files and should suffice for the regular use cases.
+ *
+ * Our advice is to enable options and change their values here
+ * only if you have a good reason and know the consequences.
+ *
+ * Please check the respective header file for documentation on these
+ * parameters (to prevent duplicate documentation).
+ * \{
+ */
+
+/* MPI / BIGNUM options */
+//#define MBEDCRYPTO_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
+//#define MBEDCRYPTO_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */
+
+/* CTR_DRBG options */
+//#define MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+//#define MBEDCRYPTO_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+//#define MBEDCRYPTO_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+//#define MBEDCRYPTO_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+//#define MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+
+/* HMAC_DRBG options */
+//#define MBEDCRYPTO_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+//#define MBEDCRYPTO_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+//#define MBEDCRYPTO_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+//#define MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+
+/* ECP options */
+//#define MBEDCRYPTO_ECP_MAX_BITS 521 /**< Maximum bit size of groups */
+//#define MBEDCRYPTO_ECP_WINDOW_SIZE 6 /**< Maximum window size used */
+//#define MBEDCRYPTO_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */
+
+/* Entropy options */
+//#define MBEDCRYPTO_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */
+//#define MBEDCRYPTO_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
+//#define MBEDCRYPTO_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedcrypto_hardware_poll() before entropy is released */
+
+/* Memory buffer allocator options */
+//#define MBEDCRYPTO_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */
+
+/* Platform options */
+//#define MBEDCRYPTO_PLATFORM_STD_MEM_HDR <stdlib.h> /**< Header to include if MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
+//#define MBEDCRYPTO_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDCRYPTO_HAVE_TIME must be enabled */
+//#define MBEDCRYPTO_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */
+/* Note: your snprintf must correclty zero-terminate the buffer! */
+//#define MBEDCRYPTO_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ mbedcrypto_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE mbedcrypto_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */
+
+/* To Use Function Macros MBEDCRYPTO_PLATFORM_C must be enabled */
+/* MBEDCRYPTO_PLATFORM_XXX_MACRO and MBEDCRYPTO_PLATFORM_XXX_ALT cannot both be defined */
+//#define MBEDCRYPTO_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDCRYPTO_HAVE_TIME must be enabled */
+//#define MBEDCRYPTO_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDCRYPTO_HAVE_TIME must be enabled */
+//#define MBEDCRYPTO_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */
+/* Note: your snprintf must correclty zero-terminate the buffer! */
+//#define MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_NV_SEED_READ_MACRO mbedcrypto_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDCRYPTO_PLATFORM_NV_SEED_WRITE_MACRO mbedcrypto_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+
+/**
+ * Uncomment the macro to let Mbed Crypto use your alternate implementation of
+ * mbedcrypto_platform_zeroize(). This replaces the default implementation in
+ * platform_util.c.
+ *
+ * mbedcrypto_platform_zeroize() is a widely used function across the library to
+ * zero a block of memory. The implementation is expected to be secure in the
+ * sense that it has been written to prevent the compiler from removing calls
+ * to mbedcrypto_platform_zeroize() as part of redundant code elimination
+ * optimizations. However, it is difficult to guarantee that calls to
+ * mbedcrypto_platform_zeroize() will not be optimized by the compiler as older
+ * versions of the C language standards do not provide a secure implementation
+ * of memset(). Therefore, MBEDCRYPTO_PLATFORM_ZEROIZE_ALT enables users to
+ * configure their own implementation of mbedcrypto_platform_zeroize(), for
+ * example by using directives specific to their compiler, features from newer
+ * C standards (e.g using memset_s() in C11) or calling a secure memset() from
+ * their system (e.g explicit_bzero() in BSD).
+ */
+//#define MBEDCRYPTO_PLATFORM_ZEROIZE_ALT
+
+/* \} name SECTION: Customisation configuration options */
+
+#include "mbedcrypto/check_config.h"
+
+#endif /* MBEDCRYPTO_CONFIG_H */
diff --git a/include/mbedcrypto/ctr_drbg.h b/include/mbedcrypto/ctr_drbg.h
new file mode 100644
index 0000000..eca2d9d
--- /dev/null
+++ b/include/mbedcrypto/ctr_drbg.h
@@ -0,0 +1,330 @@
+/**
+ * \file ctr_drbg.h
+ *
+ * \brief This file contains CTR_DRBG definitions and functions.
+ *
+ * CTR_DRBG is a standardized way of building a PRNG from a block-cipher
+ * in counter mode operation, as defined in <em>NIST SP 800-90A:
+ * Recommendation for Random Number Generation Using Deterministic Random
+ * Bit Generators</em>.
+ *
+ * The Mbed Crypto implementation of CTR_DRBG uses AES-256 as the underlying
+ * block cipher.
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_CTR_DRBG_H
+#define MBEDCRYPTO_CTR_DRBG_H
+
+#include "aes.h"
+
+#if defined(MBEDCRYPTO_THREADING_C)
+#include "mbedcrypto/threading.h"
+#endif
+
+#define MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */
+#define MBEDCRYPTO_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< The requested random buffer length is too big. */
+#define MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< The input (entropy + additional data) is too large. */
+#define MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */
+
+#define MBEDCRYPTO_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */
+#define MBEDCRYPTO_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher. */
+#define MBEDCRYPTO_CTR_DRBG_KEYBITS ( MBEDCRYPTO_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */
+#define MBEDCRYPTO_CTR_DRBG_SEEDLEN ( MBEDCRYPTO_CTR_DRBG_KEYSIZE + MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them using the compiler command
+ * line.
+ * \{
+ */
+
+#if !defined(MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN)
+#if defined(MBEDCRYPTO_SHA512_C) && !defined(MBEDCRYPTO_ENTROPY_FORCE_SHA256)
+#define MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN 48
+/**< The amount of entropy used per seed by default:
+ * <ul><li>48 with SHA-512.</li>
+ * <li>32 with SHA-256.</li></ul>
+ */
+#else
+#define MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN 32
+/**< Amount of entropy used per seed by default:
+ * <ul><li>48 with SHA-512.</li>
+ * <li>32 with SHA-256.</li></ul>
+ */
+#endif
+#endif
+
+#if !defined(MBEDCRYPTO_CTR_DRBG_RESEED_INTERVAL)
+#define MBEDCRYPTO_CTR_DRBG_RESEED_INTERVAL 10000
+/**< The interval before reseed is performed by default. */
+#endif
+
+#if !defined(MBEDCRYPTO_CTR_DRBG_MAX_INPUT)
+#define MBEDCRYPTO_CTR_DRBG_MAX_INPUT 256
+/**< The maximum number of additional input Bytes. */
+#endif
+
+#if !defined(MBEDCRYPTO_CTR_DRBG_MAX_REQUEST)
+#define MBEDCRYPTO_CTR_DRBG_MAX_REQUEST 1024
+/**< The maximum number of requested Bytes per call. */
+#endif
+
+#if !defined(MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT)
+#define MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT 384
+/**< The maximum size of seed or reseed buffer. */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#define MBEDCRYPTO_CTR_DRBG_PR_OFF 0
+/**< Prediction resistance is disabled. */
+#define MBEDCRYPTO_CTR_DRBG_PR_ON 1
+/**< Prediction resistance is enabled. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The CTR_DRBG context structure.
+ */
+typedef struct
+{
+ unsigned char counter[16]; /*!< The counter (V). */
+ int reseed_counter; /*!< The reseed counter. */
+ int prediction_resistance; /*!< This determines whether prediction
+ resistance is enabled, that is
+ whether to systematically reseed before
+ each random generation. */
+ size_t entropy_len; /*!< The amount of entropy grabbed on each
+ seed or reseed operation. */
+ int reseed_interval; /*!< The reseed interval. */
+
+ mbedcrypto_aes_context aes_ctx; /*!< The AES context. */
+
+ /*
+ * Callbacks (Entropy)
+ */
+ int (*f_entropy)(void *, unsigned char *, size_t);
+ /*!< The entropy callback function. */
+
+ void *p_entropy; /*!< The context for the entropy function. */
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_threading_mutex_t mutex;
+#endif
+}
+mbedcrypto_ctr_drbg_context;
+
+/**
+ * \brief This function initializes the CTR_DRBG context,
+ * and prepares it for mbedcrypto_ctr_drbg_seed()
+ * or mbedcrypto_ctr_drbg_free().
+ *
+ * \param ctx The CTR_DRBG context to initialize.
+ */
+void mbedcrypto_ctr_drbg_init( mbedcrypto_ctr_drbg_context *ctx );
+
+/**
+ * \brief This function seeds and sets up the CTR_DRBG
+ * entropy source for future reseeds.
+ *
+ * \note Personalization data can be provided in addition to the more generic
+ * entropy source, to make this instantiation as unique as possible.
+ *
+ * \param ctx The CTR_DRBG context to seed.
+ * \param f_entropy The entropy callback, taking as arguments the
+ * \p p_entropy context, the buffer to fill, and the
+ length of the buffer.
+ * \param p_entropy The entropy context.
+ * \param custom Personalization data, that is device-specific
+ identifiers. Can be NULL.
+ * \param len The length of the personalization data.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
+ */
+int mbedcrypto_ctr_drbg_seed( mbedcrypto_ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len );
+
+/**
+ * \brief This function clears CTR_CRBG context data.
+ *
+ * \param ctx The CTR_DRBG context to clear.
+ */
+void mbedcrypto_ctr_drbg_free( mbedcrypto_ctr_drbg_context *ctx );
+
+/**
+ * \brief This function turns prediction resistance on or off.
+ * The default value is off.
+ *
+ * \note If enabled, entropy is gathered at the beginning of
+ * every call to mbedcrypto_ctr_drbg_random_with_add().
+ * Only use this if your entropy source has sufficient
+ * throughput.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param resistance #MBEDCRYPTO_CTR_DRBG_PR_ON or #MBEDCRYPTO_CTR_DRBG_PR_OFF.
+ */
+void mbedcrypto_ctr_drbg_set_prediction_resistance( mbedcrypto_ctr_drbg_context *ctx,
+ int resistance );
+
+/**
+ * \brief This function sets the amount of entropy grabbed on each
+ * seed or reseed. The default value is
+ * #MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param len The amount of entropy to grab.
+ */
+void mbedcrypto_ctr_drbg_set_entropy_len( mbedcrypto_ctr_drbg_context *ctx,
+ size_t len );
+
+/**
+ * \brief This function sets the reseed interval.
+ * The default value is #MBEDCRYPTO_CTR_DRBG_RESEED_INTERVAL.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param interval The reseed interval.
+ */
+void mbedcrypto_ctr_drbg_set_reseed_interval( mbedcrypto_ctr_drbg_context *ctx,
+ int interval );
+
+/**
+ * \brief This function reseeds the CTR_DRBG context, that is
+ * extracts data from the entropy source.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param additional Additional data to add to the state. Can be NULL.
+ * \param len The length of the additional data.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
+ */
+int mbedcrypto_ctr_drbg_reseed( mbedcrypto_ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t len );
+
+/**
+ * \brief This function updates the state of the CTR_DRBG context.
+ *
+ * \note If \p add_len is greater than
+ * #MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT, only the first
+ * #MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
+ * The remaining Bytes are silently discarded.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param additional The data to update the state with.
+ * \param add_len Length of \p additional data.
+ *
+ */
+void mbedcrypto_ctr_drbg_update( mbedcrypto_ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief This function updates a CTR_DRBG instance with additional
+ * data and uses it to generate random data.
+ *
+ * \note The function automatically reseeds if the reseed counter is exceeded.
+ *
+ * \param p_rng The CTR_DRBG context. This must be a pointer to a
+ * #mbedcrypto_ctr_drbg_context structure.
+ * \param output The buffer to fill.
+ * \param output_len The length of the buffer.
+ * \param additional Additional data to update. Can be NULL.
+ * \param add_len The length of the additional data.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
+ * #MBEDCRYPTO_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure.
+ */
+int mbedcrypto_ctr_drbg_random_with_add( void *p_rng,
+ unsigned char *output, size_t output_len,
+ const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief This function uses CTR_DRBG to generate random data.
+ *
+ * \note The function automatically reseeds if the reseed counter is exceeded.
+ *
+ * \param p_rng The CTR_DRBG context. This must be a pointer to a
+ * #mbedcrypto_ctr_drbg_context structure.
+ * \param output The buffer to fill.
+ * \param output_len The length of the buffer.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
+ * #MBEDCRYPTO_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure.
+ */
+int mbedcrypto_ctr_drbg_random( void *p_rng,
+ unsigned char *output, size_t output_len );
+
+#if defined(MBEDCRYPTO_FS_IO)
+/**
+ * \brief This function writes a seed file.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param path The name of the file.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
+ * \return #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on
+ * failure.
+ */
+int mbedcrypto_ctr_drbg_write_seed_file( mbedcrypto_ctr_drbg_context *ctx, const char *path );
+
+/**
+ * \brief This function reads and updates a seed file. The seed
+ * is added to this instance.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param path The name of the file.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
+ * \return #MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
+ * #MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG on failure.
+ */
+int mbedcrypto_ctr_drbg_update_seed_file( mbedcrypto_ctr_drbg_context *ctx, const char *path );
+#endif /* MBEDCRYPTO_FS_IO */
+
+/**
+ * \brief The CTR_DRBG checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedcrypto_ctr_drbg_self_test( int verbose );
+
+/* Internal functions (do not call directly) */
+int mbedcrypto_ctr_drbg_seed_entropy_len( mbedcrypto_ctr_drbg_context *,
+ int (*)(void *, unsigned char *, size_t), void *,
+ const unsigned char *, size_t, size_t );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ctr_drbg.h */
diff --git a/include/mbedcrypto/des.h b/include/mbedcrypto/des.h
new file mode 100644
index 0000000..1eeb760
--- /dev/null
+++ b/include/mbedcrypto/des.h
@@ -0,0 +1,350 @@
+/**
+ * \file des.h
+ *
+ * \brief DES block cipher
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+#ifndef MBEDCRYPTO_DES_H
+#define MBEDCRYPTO_DES_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_DES_ENCRYPT 1
+#define MBEDCRYPTO_DES_DECRYPT 0
+
+#define MBEDCRYPTO_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */
+#define MBEDCRYPTO_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */
+
+#define MBEDCRYPTO_DES_KEY_SIZE 8
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_DES_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief DES context structure
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+typedef struct
+{
+ uint32_t sk[32]; /*!< DES subkeys */
+}
+mbedcrypto_des_context;
+
+/**
+ * \brief Triple-DES context structure
+ */
+typedef struct
+{
+ uint32_t sk[96]; /*!< 3DES subkeys */
+}
+mbedcrypto_des3_context;
+
+#else /* MBEDCRYPTO_DES_ALT */
+#include "des_alt.h"
+#endif /* MBEDCRYPTO_DES_ALT */
+
+/**
+ * \brief Initialize DES context
+ *
+ * \param ctx DES context to be initialized
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+void mbedcrypto_des_init( mbedcrypto_des_context *ctx );
+
+/**
+ * \brief Clear DES context
+ *
+ * \param ctx DES context to be cleared
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+void mbedcrypto_des_free( mbedcrypto_des_context *ctx );
+
+/**
+ * \brief Initialize Triple-DES context
+ *
+ * \param ctx DES3 context to be initialized
+ */
+void mbedcrypto_des3_init( mbedcrypto_des3_context *ctx );
+
+/**
+ * \brief Clear Triple-DES context
+ *
+ * \param ctx DES3 context to be cleared
+ */
+void mbedcrypto_des3_free( mbedcrypto_des3_context *ctx );
+
+/**
+ * \brief Set key parity on the given key to odd.
+ *
+ * DES keys are 56 bits long, but each byte is padded with
+ * a parity bit to allow verification.
+ *
+ * \param key 8-byte secret key
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+void mbedcrypto_des_key_set_parity( unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief Check that key parity on the given key is odd.
+ *
+ * DES keys are 56 bits long, but each byte is padded with
+ * a parity bit to allow verification.
+ *
+ * \param key 8-byte secret key
+ *
+ * \return 0 is parity was ok, 1 if parity was not correct.
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+int mbedcrypto_des_key_check_key_parity( const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief Check that key is not a weak or semi-weak DES key
+ *
+ * \param key 8-byte secret key
+ *
+ * \return 0 if no weak key was found, 1 if a weak key was identified.
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+int mbedcrypto_des_key_check_weak( const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief DES key schedule (56-bit, encryption)
+ *
+ * \param ctx DES context to be initialized
+ * \param key 8-byte secret key
+ *
+ * \return 0
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+int mbedcrypto_des_setkey_enc( mbedcrypto_des_context *ctx, const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief DES key schedule (56-bit, decryption)
+ *
+ * \param ctx DES context to be initialized
+ * \param key 8-byte secret key
+ *
+ * \return 0
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+int mbedcrypto_des_setkey_dec( mbedcrypto_des_context *ctx, const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief Triple-DES key schedule (112-bit, encryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 16-byte secret key
+ *
+ * \return 0
+ */
+int mbedcrypto_des3_set2key_enc( mbedcrypto_des3_context *ctx,
+ const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 2] );
+
+/**
+ * \brief Triple-DES key schedule (112-bit, decryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 16-byte secret key
+ *
+ * \return 0
+ */
+int mbedcrypto_des3_set2key_dec( mbedcrypto_des3_context *ctx,
+ const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 2] );
+
+/**
+ * \brief Triple-DES key schedule (168-bit, encryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 24-byte secret key
+ *
+ * \return 0
+ */
+int mbedcrypto_des3_set3key_enc( mbedcrypto_des3_context *ctx,
+ const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 3] );
+
+/**
+ * \brief Triple-DES key schedule (168-bit, decryption)
+ *
+ * \param ctx 3DES context to be initialized
+ * \param key 24-byte secret key
+ *
+ * \return 0
+ */
+int mbedcrypto_des3_set3key_dec( mbedcrypto_des3_context *ctx,
+ const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 3] );
+
+/**
+ * \brief DES-ECB block encryption/decryption
+ *
+ * \param ctx DES context
+ * \param input 64-bit input block
+ * \param output 64-bit output block
+ *
+ * \return 0 if successful
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+int mbedcrypto_des_crypt_ecb( mbedcrypto_des_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief DES-CBC buffer encryption/decryption
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the function same function again on the following
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If on the other hand you need to retain the contents of the
+ * IV, you should either save it manually or use the cipher
+ * module instead.
+ *
+ * \param ctx DES context
+ * \param mode MBEDCRYPTO_DES_ENCRYPT or MBEDCRYPTO_DES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+int mbedcrypto_des_crypt_cbc( mbedcrypto_des_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+/**
+ * \brief 3DES-ECB block encryption/decryption
+ *
+ * \param ctx 3DES context
+ * \param input 64-bit input block
+ * \param output 64-bit output block
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_des3_crypt_ecb( mbedcrypto_des3_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief 3DES-CBC buffer encryption/decryption
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the function same function again on the following
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If on the other hand you need to retain the contents of the
+ * IV, you should either save it manually or use the cipher
+ * module instead.
+ *
+ * \param ctx 3DES context
+ * \param mode MBEDCRYPTO_DES_ENCRYPT or MBEDCRYPTO_DES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_DES_INVALID_INPUT_LENGTH
+ */
+int mbedcrypto_des3_crypt_cbc( mbedcrypto_des3_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+/**
+ * \brief Internal function for key expansion.
+ * (Only exposed to allow overriding it,
+ * see MBEDCRYPTO_DES_SETKEY_ALT)
+ *
+ * \param SK Round keys
+ * \param key Base key
+ *
+ * \warning DES is considered a weak cipher and its use constitutes a
+ * security risk. We recommend considering stronger ciphers
+ * instead.
+ */
+void mbedcrypto_des_setkey( uint32_t SK[32],
+ const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_des_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* des.h */
diff --git a/include/mbedcrypto/ecdsa.h b/include/mbedcrypto/ecdsa.h
new file mode 100644
index 0000000..93084a5
--- /dev/null
+++ b/include/mbedcrypto/ecdsa.h
@@ -0,0 +1,339 @@
+/**
+ * \file ecdsa.h
+ *
+ * \brief This file contains ECDSA definitions and functions.
+ *
+ * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in
+ * <em>Standards for Efficient Cryptography Group (SECG):
+ * SEC1 Elliptic Curve Cryptography</em>.
+ * The use of ECDSA for TLS is defined in <em>RFC-4492: Elliptic Curve
+ * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)</em>.
+ *
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_ECDSA_H
+#define MBEDCRYPTO_ECDSA_H
+
+#include "ecp.h"
+#include "md.h"
+
+/*
+ * RFC-4492 page 20:
+ *
+ * Ecdsa-Sig-Value ::= SEQUENCE {
+ * r INTEGER,
+ * s INTEGER
+ * }
+ *
+ * Size is at most
+ * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s,
+ * twice that + 1 (tag) + 2 (len) for the sequence
+ * (assuming ECP_MAX_BYTES is less than 126 for r and s,
+ * and less than 124 (total len <= 255) for the sequence)
+ */
+#if MBEDCRYPTO_ECP_MAX_BYTES > 124
+#error "MBEDCRYPTO_ECP_MAX_BYTES bigger than expected, please fix MBEDCRYPTO_ECDSA_MAX_LEN"
+#endif
+/** The maximal size of an ECDSA signature in Bytes. */
+#define MBEDCRYPTO_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDCRYPTO_ECP_MAX_BYTES ) )
+
+/**
+ * \brief The ECDSA context structure.
+ */
+typedef mbedcrypto_ecp_keypair mbedcrypto_ecdsa_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief This function computes the ECDSA signature of a
+ * previously-hashed message.
+ *
+ * \note The deterministic version is usually preferred.
+ *
+ * \note If the bitlength of the message hash is larger than the
+ * bitlength of the group order, then the hash is truncated
+ * as defined in <em>Standards for Efficient Cryptography Group
+ * (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ * 4.1.3, step 5.
+ *
+ * \see ecp.h
+ *
+ * \param grp The ECP group.
+ * \param r The first output integer.
+ * \param s The second output integer.
+ * \param d The private signing key.
+ * \param buf The message hash.
+ * \param blen The length of \p buf.
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG context.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX
+ * or \c MBEDCRYPTO_MPI_XXX error code on failure.
+ */
+int mbedcrypto_ecdsa_sign( mbedcrypto_ecp_group *grp, mbedcrypto_mpi *r, mbedcrypto_mpi *s,
+ const mbedcrypto_mpi *d, const unsigned char *buf, size_t blen,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+#if defined(MBEDCRYPTO_ECDSA_DETERMINISTIC)
+/**
+ * \brief This function computes the ECDSA signature of a
+ * previously-hashed message, deterministic version.
+ *
+ * For more information, see <em>RFC-6979: Deterministic
+ * Usage of the Digital Signature Algorithm (DSA) and Elliptic
+ * Curve Digital Signature Algorithm (ECDSA)</em>.
+ *
+ * \note If the bitlength of the message hash is larger than the
+ * bitlength of the group order, then the hash is truncated as
+ * defined in <em>Standards for Efficient Cryptography Group
+ * (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ * 4.1.3, step 5.
+ *
+ * \see ecp.h
+ *
+ * \param grp The ECP group.
+ * \param r The first output integer.
+ * \param s The second output integer.
+ * \param d The private signing key.
+ * \param buf The message hash.
+ * \param blen The length of \p buf.
+ * \param md_alg The MD algorithm used to hash the message.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_MPI_XXX
+ * error code on failure.
+ */
+int mbedcrypto_ecdsa_sign_det( mbedcrypto_ecp_group *grp, mbedcrypto_mpi *r, mbedcrypto_mpi *s,
+ const mbedcrypto_mpi *d, const unsigned char *buf, size_t blen,
+ mbedcrypto_md_type_t md_alg );
+#endif /* MBEDCRYPTO_ECDSA_DETERMINISTIC */
+
+/**
+ * \brief This function verifies the ECDSA signature of a
+ * previously-hashed message.
+ *
+ * \note If the bitlength of the message hash is larger than the
+ * bitlength of the group order, then the hash is truncated as
+ * defined in <em>Standards for Efficient Cryptography Group
+ * (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ * 4.1.4, step 3.
+ *
+ * \see ecp.h
+ *
+ * \param grp The ECP group.
+ * \param buf The message hash.
+ * \param blen The length of \p buf.
+ * \param Q The public key to use for verification.
+ * \param r The first integer of the signature.
+ * \param s The second integer of the signature.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if the signature
+ * is invalid.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_MPI_XXX
+ * error code on failure for any other reason.
+ */
+int mbedcrypto_ecdsa_verify( mbedcrypto_ecp_group *grp,
+ const unsigned char *buf, size_t blen,
+ const mbedcrypto_ecp_point *Q, const mbedcrypto_mpi *r, const mbedcrypto_mpi *s);
+
+/**
+ * \brief This function computes the ECDSA signature and writes it
+ * to a buffer, serialized as defined in <em>RFC-4492:
+ * Elliptic Curve Cryptography (ECC) Cipher Suites for
+ * Transport Layer Security (TLS)</em>.
+ *
+ * \warning It is not thread-safe to use the same context in
+ * multiple threads.
+ *
+ * \note The deterministic version is used if
+ * #MBEDCRYPTO_ECDSA_DETERMINISTIC is defined. For more
+ * information, see <em>RFC-6979: Deterministic Usage
+ * of the Digital Signature Algorithm (DSA) and Elliptic
+ * Curve Digital Signature Algorithm (ECDSA)</em>.
+ *
+ * \note The \p sig buffer must be at least twice as large as the
+ * size of the curve used, plus 9. For example, 73 Bytes if
+ * a 256-bit curve is used. A buffer length of
+ * #MBEDCRYPTO_ECDSA_MAX_LEN is always safe.
+ *
+ * \note If the bitlength of the message hash is larger than the
+ * bitlength of the group order, then the hash is truncated as
+ * defined in <em>Standards for Efficient Cryptography Group
+ * (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ * 4.1.3, step 5.
+ *
+ * \see ecp.h
+ *
+ * \param ctx The ECDSA context.
+ * \param md_alg The message digest that was used to hash the message.
+ * \param hash The message hash.
+ * \param hlen The length of the hash.
+ * \param sig The buffer that holds the signature.
+ * \param slen The length of the signature written.
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG context.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX, \c MBEDCRYPTO_ERR_MPI_XXX or
+ * \c MBEDCRYPTO_ERR_ASN1_XXX error code on failure.
+ */
+int mbedcrypto_ecdsa_write_signature( mbedcrypto_ecdsa_context *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hlen,
+ unsigned char *sig, size_t *slen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+#if defined(MBEDCRYPTO_ECDSA_DETERMINISTIC)
+#if ! defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief This function computes an ECDSA signature and writes
+ * it to a buffer, serialized as defined in <em>RFC-4492:
+ * Elliptic Curve Cryptography (ECC) Cipher Suites for
+ * Transport Layer Security (TLS)</em>.
+ *
+ * The deterministic version is defined in <em>RFC-6979:
+ * Deterministic Usage of the Digital Signature Algorithm (DSA)
+ * and Elliptic Curve Digital Signature Algorithm (ECDSA)</em>.
+ *
+ * \warning It is not thread-safe to use the same context in
+ * multiple threads.
+ *
+ * \note The \p sig buffer must be at least twice as large as the
+ * size of the curve used, plus 9. For example, 73 Bytes if a
+ * 256-bit curve is used. A buffer length of
+ * #MBEDCRYPTO_ECDSA_MAX_LEN is always safe.
+ *
+ * \note If the bitlength of the message hash is larger than the
+ * bitlength of the group order, then the hash is truncated as
+ * defined in <em>Standards for Efficient Cryptography Group
+ * (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ * 4.1.3, step 5.
+ *
+ * \see ecp.h
+ *
+ * \deprecated Superseded by mbedcrypto_ecdsa_write_signature() in
+ * Mbed Crypto version 2.0 and later.
+ *
+ * \param ctx The ECDSA context.
+ * \param hash The message hash.
+ * \param hlen The length of the hash.
+ * \param sig The buffer that holds the signature.
+ * \param slen The length of the signature written.
+ * \param md_alg The MD algorithm used to hash the message.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX, \c MBEDCRYPTO_ERR_MPI_XXX or
+ * \c MBEDCRYPTO_ERR_ASN1_XXX error code on failure.
+ */
+int mbedcrypto_ecdsa_write_signature_det( mbedcrypto_ecdsa_context *ctx,
+ const unsigned char *hash, size_t hlen,
+ unsigned char *sig, size_t *slen,
+ mbedcrypto_md_type_t md_alg ) MBEDCRYPTO_DEPRECATED;
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* MBEDCRYPTO_DEPRECATED_REMOVED */
+#endif /* MBEDCRYPTO_ECDSA_DETERMINISTIC */
+
+/**
+ * \brief This function reads and verifies an ECDSA signature.
+ *
+ * \note If the bitlength of the message hash is larger than the
+ * bitlength of the group order, then the hash is truncated as
+ * defined in <em>Standards for Efficient Cryptography Group
+ * (SECG): SEC1 Elliptic Curve Cryptography</em>, section
+ * 4.1.4, step 3.
+ *
+ * \see ecp.h
+ *
+ * \param ctx The ECDSA context.
+ * \param hash The message hash.
+ * \param hlen The size of the hash.
+ * \param sig The signature to read and verify.
+ * \param slen The size of \p sig.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
+ * \return #MBEDCRYPTO_ERR_ECP_SIG_LEN_MISMATCH if there is a valid
+ * signature in \p sig, but its length is less than \p siglen.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_ERR_MPI_XXX
+ * error code on failure for any other reason.
+ */
+int mbedcrypto_ecdsa_read_signature( mbedcrypto_ecdsa_context *ctx,
+ const unsigned char *hash, size_t hlen,
+ const unsigned char *sig, size_t slen );
+
+/**
+ * \brief This function generates an ECDSA keypair on the given curve.
+ *
+ * \see ecp.h
+ *
+ * \param ctx The ECDSA context to store the keypair in.
+ * \param gid The elliptic curve to use. One of the various
+ * \c MBEDCRYPTO_ECP_DP_XXX macros depending on configuration.
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG context.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX code on failure.
+ */
+int mbedcrypto_ecdsa_genkey( mbedcrypto_ecdsa_context *ctx, mbedcrypto_ecp_group_id gid,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief This function sets an ECDSA context from an EC key pair.
+ *
+ * \see ecp.h
+ *
+ * \param ctx The ECDSA context to set.
+ * \param key The EC key to use.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX code on failure.
+ */
+int mbedcrypto_ecdsa_from_keypair( mbedcrypto_ecdsa_context *ctx, const mbedcrypto_ecp_keypair *key );
+
+/**
+ * \brief This function initializes an ECDSA context.
+ *
+ * \param ctx The ECDSA context to initialize.
+ */
+void mbedcrypto_ecdsa_init( mbedcrypto_ecdsa_context *ctx );
+
+/**
+ * \brief This function frees an ECDSA context.
+ *
+ * \param ctx The ECDSA context to free.
+ */
+void mbedcrypto_ecdsa_free( mbedcrypto_ecdsa_context *ctx );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ecdsa.h */
diff --git a/include/mbedcrypto/ecp.h b/include/mbedcrypto/ecp.h
new file mode 100644
index 0000000..eb6bf6c
--- /dev/null
+++ b/include/mbedcrypto/ecp.h
@@ -0,0 +1,764 @@
+/**
+ * \file ecp.h
+ *
+ * \brief This file provides an API for Elliptic Curves over GF(P) (ECP).
+ *
+ * The use of ECP in cryptography and TLS is defined in
+ * <em>Standards for Efficient Cryptography Group (SECG): SEC1
+ * Elliptic Curve Cryptography</em> and
+ * <em>RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites
+ * for Transport Layer Security (TLS)</em>.
+ *
+ * <em>RFC-2409: The Internet Key Exchange (IKE)</em> defines ECP
+ * group types.
+ *
+ */
+
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_ECP_H
+#define MBEDCRYPTO_ECP_H
+
+#include "bignum.h"
+
+/*
+ * ECP error codes
+ */
+#define MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */
+#define MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< The requested feature is not available, for example, the requested curve is not supported. */
+#define MBEDCRYPTO_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */
+#define MBEDCRYPTO_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */
+#define MBEDCRYPTO_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */
+#define MBEDCRYPTO_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */
+#define MBEDCRYPTO_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */
+#define MBEDCRYPTO_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Domain-parameter identifiers: curve, subgroup, and generator.
+ *
+ * \note Only curves over prime fields are supported.
+ *
+ * \warning This library does not support validation of arbitrary domain
+ * parameters. Therefore, only standardized domain parameters from trusted
+ * sources should be used. See mbedcrypto_ecp_group_load().
+ */
+typedef enum
+{
+ MBEDCRYPTO_ECP_DP_NONE = 0, /*!< Curve not defined. */
+ MBEDCRYPTO_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */
+ MBEDCRYPTO_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */
+ MBEDCRYPTO_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */
+ MBEDCRYPTO_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */
+ MBEDCRYPTO_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */
+ MBEDCRYPTO_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */
+ MBEDCRYPTO_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */
+ MBEDCRYPTO_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */
+ MBEDCRYPTO_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */
+ MBEDCRYPTO_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */
+ MBEDCRYPTO_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */
+ MBEDCRYPTO_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */
+ MBEDCRYPTO_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */
+} mbedcrypto_ecp_group_id;
+
+/**
+ * The number of supported curves, plus one for #MBEDCRYPTO_ECP_DP_NONE.
+ *
+ * \note Montgomery curves are currently excluded.
+ */
+#define MBEDCRYPTO_ECP_DP_MAX 12
+
+/**
+ * Curve information, for use by other modules.
+ */
+typedef struct
+{
+ mbedcrypto_ecp_group_id grp_id; /*!< An internal identifier. */
+ uint16_t tls_id; /*!< The TLS NamedCurve identifier. */
+ uint16_t bit_size; /*!< The curve size in bits. */
+ const char *name; /*!< A human-friendly name. */
+} mbedcrypto_ecp_curve_info;
+
+/**
+ * \brief The ECP point structure, in Jacobian coordinates.
+ *
+ * \note All functions expect and return points satisfying
+ * the following condition: <code>Z == 0</code> or
+ * <code>Z == 1</code>. Other values of \p Z are
+ * used only by internal functions.
+ * The point is zero, or "at infinity", if <code>Z == 0</code>.
+ * Otherwise, \p X and \p Y are its standard (affine)
+ * coordinates.
+ */
+typedef struct
+{
+ mbedcrypto_mpi X; /*!< The X coordinate of the ECP point. */
+ mbedcrypto_mpi Y; /*!< The Y coordinate of the ECP point. */
+ mbedcrypto_mpi Z; /*!< The Z coordinate of the ECP point. */
+}
+mbedcrypto_ecp_point;
+
+#if !defined(MBEDCRYPTO_ECP_ALT)
+/*
+ * default Mbed Crypto elliptic curve arithmetic implementation
+ *
+ * (in case MBEDCRYPTO_ECP_ALT is defined then the developer has to provide an
+ * alternative implementation for the whole module and it will replace this
+ * one.)
+ */
+
+/**
+ * \brief The ECP group structure.
+ *
+ * We consider two types of curve equations:
+ * <ul><li>Short Weierstrass: <code>y^2 = x^3 + A x + B mod P</code>
+ * (SEC1 + RFC-4492)</li>
+ * <li>Montgomery: <code>y^2 = x^3 + A x^2 + x mod P</code> (Curve25519,
+ * Curve448)</li></ul>
+ * In both cases, the generator (\p G) for a prime-order subgroup is fixed.
+ *
+ * For Short Weierstrass, this subgroup is the whole curve, and its
+ * cardinality is denoted by \p N. Our code requires that \p N is an
+ * odd prime as mbedcrypto_ecp_mul() requires an odd number, and
+ * mbedcrypto_ecdsa_sign() requires that it is prime for blinding purposes.
+ *
+ * For Montgomery curves, we do not store \p A, but <code>(A + 2) / 4</code>,
+ * which is the quantity used in the formulas. Additionally, \p nbits is
+ * not the size of \p N but the required size for private keys.
+ *
+ * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm.
+ * Otherwise, \p modp must point to a function that takes an \p mbedcrypto_mpi in the
+ * range of <code>0..2^(2*pbits)-1</code>, and transforms it in-place to an integer
+ * which is congruent mod \p P to the given MPI, and is close enough to \p pbits
+ * in size, so that it may be efficiently brought in the 0..P-1 range by a few
+ * additions or subtractions. Therefore, it is only an approximative modular
+ * reduction. It must return 0 on success and non-zero on failure.
+ *
+ */
+typedef struct
+{
+ mbedcrypto_ecp_group_id id; /*!< An internal group identifier. */
+ mbedcrypto_mpi P; /*!< The prime modulus of the base field. */
+ mbedcrypto_mpi A; /*!< For Short Weierstrass: \p A in the equation. For
+ Montgomery curves: <code>(A + 2) / 4</code>. */
+ mbedcrypto_mpi B; /*!< For Short Weierstrass: \p B in the equation.
+ For Montgomery curves: unused. */
+ mbedcrypto_ecp_point G; /*!< The generator of the subgroup used. */
+ mbedcrypto_mpi N; /*!< The order of \p G. */
+ size_t pbits; /*!< The number of bits in \p P.*/
+ size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P.
+ For Montgomery curves: the number of bits in the
+ private keys. */
+ unsigned int h; /*!< \internal 1 if the constants are static. */
+ int (*modp)(mbedcrypto_mpi *); /*!< The function for fast pseudo-reduction
+ mod \p P (see above).*/
+ int (*t_pre)(mbedcrypto_ecp_point *, void *); /*!< Unused. */
+ int (*t_post)(mbedcrypto_ecp_point *, void *); /*!< Unused. */
+ void *t_data; /*!< Unused. */
+ mbedcrypto_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */
+ size_t T_size; /*!< The number of pre-computed points. */
+}
+mbedcrypto_ecp_group;
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h, or define them using the compiler command line.
+ * \{
+ */
+
+#if !defined(MBEDCRYPTO_ECP_MAX_BITS)
+/**
+ * The maximum size of the groups, that is, of \c N and \c P.
+ */
+#define MBEDCRYPTO_ECP_MAX_BITS 521 /**< The maximum size of groups, in bits. */
+#endif
+
+#define MBEDCRYPTO_ECP_MAX_BYTES ( ( MBEDCRYPTO_ECP_MAX_BITS + 7 ) / 8 )
+#define MBEDCRYPTO_ECP_MAX_PT_LEN ( 2 * MBEDCRYPTO_ECP_MAX_BYTES + 1 )
+
+#if !defined(MBEDCRYPTO_ECP_WINDOW_SIZE)
+/*
+ * Maximum "window" size used for point multiplication.
+ * Default: 6.
+ * Minimum value: 2. Maximum value: 7.
+ *
+ * Result is an array of at most ( 1 << ( MBEDCRYPTO_ECP_WINDOW_SIZE - 1 ) )
+ * points used for point multiplication. This value is directly tied to EC
+ * peak memory usage, so decreasing it by one should roughly cut memory usage
+ * by two (if large curves are in use).
+ *
+ * Reduction in size may reduce speed, but larger curves are impacted first.
+ * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1):
+ * w-size: 6 5 4 3 2
+ * 521 145 141 135 120 97
+ * 384 214 209 198 177 146
+ * 256 320 320 303 262 226
+ * 224 475 475 453 398 342
+ * 192 640 640 633 587 476
+ */
+#define MBEDCRYPTO_ECP_WINDOW_SIZE 6 /**< The maximum window size used. */
+#endif /* MBEDCRYPTO_ECP_WINDOW_SIZE */
+
+#if !defined(MBEDCRYPTO_ECP_FIXED_POINT_OPTIM)
+/*
+ * Trade memory for speed on fixed-point multiplication.
+ *
+ * This speeds up repeated multiplication of the generator (that is, the
+ * multiplication in ECDSA signatures, and half of the multiplications in
+ * ECDSA verification and ECDHE) by a factor roughly 3 to 4.
+ *
+ * The cost is increasing EC peak memory usage by a factor roughly 2.
+ *
+ * Change this value to 0 to reduce peak memory usage.
+ */
+#define MBEDCRYPTO_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */
+#endif /* MBEDCRYPTO_ECP_FIXED_POINT_OPTIM */
+
+/* \} name SECTION: Module settings */
+
+#else /* MBEDCRYPTO_ECP_ALT */
+#include "ecp_alt.h"
+#endif /* MBEDCRYPTO_ECP_ALT */
+
+/**
+ * \brief The ECP key-pair structure.
+ *
+ * A generic key-pair that may be used for ECDSA and fixed ECDH, for example.
+ *
+ * \note Members are deliberately in the same order as in the
+ * ::mbedcrypto_ecdsa_context structure.
+ */
+typedef struct
+{
+ mbedcrypto_ecp_group grp; /*!< Elliptic curve and base point */
+ mbedcrypto_mpi d; /*!< our secret value */
+ mbedcrypto_ecp_point Q; /*!< our public value */
+}
+mbedcrypto_ecp_keypair;
+
+/*
+ * Point formats, from RFC 4492's enum ECPointFormat
+ */
+#define MBEDCRYPTO_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format. */
+#define MBEDCRYPTO_ECP_PF_COMPRESSED 1 /**< Compressed point format. */
+
+/*
+ * Some other constants from RFC 4492
+ */
+#define MBEDCRYPTO_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */
+
+/**
+ * \brief This function retrieves the information defined in
+ * mbedcrypto_ecp_curve_info() for all supported curves in order
+ * of preference.
+ *
+ * \return A statically allocated array. The last entry is 0.
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_list( void );
+
+/**
+ * \brief This function retrieves the list of internal group
+ * identifiers of all supported curves in the order of
+ * preference.
+ *
+ * \return A statically allocated array,
+ * terminated with MBEDCRYPTO_ECP_DP_NONE.
+ */
+const mbedcrypto_ecp_group_id *mbedcrypto_ecp_grp_id_list( void );
+
+/**
+ * \brief This function retrieves curve information from an internal
+ * group identifier.
+ *
+ * \param grp_id An \c MBEDCRYPTO_ECP_DP_XXX value.
+ *
+ * \return The associated curve information on success.
+ * \return NULL on failure.
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_info_from_grp_id( mbedcrypto_ecp_group_id grp_id );
+
+/**
+ * \brief This function retrieves curve information from a TLS
+ * NamedCurve value.
+ *
+ * \param tls_id An \c MBEDCRYPTO_ECP_DP_XXX value.
+ *
+ * \return The associated curve information on success.
+ * \return NULL on failure.
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_info_from_tls_id( uint16_t tls_id );
+
+/**
+ * \brief This function retrieves curve information from a
+ * human-readable name.
+ *
+ * \param name The human-readable name.
+ *
+ * \return The associated curve information on success.
+ * \return NULL on failure.
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_info_from_name( const char *name );
+
+/**
+ * \brief This function initializes a point as zero.
+ *
+ * \param pt The point to initialize.
+ */
+void mbedcrypto_ecp_point_init( mbedcrypto_ecp_point *pt );
+
+/**
+ * \brief This function initializes an ECP group context
+ * without loading any domain parameters.
+ *
+ * \note After this function is called, domain parameters
+ * for various ECP groups can be loaded through the
+ * mbedcrypto_ecp_load() or mbedcrypto_ecp_tls_read_group()
+ * functions.
+ */
+void mbedcrypto_ecp_group_init( mbedcrypto_ecp_group *grp );
+
+/**
+ * \brief This function initializes a key pair as an invalid one.
+ *
+ * \param key The key pair to initialize.
+ */
+void mbedcrypto_ecp_keypair_init( mbedcrypto_ecp_keypair *key );
+
+/**
+ * \brief This function frees the components of a point.
+ *
+ * \param pt The point to free.
+ */
+void mbedcrypto_ecp_point_free( mbedcrypto_ecp_point *pt );
+
+/**
+ * \brief This function frees the components of an ECP group.
+ * \param grp The group to free.
+ */
+void mbedcrypto_ecp_group_free( mbedcrypto_ecp_group *grp );
+
+/**
+ * \brief This function frees the components of a key pair.
+ * \param key The key pair to free.
+ */
+void mbedcrypto_ecp_keypair_free( mbedcrypto_ecp_keypair *key );
+
+/**
+ * \brief This function copies the contents of point \p Q into
+ * point \p P.
+ *
+ * \param P The destination point.
+ * \param Q The source point.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_ecp_copy( mbedcrypto_ecp_point *P, const mbedcrypto_ecp_point *Q );
+
+/**
+ * \brief This function copies the contents of group \p src into
+ * group \p dst.
+ *
+ * \param dst The destination group.
+ * \param src The source group.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_ecp_group_copy( mbedcrypto_ecp_group *dst, const mbedcrypto_ecp_group *src );
+
+/**
+ * \brief This function sets a point to zero.
+ *
+ * \param pt The point to set.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_ecp_set_zero( mbedcrypto_ecp_point *pt );
+
+/**
+ * \brief This function checks if a point is zero.
+ *
+ * \param pt The point to test.
+ *
+ * \return \c 1 if the point is zero.
+ * \return \c 0 if the point is non-zero.
+ */
+int mbedcrypto_ecp_is_zero( mbedcrypto_ecp_point *pt );
+
+/**
+ * \brief This function compares two points.
+ *
+ * \note This assumes that the points are normalized. Otherwise,
+ * they may compare as "not equal" even if they are.
+ *
+ * \param P The first point to compare.
+ * \param Q The second point to compare.
+ *
+ * \return \c 0 if the points are equal.
+ * \return #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if the points are not equal.
+ */
+int mbedcrypto_ecp_point_cmp( const mbedcrypto_ecp_point *P,
+ const mbedcrypto_ecp_point *Q );
+
+/**
+ * \brief This function imports a non-zero point from two ASCII
+ * strings.
+ *
+ * \param P The destination point.
+ * \param radix The numeric base of the input.
+ * \param x The first affine coordinate, as a null-terminated string.
+ * \param y The second affine coordinate, as a null-terminated string.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_MPI_XXX error code on failure.
+ */
+int mbedcrypto_ecp_point_read_string( mbedcrypto_ecp_point *P, int radix,
+ const char *x, const char *y );
+
+/**
+ * \brief This function exports a point into unsigned binary data.
+ *
+ * \param grp The group to which the point should belong.
+ * \param P The point to export.
+ * \param format The point format. Should be an \c MBEDCRYPTO_ECP_PF_XXX macro.
+ * \param olen The length of the output.
+ * \param buf The output buffer.
+ * \param buflen The length of the output buffer.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA
+ * or #MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL on failure.
+ */
+int mbedcrypto_ecp_point_write_binary( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *P,
+ int format, size_t *olen,
+ unsigned char *buf, size_t buflen );
+
+/**
+ * \brief This function imports a point from unsigned binary data.
+ *
+ * \note This function does not check that the point actually
+ * belongs to the given group, see mbedcrypto_ecp_check_pubkey()
+ * for that.
+ *
+ * \param grp The group to which the point should belong.
+ * \param P The point to import.
+ * \param buf The input buffer.
+ * \param ilen The length of the input.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if input is invalid.
+ * \return #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return #MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE if the point format
+ * is not implemented.
+ *
+ */
+int mbedcrypto_ecp_point_read_binary( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *P,
+ const unsigned char *buf, size_t ilen );
+
+/**
+ * \brief This function imports a point from a TLS ECPoint record.
+ *
+ * \note On function return, \p buf is updated to point to immediately
+ * after the ECPoint record.
+ *
+ * \param grp The ECP group used.
+ * \param pt The destination point.
+ * \param buf The address of the pointer to the start of the input buffer.
+ * \param len The length of the buffer.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_MPI_XXX error code on initialization failure.
+ * \return #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if input is invalid.
+ */
+int mbedcrypto_ecp_tls_read_point( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *pt,
+ const unsigned char **buf, size_t len );
+
+/**
+ * \brief This function exports a point as a TLS ECPoint record.
+ *
+ * \param grp The ECP group used.
+ * \param pt The point format to export to. The point format is an
+ * \c MBEDCRYPTO_ECP_PF_XXX constant.
+ * \param format The export format.
+ * \param olen The length of the data written.
+ * \param buf The buffer to write to.
+ * \param blen The length of the buffer.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA or
+ * #MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL on failure.
+ */
+int mbedcrypto_ecp_tls_write_point( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *pt,
+ int format, size_t *olen,
+ unsigned char *buf, size_t blen );
+
+/**
+ * \brief This function sets a group using standardized domain parameters.
+ *
+ * \note The index should be a value of the NamedCurve enum,
+ * as defined in <em>RFC-4492: Elliptic Curve Cryptography
+ * (ECC) Cipher Suites for Transport Layer Security (TLS)</em>,
+ * usually in the form of an \c MBEDCRYPTO_ECP_DP_XXX macro.
+ *
+ * \param grp The destination group.
+ * \param id The identifier of the domain parameter set to load.
+ *
+ * \return \c 0 on success,
+ * \return An \c MBEDCRYPTO_ERR_MPI_XXX error code on initialization failure.
+ * \return #MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups.
+
+ */
+int mbedcrypto_ecp_group_load( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_group_id id );
+
+/**
+ * \brief This function sets a group from a TLS ECParameters record.
+ *
+ * \note \p buf is updated to point right after the ECParameters record
+ * on exit.
+ *
+ * \param grp The destination group.
+ * \param buf The address of the pointer to the start of the input buffer.
+ * \param len The length of the buffer.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_MPI_XXX error code on initialization failure.
+ * \return #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if input is invalid.
+ */
+int mbedcrypto_ecp_tls_read_group( mbedcrypto_ecp_group *grp, const unsigned char **buf, size_t len );
+
+/**
+ * \brief This function writes the TLS ECParameters record for a group.
+ *
+ * \param grp The ECP group used.
+ * \param olen The number of Bytes written.
+ * \param buf The buffer to write to.
+ * \param blen The length of the buffer.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL on failure.
+ */
+int mbedcrypto_ecp_tls_write_group( const mbedcrypto_ecp_group *grp, size_t *olen,
+ unsigned char *buf, size_t blen );
+
+/**
+ * \brief This function performs multiplication of a point by
+ * an integer: \p R = \p m * \p P.
+ *
+ * It is not thread-safe to use same group in multiple threads.
+ *
+ * \note To prevent timing attacks, this function
+ * executes the exact same sequence of base-field
+ * operations for any valid \p m. It avoids any if-branch or
+ * array index depending on the value of \p m.
+ *
+ * \note If \p f_rng is not NULL, it is used to randomize
+ * intermediate results to prevent potential timing attacks
+ * targeting these results. We recommend always providing
+ * a non-NULL \p f_rng. The overhead is negligible.
+ *
+ * \param grp The ECP group.
+ * \param R The destination point.
+ * \param m The integer by which to multiply.
+ * \param P The point to multiply.
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG context.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_ECP_INVALID_KEY if \p m is not a valid private
+ * key, or \p P is not a valid public key.
+ * \return #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_ecp_mul( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+ const mbedcrypto_mpi *m, const mbedcrypto_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief This function performs multiplication and addition of two
+ * points by integers: \p R = \p m * \p P + \p n * \p Q
+ *
+ * It is not thread-safe to use same group in multiple threads.
+ *
+ * \note In contrast to mbedcrypto_ecp_mul(), this function does not
+ * guarantee a constant execution flow and timing.
+ *
+ * \param grp The ECP group.
+ * \param R The destination point.
+ * \param m The integer by which to multiply \p P.
+ * \param P The point to multiply by \p m.
+ * \param n The integer by which to multiply \p Q.
+ * \param Q The point to be multiplied by \p n.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_ECP_INVALID_KEY if \p m or \p n are not
+ * valid private keys, or \p P or \p Q are not valid public
+ * keys.
+ * \return #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_ecp_muladd( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+ const mbedcrypto_mpi *m, const mbedcrypto_ecp_point *P,
+ const mbedcrypto_mpi *n, const mbedcrypto_ecp_point *Q );
+
+/**
+ * \brief This function checks that a point is a valid public key
+ * on this curve.
+ *
+ * It only checks that the point is non-zero, has
+ * valid coordinates and lies on the curve. It does not verify
+ * that it is indeed a multiple of \p G. This additional
+ * check is computationally more expensive, is not required
+ * by standards, and should not be necessary if the group
+ * used has a small cofactor. In particular, it is useless for
+ * the NIST groups which all have a cofactor of 1.
+ *
+ * \note This function uses bare components rather than an
+ * ::mbedcrypto_ecp_keypair structure, to ease use with other
+ * structures, such as ::mbedcrypto_ecdh_context or
+ * ::mbedcrypto_ecdsa_context.
+ *
+ * \param grp The curve the point should lie on.
+ * \param pt The point to check.
+ *
+ * \return \c 0 if the point is a valid public key.
+ * \return #MBEDCRYPTO_ERR_ECP_INVALID_KEY on failure.
+ */
+int mbedcrypto_ecp_check_pubkey( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *pt );
+
+/**
+ * \brief This function checks that an \p mbedcrypto_mpi is a valid private
+ * key for this curve.
+ *
+ * \note This function uses bare components rather than an
+ * ::mbedcrypto_ecp_keypair structure to ease use with other
+ * structures, such as ::mbedcrypto_ecdh_context or
+ * ::mbedcrypto_ecdsa_context.
+ *
+ * \param grp The group used.
+ * \param d The integer to check.
+ *
+ * \return \c 0 if the point is a valid private key.
+ * \return #MBEDCRYPTO_ERR_ECP_INVALID_KEY on failure.
+ */
+int mbedcrypto_ecp_check_privkey( const mbedcrypto_ecp_group *grp, const mbedcrypto_mpi *d );
+
+/**
+ * \brief This function generates a keypair with a configurable base
+ * point.
+ *
+ * \note This function uses bare components rather than an
+ * ::mbedcrypto_ecp_keypair structure to ease use with other
+ * structures, such as ::mbedcrypto_ecdh_context or
+ * ::mbedcrypto_ecdsa_context.
+ *
+ * \param grp The ECP group.
+ * \param G The chosen base point.
+ * \param d The destination MPI (secret part).
+ * \param Q The destination point (public part).
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG context.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_MPI_XXX error code
+ * on failure.
+ */
+int mbedcrypto_ecp_gen_keypair_base( mbedcrypto_ecp_group *grp,
+ const mbedcrypto_ecp_point *G,
+ mbedcrypto_mpi *d, mbedcrypto_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief This function generates an ECP keypair.
+ *
+ * \note This function uses bare components rather than an
+ * ::mbedcrypto_ecp_keypair structure to ease use with other
+ * structures, such as ::mbedcrypto_ecdh_context or
+ * ::mbedcrypto_ecdsa_context.
+ *
+ * \param grp The ECP group.
+ * \param d The destination MPI (secret part).
+ * \param Q The destination point (public part).
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG context.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_MPI_XXX error code
+ * on failure.
+ */
+int mbedcrypto_ecp_gen_keypair( mbedcrypto_ecp_group *grp, mbedcrypto_mpi *d, mbedcrypto_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief This function generates an ECP key.
+ *
+ * \param grp_id The ECP group identifier.
+ * \param key The destination key.
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG context.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX or \c MBEDCRYPTO_MPI_XXX error code
+ * on failure.
+ */
+int mbedcrypto_ecp_gen_key( mbedcrypto_ecp_group_id grp_id, mbedcrypto_ecp_keypair *key,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief This function checks that the keypair objects
+ * \p pub and \p prv have the same group and the
+ * same public point, and that the private key in
+ * \p prv is consistent with the public key.
+ *
+ * \param pub The keypair structure holding the public key.
+ * If it contains a private key, that part is ignored.
+ * \param prv The keypair structure holding the full keypair.
+ *
+ * \return \c 0 on success, meaning that the keys are valid and match.
+ * \return #MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match.
+ * \return An \c MBEDCRYPTO_ERR_ECP_XXX or an \c MBEDCRYPTO_ERR_MPI_XXX
+ * error code on calculation failure.
+ */
+int mbedcrypto_ecp_check_pub_priv( const mbedcrypto_ecp_keypair *pub, const mbedcrypto_ecp_keypair *prv );
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+/**
+ * \brief The ECP checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedcrypto_ecp_self_test( int verbose );
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ecp.h */
diff --git a/include/mbedcrypto/ecp_internal.h b/include/mbedcrypto/ecp_internal.h
new file mode 100644
index 0000000..98a6bb7
--- /dev/null
+++ b/include/mbedcrypto/ecp_internal.h
@@ -0,0 +1,293 @@
+/**
+ * \file ecp_internal.h
+ *
+ * \brief Function declarations for alternative implementation of elliptic curve
+ * point arithmetic.
+ */
+/*
+ * Copyright (C) 2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * References:
+ *
+ * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records.
+ * <http://cr.yp.to/ecdh/curve25519-20060209.pdf>
+ *
+ * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
+ * for elliptic curve cryptosystems. In : Cryptographic Hardware and
+ * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
+ * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
+ *
+ * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
+ * render ECC resistant against Side Channel Attacks. IACR Cryptology
+ * ePrint Archive, 2004, vol. 2004, p. 342.
+ * <http://eprint.iacr.org/2004/342.pdf>
+ *
+ * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters.
+ * <http://www.secg.org/sec2-v2.pdf>
+ *
+ * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic
+ * Curve Cryptography.
+ *
+ * [6] Digital Signature Standard (DSS), FIPS 186-4.
+ * <http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf>
+ *
+ * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer
+ * Security (TLS), RFC 4492.
+ * <https://tools.ietf.org/search/rfc4492>
+ *
+ * [8] <http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html>
+ *
+ * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory.
+ * Springer Science & Business Media, 1 Aug 2000
+ */
+
+#ifndef MBEDCRYPTO_ECP_INTERNAL_H
+#define MBEDCRYPTO_ECP_INTERNAL_H
+
+#if defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+
+/**
+ * \brief Indicate if the Elliptic Curve Point module extension can
+ * handle the group.
+ *
+ * \param grp The pointer to the elliptic curve group that will be the
+ * basis of the cryptographic computations.
+ *
+ * \return Non-zero if successful.
+ */
+unsigned char mbedcrypto_internal_ecp_grp_capable( const mbedcrypto_ecp_group *grp );
+
+/**
+ * \brief Initialise the Elliptic Curve Point module extension.
+ *
+ * If mbedcrypto_internal_ecp_grp_capable returns true for a
+ * group, this function has to be able to initialise the
+ * module for it.
+ *
+ * This module can be a driver to a crypto hardware
+ * accelerator, for which this could be an initialise function.
+ *
+ * \param grp The pointer to the group the module needs to be
+ * initialised for.
+ *
+ * \return 0 if successful.
+ */
+int mbedcrypto_internal_ecp_init( const mbedcrypto_ecp_group *grp );
+
+/**
+ * \brief Frees and deallocates the Elliptic Curve Point module
+ * extension.
+ *
+ * \param grp The pointer to the group the module was initialised for.
+ */
+void mbedcrypto_internal_ecp_free( const mbedcrypto_ecp_group *grp );
+
+#if defined(ECP_SHORTWEIERSTRASS)
+
+#if defined(MBEDCRYPTO_ECP_RANDOMIZE_JAC_ALT)
+/**
+ * \brief Randomize jacobian coordinates:
+ * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l.
+ *
+ * \param grp Pointer to the group representing the curve.
+ *
+ * \param pt The point on the curve to be randomised, given with Jacobian
+ * coordinates.
+ *
+ * \param f_rng A function pointer to the random number generator.
+ *
+ * \param p_rng A pointer to the random number generator state.
+ *
+ * \return 0 if successful.
+ */
+int mbedcrypto_internal_ecp_randomize_jac( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+#endif
+
+#if defined(MBEDCRYPTO_ECP_ADD_MIXED_ALT)
+/**
+ * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates.
+ *
+ * The coordinates of Q must be normalized (= affine),
+ * but those of P don't need to. R is not normalized.
+ *
+ * This function is used only as a subrutine of
+ * ecp_mul_comb().
+ *
+ * Special cases: (1) P or Q is zero, (2) R is zero,
+ * (3) P == Q.
+ * None of these cases can happen as intermediate step in
+ * ecp_mul_comb():
+ * - at each step, P, Q and R are multiples of the base
+ * point, the factor being less than its order, so none of
+ * them is zero;
+ * - Q is an odd multiple of the base point, P an even
+ * multiple, due to the choice of precomputed points in the
+ * modified comb method.
+ * So branches for these cases do not leak secret information.
+ *
+ * We accept Q->Z being unset (saving memory in tables) as
+ * meaning 1.
+ *
+ * Cost in field operations if done by [5] 3.22:
+ * 1A := 8M + 3S
+ *
+ * \param grp Pointer to the group representing the curve.
+ *
+ * \param R Pointer to a point structure to hold the result.
+ *
+ * \param P Pointer to the first summand, given with Jacobian
+ * coordinates
+ *
+ * \param Q Pointer to the second summand, given with affine
+ * coordinates.
+ *
+ * \return 0 if successful.
+ */
+int mbedcrypto_internal_ecp_add_mixed( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *R, const mbedcrypto_ecp_point *P,
+ const mbedcrypto_ecp_point *Q );
+#endif
+
+/**
+ * \brief Point doubling R = 2 P, Jacobian coordinates.
+ *
+ * Cost: 1D := 3M + 4S (A == 0)
+ * 4M + 4S (A == -3)
+ * 3M + 6S + 1a otherwise
+ * when the implementation is based on the "dbl-1998-cmo-2"
+ * doubling formulas in [8] and standard optimizations are
+ * applied when curve parameter A is one of { 0, -3 }.
+ *
+ * \param grp Pointer to the group representing the curve.
+ *
+ * \param R Pointer to a point structure to hold the result.
+ *
+ * \param P Pointer to the point that has to be doubled, given with
+ * Jacobian coordinates.
+ *
+ * \return 0 if successful.
+ */
+#if defined(MBEDCRYPTO_ECP_DOUBLE_JAC_ALT)
+int mbedcrypto_internal_ecp_double_jac( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *R, const mbedcrypto_ecp_point *P );
+#endif
+
+/**
+ * \brief Normalize jacobian coordinates of an array of (pointers to)
+ * points.
+ *
+ * Using Montgomery's trick to perform only one inversion mod P
+ * the cost is:
+ * 1N(t) := 1I + (6t - 3)M + 1S
+ * (See for example Algorithm 10.3.4. in [9])
+ *
+ * This function is used only as a subrutine of
+ * ecp_mul_comb().
+ *
+ * Warning: fails (returning an error) if one of the points is
+ * zero!
+ * This should never happen, see choice of w in ecp_mul_comb().
+ *
+ * \param grp Pointer to the group representing the curve.
+ *
+ * \param T Array of pointers to the points to normalise.
+ *
+ * \param t_len Number of elements in the array.
+ *
+ * \return 0 if successful,
+ * an error if one of the points is zero.
+ */
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_JAC_MANY_ALT)
+int mbedcrypto_internal_ecp_normalize_jac_many( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *T[], size_t t_len );
+#endif
+
+/**
+ * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1.
+ *
+ * Cost in field operations if done by [5] 3.2.1:
+ * 1N := 1I + 3M + 1S
+ *
+ * \param grp Pointer to the group representing the curve.
+ *
+ * \param pt pointer to the point to be normalised. This is an
+ * input/output parameter.
+ *
+ * \return 0 if successful.
+ */
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_JAC_ALT)
+int mbedcrypto_internal_ecp_normalize_jac( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *pt );
+#endif
+
+#endif /* ECP_SHORTWEIERSTRASS */
+
+#if defined(ECP_MONTGOMERY)
+
+#if defined(MBEDCRYPTO_ECP_DOUBLE_ADD_MXZ_ALT)
+int mbedcrypto_internal_ecp_double_add_mxz( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *R, mbedcrypto_ecp_point *S, const mbedcrypto_ecp_point *P,
+ const mbedcrypto_ecp_point *Q, const mbedcrypto_mpi *d );
+#endif
+
+/**
+ * \brief Randomize projective x/z coordinates:
+ * (X, Z) -> (l X, l Z) for random l
+ *
+ * \param grp pointer to the group representing the curve
+ *
+ * \param P the point on the curve to be randomised given with
+ * projective coordinates. This is an input/output parameter.
+ *
+ * \param f_rng a function pointer to the random number generator
+ *
+ * \param p_rng a pointer to the random number generator state
+ *
+ * \return 0 if successful
+ */
+#if defined(MBEDCRYPTO_ECP_RANDOMIZE_MXZ_ALT)
+int mbedcrypto_internal_ecp_randomize_mxz( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+#endif
+
+/**
+ * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1.
+ *
+ * \param grp pointer to the group representing the curve
+ *
+ * \param P pointer to the point to be normalised. This is an
+ * input/output parameter.
+ *
+ * \return 0 if successful
+ */
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_MXZ_ALT)
+int mbedcrypto_internal_ecp_normalize_mxz( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *P );
+#endif
+
+#endif /* ECP_MONTGOMERY */
+
+#endif /* MBEDCRYPTO_ECP_INTERNAL_ALT */
+
+#endif /* ecp_internal.h */
+
diff --git a/include/mbedcrypto/entropy.h b/include/mbedcrypto/entropy.h
new file mode 100644
index 0000000..9ba727f
--- /dev/null
+++ b/include/mbedcrypto/entropy.h
@@ -0,0 +1,289 @@
+/**
+ * \file entropy.h
+ *
+ * \brief Entropy accumulator implementation
+ */
+/*
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_ENTROPY_H
+#define MBEDCRYPTO_ENTROPY_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#if defined(MBEDCRYPTO_SHA512_C) && !defined(MBEDCRYPTO_ENTROPY_FORCE_SHA256)
+#include "sha512.h"
+#define MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR
+#else
+#if defined(MBEDCRYPTO_SHA256_C)
+#define MBEDCRYPTO_ENTROPY_SHA256_ACCUMULATOR
+#include "sha256.h"
+#endif
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_C)
+#include "threading.h"
+#endif
+
+#if defined(MBEDCRYPTO_HAVEGE_C)
+#include "havege.h"
+#endif
+
+#define MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */
+#define MBEDCRYPTO_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */
+#define MBEDCRYPTO_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */
+#define MBEDCRYPTO_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */
+#define MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(MBEDCRYPTO_ENTROPY_MAX_SOURCES)
+#define MBEDCRYPTO_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */
+#endif
+
+#if !defined(MBEDCRYPTO_ENTROPY_MAX_GATHER)
+#define MBEDCRYPTO_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#if defined(MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR)
+#define MBEDCRYPTO_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */
+#else
+#define MBEDCRYPTO_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */
+#endif
+
+#define MBEDCRYPTO_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */
+#define MBEDCRYPTO_ENTROPY_SOURCE_MANUAL MBEDCRYPTO_ENTROPY_MAX_SOURCES
+
+#define MBEDCRYPTO_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */
+#define MBEDCRYPTO_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Entropy poll callback pointer
+ *
+ * \param data Callback-specific data pointer
+ * \param output Data to fill
+ * \param len Maximum size to provide
+ * \param olen The actual amount of bytes put into the buffer (Can be 0)
+ *
+ * \return 0 if no critical failures occurred,
+ * MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED otherwise
+ */
+typedef int (*mbedcrypto_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len,
+ size_t *olen);
+
+/**
+ * \brief Entropy source state
+ */
+typedef struct
+{
+ mbedcrypto_entropy_f_source_ptr f_source; /**< The entropy source callback */
+ void * p_source; /**< The callback data pointer */
+ size_t size; /**< Amount received in bytes */
+ size_t threshold; /**< Minimum bytes required before release */
+ int strong; /**< Is the source strong? */
+}
+mbedcrypto_entropy_source_state;
+
+/**
+ * \brief Entropy context structure
+ */
+typedef struct
+{
+ int accumulator_started;
+#if defined(MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR)
+ mbedcrypto_sha512_context accumulator;
+#else
+ mbedcrypto_sha256_context accumulator;
+#endif
+ int source_count;
+ mbedcrypto_entropy_source_state source[MBEDCRYPTO_ENTROPY_MAX_SOURCES];
+#if defined(MBEDCRYPTO_HAVEGE_C)
+ mbedcrypto_havege_state havege_data;
+#endif
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_threading_mutex_t mutex; /*!< mutex */
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+ int initial_entropy_run;
+#endif
+}
+mbedcrypto_entropy_context;
+
+/**
+ * \brief Initialize the context
+ *
+ * \param ctx Entropy context to initialize
+ */
+void mbedcrypto_entropy_init( mbedcrypto_entropy_context *ctx );
+
+/**
+ * \brief Free the data in the context
+ *
+ * \param ctx Entropy context to free
+ */
+void mbedcrypto_entropy_free( mbedcrypto_entropy_context *ctx );
+
+/**
+ * \brief Adds an entropy source to poll
+ * (Thread-safe if MBEDCRYPTO_THREADING_C is enabled)
+ *
+ * \param ctx Entropy context
+ * \param f_source Entropy function
+ * \param p_source Function data
+ * \param threshold Minimum required from source before entropy is released
+ * ( with mbedcrypto_entropy_func() ) (in bytes)
+ * \param strong MBEDCRYPTO_ENTROPY_SOURCE_STRONG or
+ * MBEDCRYPTO_ENTROPY_SOURCE_WEAK.
+ * At least one strong source needs to be added.
+ * Weaker sources (such as the cycle counter) can be used as
+ * a complement.
+ *
+ * \return 0 if successful or MBEDCRYPTO_ERR_ENTROPY_MAX_SOURCES
+ */
+int mbedcrypto_entropy_add_source( mbedcrypto_entropy_context *ctx,
+ mbedcrypto_entropy_f_source_ptr f_source, void *p_source,
+ size_t threshold, int strong );
+
+/**
+ * \brief Trigger an extra gather poll for the accumulator
+ * (Thread-safe if MBEDCRYPTO_THREADING_C is enabled)
+ *
+ * \param ctx Entropy context
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_entropy_gather( mbedcrypto_entropy_context *ctx );
+
+/**
+ * \brief Retrieve entropy from the accumulator
+ * (Maximum length: MBEDCRYPTO_ENTROPY_BLOCK_SIZE)
+ * (Thread-safe if MBEDCRYPTO_THREADING_C is enabled)
+ *
+ * \param data Entropy context
+ * \param output Buffer to fill
+ * \param len Number of bytes desired, must be at most MBEDCRYPTO_ENTROPY_BLOCK_SIZE
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_entropy_func( void *data, unsigned char *output, size_t len );
+
+/**
+ * \brief Add data to the accumulator manually
+ * (Thread-safe if MBEDCRYPTO_THREADING_C is enabled)
+ *
+ * \param ctx Entropy context
+ * \param data Data to add
+ * \param len Length of data
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_entropy_update_manual( mbedcrypto_entropy_context *ctx,
+ const unsigned char *data, size_t len );
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+/**
+ * \brief Trigger an update of the seed file in NV by using the
+ * current entropy pool.
+ *
+ * \param ctx Entropy context
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_entropy_update_nv_seed( mbedcrypto_entropy_context *ctx );
+#endif /* MBEDCRYPTO_ENTROPY_NV_SEED */
+
+#if defined(MBEDCRYPTO_FS_IO)
+/**
+ * \brief Write a seed file
+ *
+ * \param ctx Entropy context
+ * \param path Name of the file
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR on file error, or
+ * MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_entropy_write_seed_file( mbedcrypto_entropy_context *ctx, const char *path );
+
+/**
+ * \brief Read and update a seed file. Seed is added to this
+ * instance. No more than MBEDCRYPTO_ENTROPY_MAX_SEED_SIZE bytes are
+ * read from the seed file. The rest is ignored.
+ *
+ * \param ctx Entropy context
+ * \param path Name of the file
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR on file error,
+ * MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_entropy_update_seed_file( mbedcrypto_entropy_context *ctx, const char *path );
+#endif /* MBEDCRYPTO_FS_IO */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/**
+ * \brief Checkup routine
+ *
+ * This module self-test also calls the entropy self-test,
+ * mbedcrypto_entropy_source_self_test();
+ *
+ * \return 0 if successful, or 1 if a test failed
+ */
+int mbedcrypto_entropy_self_test( int verbose );
+
+#if defined(MBEDCRYPTO_ENTROPY_HARDWARE_ALT)
+/**
+ * \brief Checkup routine
+ *
+ * Verifies the integrity of the hardware entropy source
+ * provided by the function 'mbedcrypto_hardware_poll()'.
+ *
+ * Note this is the only hardware entropy source that is known
+ * at link time, and other entropy sources configured
+ * dynamically at runtime by the function
+ * mbedcrypto_entropy_add_source() will not be tested.
+ *
+ * \return 0 if successful, or 1 if a test failed
+ */
+int mbedcrypto_entropy_source_self_test( int verbose );
+#endif /* MBEDCRYPTO_ENTROPY_HARDWARE_ALT */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy.h */
diff --git a/include/mbedcrypto/entropy_poll.h b/include/mbedcrypto/entropy_poll.h
new file mode 100644
index 0000000..a044557
--- /dev/null
+++ b/include/mbedcrypto/entropy_poll.h
@@ -0,0 +1,110 @@
+/**
+ * \file entropy_poll.h
+ *
+ * \brief Platform-specific and custom entropy polling functions
+ */
+/*
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_ENTROPY_POLL_H
+#define MBEDCRYPTO_ENTROPY_POLL_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Default thresholds for built-in sources, in bytes
+ */
+#define MBEDCRYPTO_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */
+#define MBEDCRYPTO_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */
+#define MBEDCRYPTO_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedcrypto_timing_hardclock() */
+#if !defined(MBEDCRYPTO_ENTROPY_MIN_HARDWARE)
+#define MBEDCRYPTO_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */
+#endif
+
+/**
+ * \brief Entropy poll callback that provides 0 entropy.
+ */
+#if defined(MBEDCRYPTO_TEST_NULL_ENTROPY)
+ int mbedcrypto_null_entropy_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if !defined(MBEDCRYPTO_NO_PLATFORM_ENTROPY)
+/**
+ * \brief Platform-specific entropy poll callback
+ */
+int mbedcrypto_platform_entropy_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(MBEDCRYPTO_HAVEGE_C)
+/**
+ * \brief HAVEGE based entropy poll callback
+ *
+ * Requires an HAVEGE state as its data pointer.
+ */
+int mbedcrypto_havege_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(MBEDCRYPTO_TIMING_C)
+/**
+ * \brief mbedcrypto_timing_hardclock-based entropy poll callback
+ */
+int mbedcrypto_hardclock_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(MBEDCRYPTO_ENTROPY_HARDWARE_ALT)
+/**
+ * \brief Entropy poll callback for a hardware source
+ *
+ * \warning This is not provided by Mbed Crypto!
+ * See \c MBEDCRYPTO_ENTROPY_HARDWARE_ALT in config.h.
+ *
+ * \note This must accept NULL as its first argument.
+ */
+int mbedcrypto_hardware_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+/**
+ * \brief Entropy poll callback for a non-volatile seed file
+ *
+ * \note This must accept NULL as its first argument.
+ */
+int mbedcrypto_nv_seed_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy_poll.h */
diff --git a/include/mbedcrypto/error.h b/include/mbedcrypto/error.h
new file mode 100644
index 0000000..3c7721f
--- /dev/null
+++ b/include/mbedcrypto/error.h
@@ -0,0 +1,117 @@
+/**
+ * \file error.h
+ *
+ * \brief Error to string translation
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_ERROR_H
+#define MBEDCRYPTO_ERROR_H
+
+#include <stddef.h>
+
+/**
+ * Error code layout.
+ *
+ * Currently we try to keep all error codes within the negative space of 16
+ * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In
+ * addition we'd like to give two layers of information on the error if
+ * possible.
+ *
+ * For that purpose the error codes are segmented in the following manner:
+ *
+ * 16 bit error code bit-segmentation
+ *
+ * 1 bit - Unused (sign bit)
+ * 3 bits - High level module ID
+ * 5 bits - Module-dependent error code
+ * 7 bits - Low level module errors
+ *
+ * For historical reasons, low-level error codes are divided in even and odd,
+ * even codes were assigned first, and -1 is reserved for other errors.
+ *
+ * Low-level module errors (0x0002-0x007E, 0x0003-0x007F)
+ *
+ * Module Nr Codes assigned
+ * MPI 7 0x0002-0x0010
+ * GCM 3 0x0012-0x0014 0x0013-0x0013
+ * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017
+ * THREADING 3 0x001A-0x001E
+ * AES 4 0x0020-0x0022 0x0023-0x0025
+ * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027
+ * XTEA 2 0x0028-0x0028 0x0029-0x0029
+ * BASE64 2 0x002A-0x002C
+ * OID 1 0x002E-0x002E 0x000B-0x000B
+ * PADLOCK 1 0x0030-0x0030
+ * DES 2 0x0032-0x0032 0x0033-0x0033
+ * CTR_DBRG 4 0x0034-0x003A
+ * ENTROPY 3 0x003C-0x0040 0x003D-0x003F
+ * NET 11 0x0042-0x0052 0x0043-0x0045
+ * ASN1 7 0x0060-0x006C
+ * CMAC 1 0x007A-0x007A
+ * PBKDF2 1 0x007C-0x007C
+ * HMAC_DRBG 4 0x0003-0x0009
+ * CCM 3 0x000D-0x0011
+ * ARC4 1 0x0019-0x0019
+ * MD2 1 0x002B-0x002B
+ * MD4 1 0x002D-0x002D
+ * MD5 1 0x002F-0x002F
+ * RIPEMD160 1 0x0031-0x0031
+ * SHA1 1 0x0035-0x0035
+ * SHA256 1 0x0037-0x0037
+ * SHA512 1 0x0039-0x0039
+ *
+ * High-level module nr (3 bits - 0x0...-0x7...)
+ * Name ID Nr of Errors
+ * PEM 1 9
+ * PKCS#12 1 4 (Started from top)
+ * X509 2 20
+ * PKCS5 2 4 (Started from top)
+ * DHM 3 11
+ * PK 3 15 (Started from top)
+ * RSA 4 11
+ * ECP 4 9 (Started from top)
+ * MD 5 5
+ * CIPHER 6 8
+ * SSL 6 17 (Started from top)
+ * SSL 7 31
+ *
+ * Module dependent error code (5 bits 0x.00.-0x.F8.)
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Translate a Mbed Crypto error code into a string representation,
+ * Result is truncated if necessary and always includes a terminating
+ * null byte.
+ *
+ * \param errnum error code
+ * \param buffer buffer to place representation in
+ * \param buflen length of the buffer
+ */
+void mbedcrypto_strerror( int errnum, char *buffer, size_t buflen );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */
diff --git a/include/mbedcrypto/gcm.h b/include/mbedcrypto/gcm.h
new file mode 100644
index 0000000..373797a
--- /dev/null
+++ b/include/mbedcrypto/gcm.h
@@ -0,0 +1,266 @@
+/**
+ * \file gcm.h
+ *
+ * \brief This file contains GCM definitions and functions.
+ *
+ * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined
+ * in <em>D. McGrew, J. Viega, The Galois/Counter Mode of Operation
+ * (GCM), Natl. Inst. Stand. Technol.</em>
+ *
+ * For more information on GCM, see <em>NIST SP 800-38D: Recommendation for
+ * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC</em>.
+ *
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_GCM_H
+#define MBEDCRYPTO_GCM_H
+
+#include "cipher.h"
+
+#include <stdint.h>
+
+#define MBEDCRYPTO_GCM_ENCRYPT 1
+#define MBEDCRYPTO_GCM_DECRYPT 0
+
+#define MBEDCRYPTO_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
+#define MBEDCRYPTO_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */
+#define MBEDCRYPTO_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_GCM_ALT)
+
+/**
+ * \brief The GCM context structure.
+ */
+typedef struct {
+ mbedcrypto_cipher_context_t cipher_ctx; /*!< The cipher context used. */
+ uint64_t HL[16]; /*!< Precalculated HTable low. */
+ uint64_t HH[16]; /*!< Precalculated HTable high. */
+ uint64_t len; /*!< The total length of the encrypted data. */
+ uint64_t add_len; /*!< The total length of the additional data. */
+ unsigned char base_ectr[16]; /*!< The first ECTR for tag. */
+ unsigned char y[16]; /*!< The Y working value. */
+ unsigned char buf[16]; /*!< The buf working value. */
+ int mode; /*!< The operation to perform:
+ #MBEDCRYPTO_GCM_ENCRYPT or
+ #MBEDCRYPTO_GCM_DECRYPT. */
+}
+mbedcrypto_gcm_context;
+
+#else /* !MBEDCRYPTO_GCM_ALT */
+#include "gcm_alt.h"
+#endif /* !MBEDCRYPTO_GCM_ALT */
+
+/**
+ * \brief This function initializes the specified GCM context,
+ * to make references valid, and prepares the context
+ * for mbedcrypto_gcm_setkey() or mbedcrypto_gcm_free().
+ *
+ * The function does not bind the GCM context to a particular
+ * cipher, nor set the key. For this purpose, use
+ * mbedcrypto_gcm_setkey().
+ *
+ * \param ctx The GCM context to initialize.
+ */
+void mbedcrypto_gcm_init( mbedcrypto_gcm_context *ctx );
+
+/**
+ * \brief This function associates a GCM context with a
+ * cipher algorithm and a key.
+ *
+ * \param ctx The GCM context to initialize.
+ * \param cipher The 128-bit block cipher to use.
+ * \param key The encryption key.
+ * \param keybits The key size in bits. Valid options are:
+ * <ul><li>128 bits</li>
+ * <li>192 bits</li>
+ * <li>256 bits</li></ul>
+ *
+ * \return \c 0 on success.
+ * \return A cipher-specific error code on failure.
+ */
+int mbedcrypto_gcm_setkey( mbedcrypto_gcm_context *ctx,
+ mbedcrypto_cipher_id_t cipher,
+ const unsigned char *key,
+ unsigned int keybits );
+
+/**
+ * \brief This function performs GCM encryption or decryption of a buffer.
+ *
+ * \note For encryption, the output buffer can be the same as the
+ * input buffer. For decryption, the output buffer cannot be
+ * the same as input buffer. If the buffers overlap, the output
+ * buffer must trail at least 8 Bytes behind the input buffer.
+ *
+ * \param ctx The GCM context to use for encryption or decryption.
+ * \param mode The operation to perform: #MBEDCRYPTO_GCM_ENCRYPT or
+ * #MBEDCRYPTO_GCM_DECRYPT.
+ * \param length The length of the input data. This must be a multiple of
+ * 16 except in the last call before mbedcrypto_gcm_finish().
+ * \param iv The initialization vector.
+ * \param iv_len The length of the IV.
+ * \param add The buffer holding the additional data.
+ * \param add_len The length of the additional data.
+ * \param input The buffer holding the input data.
+ * \param output The buffer for holding the output data.
+ * \param tag_len The length of the tag to generate.
+ * \param tag The buffer for holding the tag.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_gcm_crypt_and_tag( mbedcrypto_gcm_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t tag_len,
+ unsigned char *tag );
+
+/**
+ * \brief This function performs a GCM authenticated decryption of a
+ * buffer.
+ *
+ * \note For decryption, the output buffer cannot be the same as
+ * input buffer. If the buffers overlap, the output buffer
+ * must trail at least 8 Bytes behind the input buffer.
+ *
+ * \param ctx The GCM context.
+ * \param length The length of the input data. This must be a multiple
+ * of 16 except in the last call before mbedcrypto_gcm_finish().
+ * \param iv The initialization vector.
+ * \param iv_len The length of the IV.
+ * \param add The buffer holding the additional data.
+ * \param add_len The length of the additional data.
+ * \param tag The buffer holding the tag.
+ * \param tag_len The length of the tag.
+ * \param input The buffer holding the input data.
+ * \param output The buffer for holding the output data.
+ *
+ * \return 0 if successful and authenticated.
+ * \return #MBEDCRYPTO_ERR_GCM_AUTH_FAILED if the tag does not match.
+ */
+int mbedcrypto_gcm_auth_decrypt( mbedcrypto_gcm_context *ctx,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *tag,
+ size_t tag_len,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function starts a GCM encryption or decryption
+ * operation.
+ *
+ * \param ctx The GCM context.
+ * \param mode The operation to perform: #MBEDCRYPTO_GCM_ENCRYPT or
+ * #MBEDCRYPTO_GCM_DECRYPT.
+ * \param iv The initialization vector.
+ * \param iv_len The length of the IV.
+ * \param add The buffer holding the additional data, or NULL
+ * if \p add_len is 0.
+ * \param add_len The length of the additional data. If 0,
+ * \p add is NULL.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_gcm_starts( mbedcrypto_gcm_context *ctx,
+ int mode,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing GCM
+ * encryption or decryption operation.
+ *
+ * ` The function expects input to be a multiple of 16
+ * Bytes. Only the last call before calling
+ * mbedcrypto_gcm_finish() can be less than 16 Bytes.
+ *
+ * \note For decryption, the output buffer cannot be the same as
+ * input buffer. If the buffers overlap, the output buffer
+ * must trail at least 8 Bytes behind the input buffer.
+ *
+ * \param ctx The GCM context.
+ * \param length The length of the input data. This must be a multiple of
+ * 16 except in the last call before mbedcrypto_gcm_finish().
+ * \param input The buffer holding the input data.
+ * \param output The buffer for holding the output data.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_GCM_BAD_INPUT on failure.
+ */
+int mbedcrypto_gcm_update( mbedcrypto_gcm_context *ctx,
+ size_t length,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function finishes the GCM operation and generates
+ * the authentication tag.
+ *
+ * It wraps up the GCM stream, and generates the
+ * tag. The tag can have a maximum length of 16 Bytes.
+ *
+ * \param ctx The GCM context.
+ * \param tag The buffer for holding the tag.
+ * \param tag_len The length of the tag to generate. Must be at least four.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_GCM_BAD_INPUT on failure.
+ */
+int mbedcrypto_gcm_finish( mbedcrypto_gcm_context *ctx,
+ unsigned char *tag,
+ size_t tag_len );
+
+/**
+ * \brief This function clears a GCM context and the underlying
+ * cipher sub-context.
+ *
+ * \param ctx The GCM context to clear.
+ */
+void mbedcrypto_gcm_free( mbedcrypto_gcm_context *ctx );
+
+/**
+ * \brief The GCM checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedcrypto_gcm_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* gcm.h */
diff --git a/include/mbedcrypto/hmac_drbg.h b/include/mbedcrypto/hmac_drbg.h
new file mode 100644
index 0000000..4e87fcd
--- /dev/null
+++ b/include/mbedcrypto/hmac_drbg.h
@@ -0,0 +1,300 @@
+/**
+ * \file hmac_drbg.h
+ *
+ * \brief HMAC_DRBG (NIST SP 800-90A)
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_HMAC_DRBG_H
+#define MBEDCRYPTO_HMAC_DRBG_H
+
+#include "md.h"
+
+#if defined(MBEDCRYPTO_THREADING_C)
+#include "mbedcrypto/threading.h"
+#endif
+
+/*
+ * Error codes
+ */
+#define MBEDCRYPTO_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */
+#define MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */
+#define MBEDCRYPTO_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */
+#define MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(MBEDCRYPTO_HMAC_DRBG_RESEED_INTERVAL)
+#define MBEDCRYPTO_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+#endif
+
+#if !defined(MBEDCRYPTO_HMAC_DRBG_MAX_INPUT)
+#define MBEDCRYPTO_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+#endif
+
+#if !defined(MBEDCRYPTO_HMAC_DRBG_MAX_REQUEST)
+#define MBEDCRYPTO_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+#endif
+
+#if !defined(MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT)
+#define MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#define MBEDCRYPTO_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */
+#define MBEDCRYPTO_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * HMAC_DRBG context.
+ */
+typedef struct
+{
+ /* Working state: the key K is not stored explicitely,
+ * but is implied by the HMAC context */
+ mbedcrypto_md_context_t md_ctx; /*!< HMAC context (inc. K) */
+ unsigned char V[MBEDCRYPTO_MD_MAX_SIZE]; /*!< V in the spec */
+ int reseed_counter; /*!< reseed counter */
+
+ /* Administrative state */
+ size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */
+ int prediction_resistance; /*!< enable prediction resistance (Automatic
+ reseed before every random generation) */
+ int reseed_interval; /*!< reseed interval */
+
+ /* Callbacks */
+ int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */
+ void *p_entropy; /*!< context for the entropy function */
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_threading_mutex_t mutex;
+#endif
+} mbedcrypto_hmac_drbg_context;
+
+/**
+ * \brief HMAC_DRBG context initialization
+ * Makes the context ready for mbedcrypto_hmac_drbg_seed(),
+ * mbedcrypto_hmac_drbg_seed_buf() or
+ * mbedcrypto_hmac_drbg_free().
+ *
+ * \param ctx HMAC_DRBG context to be initialized
+ */
+void mbedcrypto_hmac_drbg_init( mbedcrypto_hmac_drbg_context *ctx );
+
+/**
+ * \brief HMAC_DRBG initial seeding
+ * Seed and setup entropy source for future reseeds.
+ *
+ * \param ctx HMAC_DRBG context to be seeded
+ * \param md_info MD algorithm to use for HMAC_DRBG
+ * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer
+ * length)
+ * \param p_entropy Entropy context
+ * \param custom Personalization data (Device specific identifiers)
+ * (Can be NULL)
+ * \param len Length of personalization data
+ *
+ * \note The "security strength" as defined by NIST is set to:
+ * 128 bits if md_alg is SHA-1,
+ * 192 bits if md_alg is SHA-224,
+ * 256 bits if md_alg is SHA-256 or higher.
+ * Note that SHA-256 is just as efficient as SHA-224.
+ *
+ * \return 0 if successful, or
+ * MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA, or
+ * MBEDCRYPTO_ERR_MD_ALLOC_FAILED, or
+ * MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED.
+ */
+int mbedcrypto_hmac_drbg_seed( mbedcrypto_hmac_drbg_context *ctx,
+ const mbedcrypto_md_info_t * md_info,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len );
+
+/**
+ * \brief Initilisation of simpified HMAC_DRBG (never reseeds).
+ * (For use with deterministic ECDSA.)
+ *
+ * \param ctx HMAC_DRBG context to be initialised
+ * \param md_info MD algorithm to use for HMAC_DRBG
+ * \param data Concatenation of entropy string and additional data
+ * \param data_len Length of data in bytes
+ *
+ * \return 0 if successful, or
+ * MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA, or
+ * MBEDCRYPTO_ERR_MD_ALLOC_FAILED.
+ */
+int mbedcrypto_hmac_drbg_seed_buf( mbedcrypto_hmac_drbg_context *ctx,
+ const mbedcrypto_md_info_t * md_info,
+ const unsigned char *data, size_t data_len );
+
+/**
+ * \brief Enable / disable prediction resistance (Default: Off)
+ *
+ * Note: If enabled, entropy is used for ctx->entropy_len before each call!
+ * Only use this if you have ample supply of good entropy!
+ *
+ * \param ctx HMAC_DRBG context
+ * \param resistance MBEDCRYPTO_HMAC_DRBG_PR_ON or MBEDCRYPTO_HMAC_DRBG_PR_OFF
+ */
+void mbedcrypto_hmac_drbg_set_prediction_resistance( mbedcrypto_hmac_drbg_context *ctx,
+ int resistance );
+
+/**
+ * \brief Set the amount of entropy grabbed on each reseed
+ * (Default: given by the security strength, which
+ * depends on the hash used, see \c mbedcrypto_hmac_drbg_init() )
+ *
+ * \param ctx HMAC_DRBG context
+ * \param len Amount of entropy to grab, in bytes
+ */
+void mbedcrypto_hmac_drbg_set_entropy_len( mbedcrypto_hmac_drbg_context *ctx,
+ size_t len );
+
+/**
+ * \brief Set the reseed interval
+ * (Default: MBEDCRYPTO_HMAC_DRBG_RESEED_INTERVAL)
+ *
+ * \param ctx HMAC_DRBG context
+ * \param interval Reseed interval
+ */
+void mbedcrypto_hmac_drbg_set_reseed_interval( mbedcrypto_hmac_drbg_context *ctx,
+ int interval );
+
+/**
+ * \brief HMAC_DRBG update state
+ *
+ * \param ctx HMAC_DRBG context
+ * \param additional Additional data to update state with, or NULL
+ * \param add_len Length of additional data, or 0
+ *
+ * \note Additional data is optional, pass NULL and 0 as second
+ * third argument if no additional data is being used.
+ */
+void mbedcrypto_hmac_drbg_update( mbedcrypto_hmac_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief HMAC_DRBG reseeding (extracts data from entropy source)
+ *
+ * \param ctx HMAC_DRBG context
+ * \param additional Additional data to add to state (Can be NULL)
+ * \param len Length of additional data
+ *
+ * \return 0 if successful, or
+ * MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_hmac_drbg_reseed( mbedcrypto_hmac_drbg_context *ctx,
+ const unsigned char *additional, size_t len );
+
+/**
+ * \brief HMAC_DRBG generate random with additional update input
+ *
+ * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ *
+ * \param p_rng HMAC_DRBG context
+ * \param output Buffer to fill
+ * \param output_len Length of the buffer
+ * \param additional Additional data to update with (can be NULL)
+ * \param add_len Length of additional data (can be 0)
+ *
+ * \return 0 if successful, or
+ * MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
+ * MBEDCRYPTO_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or
+ * MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG.
+ */
+int mbedcrypto_hmac_drbg_random_with_add( void *p_rng,
+ unsigned char *output, size_t output_len,
+ const unsigned char *additional,
+ size_t add_len );
+
+/**
+ * \brief HMAC_DRBG generate random
+ *
+ * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ *
+ * \param p_rng HMAC_DRBG context
+ * \param output Buffer to fill
+ * \param out_len Length of the buffer
+ *
+ * \return 0 if successful, or
+ * MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
+ * MBEDCRYPTO_ERR_HMAC_DRBG_REQUEST_TOO_BIG
+ */
+int mbedcrypto_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len );
+
+/**
+ * \brief Free an HMAC_DRBG context
+ *
+ * \param ctx HMAC_DRBG context to free.
+ */
+void mbedcrypto_hmac_drbg_free( mbedcrypto_hmac_drbg_context *ctx );
+
+#if defined(MBEDCRYPTO_FS_IO)
+/**
+ * \brief Write a seed file
+ *
+ * \param ctx HMAC_DRBG context
+ * \param path Name of the file
+ *
+ * \return 0 if successful, 1 on file error, or
+ * MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int mbedcrypto_hmac_drbg_write_seed_file( mbedcrypto_hmac_drbg_context *ctx, const char *path );
+
+/**
+ * \brief Read and update a seed file. Seed is added to this
+ * instance
+ *
+ * \param ctx HMAC_DRBG context
+ * \param path Name of the file
+ *
+ * \return 0 if successful, 1 on file error,
+ * MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or
+ * MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG
+ */
+int mbedcrypto_hmac_drbg_update_seed_file( mbedcrypto_hmac_drbg_context *ctx, const char *path );
+#endif /* MBEDCRYPTO_FS_IO */
+
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_hmac_drbg_self_test( int verbose );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* hmac_drbg.h */
diff --git a/include/mbedcrypto/md.h b/include/mbedcrypto/md.h
new file mode 100644
index 0000000..4098662
--- /dev/null
+++ b/include/mbedcrypto/md.h
@@ -0,0 +1,465 @@
+ /**
+ * \file md.h
+ *
+ * \brief This file contains the generic message-digest wrapper.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_MD_H
+#define MBEDCRYPTO_MD_H
+
+#include <stddef.h>
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#define MBEDCRYPTO_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */
+#define MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */
+#define MBEDCRYPTO_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */
+#define MBEDCRYPTO_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Supported message digests.
+ *
+ * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and
+ * their use constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+typedef enum {
+ MBEDCRYPTO_MD_NONE=0, /**< None. */
+ MBEDCRYPTO_MD_MD2, /**< The MD2 message digest. */
+ MBEDCRYPTO_MD_MD4, /**< The MD4 message digest. */
+ MBEDCRYPTO_MD_MD5, /**< The MD5 message digest. */
+ MBEDCRYPTO_MD_SHA1, /**< The SHA-1 message digest. */
+ MBEDCRYPTO_MD_SHA224, /**< The SHA-224 message digest. */
+ MBEDCRYPTO_MD_SHA256, /**< The SHA-256 message digest. */
+ MBEDCRYPTO_MD_SHA384, /**< The SHA-384 message digest. */
+ MBEDCRYPTO_MD_SHA512, /**< The SHA-512 message digest. */
+ MBEDCRYPTO_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */
+} mbedcrypto_md_type_t;
+
+#if defined(MBEDCRYPTO_SHA512_C)
+#define MBEDCRYPTO_MD_MAX_SIZE 64 /* longest known is SHA512 */
+#else
+#define MBEDCRYPTO_MD_MAX_SIZE 32 /* longest known is SHA256 or less */
+#endif
+
+/**
+ * Opaque struct defined in md_internal.h.
+ */
+typedef struct mbedcrypto_md_info_t mbedcrypto_md_info_t;
+
+/**
+ * The generic message-digest context.
+ */
+typedef struct {
+ /** Information about the associated message digest. */
+ const mbedcrypto_md_info_t *md_info;
+
+ /** The digest-specific context. */
+ void *md_ctx;
+
+ /** The HMAC part of the context. */
+ void *hmac_ctx;
+} mbedcrypto_md_context_t;
+
+/**
+ * \brief This function returns the list of digests supported by the
+ * generic digest module.
+ *
+ * \return A statically allocated array of digests. Each element
+ * in the returned list is an integer belonging to the
+ * message-digest enumeration #mbedcrypto_md_type_t.
+ * The last entry is 0.
+ */
+const int *mbedcrypto_md_list( void );
+
+/**
+ * \brief This function returns the message-digest information
+ * associated with the given digest name.
+ *
+ * \param md_name The name of the digest to search for.
+ *
+ * \return The message-digest information associated with \p md_name.
+ * \return NULL if the associated message-digest information is not found.
+ */
+const mbedcrypto_md_info_t *mbedcrypto_md_info_from_string( const char *md_name );
+
+/**
+ * \brief This function returns the message-digest information
+ * associated with the given digest type.
+ *
+ * \param md_type The type of digest to search for.
+ *
+ * \return The message-digest information associated with \p md_type.
+ * \return NULL if the associated message-digest information is not found.
+ */
+const mbedcrypto_md_info_t *mbedcrypto_md_info_from_type( mbedcrypto_md_type_t md_type );
+
+/**
+ * \brief This function initializes a message-digest context without
+ * binding it to a particular message-digest algorithm.
+ *
+ * This function should always be called first. It prepares the
+ * context for mbedcrypto_md_setup() for binding it to a
+ * message-digest algorithm.
+ */
+void mbedcrypto_md_init( mbedcrypto_md_context_t *ctx );
+
+/**
+ * \brief This function clears the internal structure of \p ctx and
+ * frees any embedded internal structure, but does not free
+ * \p ctx itself.
+ *
+ * If you have called mbedcrypto_md_setup() on \p ctx, you must
+ * call mbedcrypto_md_free() when you are no longer using the
+ * context.
+ * Calling this function if you have previously
+ * called mbedcrypto_md_init() and nothing else is optional.
+ * You must not call this function if you have not called
+ * mbedcrypto_md_init().
+ */
+void mbedcrypto_md_free( mbedcrypto_md_context_t *ctx );
+
+#if ! defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief This function selects the message digest algorithm to use,
+ * and allocates internal structures.
+ *
+ * It should be called after mbedcrypto_md_init() or mbedcrypto_md_free().
+ * Makes it necessary to call mbedcrypto_md_free() later.
+ *
+ * \deprecated Superseded by mbedcrypto_md_setup() in 2.0.0
+ *
+ * \param ctx The context to set up.
+ * \param md_info The information structure of the message-digest algorithm
+ * to use.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ * \return #MBEDCRYPTO_ERR_MD_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_md_init_ctx( mbedcrypto_md_context_t *ctx, const mbedcrypto_md_info_t *md_info ) MBEDCRYPTO_DEPRECATED;
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief This function selects the message digest algorithm to use,
+ * and allocates internal structures.
+ *
+ * It should be called after mbedcrypto_md_init() or
+ * mbedcrypto_md_free(). Makes it necessary to call
+ * mbedcrypto_md_free() later.
+ *
+ * \param ctx The context to set up.
+ * \param md_info The information structure of the message-digest algorithm
+ * to use.
+ * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory),
+ * or non-zero: HMAC is used with this context.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ * \return #MBEDCRYPTO_ERR_MD_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedcrypto_md_setup( mbedcrypto_md_context_t *ctx, const mbedcrypto_md_info_t *md_info, int hmac );
+
+/**
+ * \brief This function clones the state of an message-digest
+ * context.
+ *
+ * \note You must call mbedcrypto_md_setup() on \c dst before calling
+ * this function.
+ *
+ * \note The two contexts must have the same type,
+ * for example, both are SHA-256.
+ *
+ * \warning This function clones the message-digest state, not the
+ * HMAC state.
+ *
+ * \param dst The destination context.
+ * \param src The context to be cloned.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification failure.
+ */
+int mbedcrypto_md_clone( mbedcrypto_md_context_t *dst,
+ const mbedcrypto_md_context_t *src );
+
+/**
+ * \brief This function extracts the message-digest size from the
+ * message-digest information structure.
+ *
+ * \param md_info The information structure of the message-digest algorithm
+ * to use.
+ *
+ * \return The size of the message-digest output in Bytes.
+ */
+unsigned char mbedcrypto_md_get_size( const mbedcrypto_md_info_t *md_info );
+
+/**
+ * \brief This function extracts the message-digest type from the
+ * message-digest information structure.
+ *
+ * \param md_info The information structure of the message-digest algorithm
+ * to use.
+ *
+ * \return The type of the message digest.
+ */
+mbedcrypto_md_type_t mbedcrypto_md_get_type( const mbedcrypto_md_info_t *md_info );
+
+/**
+ * \brief This function extracts the message-digest name from the
+ * message-digest information structure.
+ *
+ * \param md_info The information structure of the message-digest algorithm
+ * to use.
+ *
+ * \return The name of the message digest.
+ */
+const char *mbedcrypto_md_get_name( const mbedcrypto_md_info_t *md_info );
+
+/**
+ * \brief This function starts a message-digest computation.
+ *
+ * You must call this function after setting up the context
+ * with mbedcrypto_md_setup(), and before passing data with
+ * mbedcrypto_md_update().
+ *
+ * \param ctx The generic message-digest context.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ */
+int mbedcrypto_md_starts( mbedcrypto_md_context_t *ctx );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing
+ * message-digest computation.
+ *
+ * You must call mbedcrypto_md_starts() before calling this
+ * function. You may call this function multiple times.
+ * Afterwards, call mbedcrypto_md_finish().
+ *
+ * \param ctx The generic message-digest context.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ */
+int mbedcrypto_md_update( mbedcrypto_md_context_t *ctx, const unsigned char *input, size_t ilen );
+
+/**
+ * \brief This function finishes the digest operation,
+ * and writes the result to the output buffer.
+ *
+ * Call this function after a call to mbedcrypto_md_starts(),
+ * followed by any number of calls to mbedcrypto_md_update().
+ * Afterwards, you may either clear the context with
+ * mbedcrypto_md_free(), or call mbedcrypto_md_starts() to reuse
+ * the context for another digest operation with the same
+ * algorithm.
+ *
+ * \param ctx The generic message-digest context.
+ * \param output The buffer for the generic message-digest checksum result.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ */
+int mbedcrypto_md_finish( mbedcrypto_md_context_t *ctx, unsigned char *output );
+
+/**
+ * \brief This function calculates the message-digest of a buffer,
+ * with respect to a configurable message-digest algorithm
+ * in a single call.
+ *
+ * The result is calculated as
+ * Output = message_digest(input buffer).
+ *
+ * \param md_info The information structure of the message-digest algorithm
+ * to use.
+ * \param input The buffer holding the data.
+ * \param ilen The length of the input data.
+ * \param output The generic message-digest checksum result.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ */
+int mbedcrypto_md( const mbedcrypto_md_info_t *md_info, const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+#if defined(MBEDCRYPTO_FS_IO)
+/**
+ * \brief This function calculates the message-digest checksum
+ * result of the contents of the provided file.
+ *
+ * The result is calculated as
+ * Output = message_digest(file contents).
+ *
+ * \param md_info The information structure of the message-digest algorithm
+ * to use.
+ * \param path The input file name.
+ * \param output The generic message-digest checksum result.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_FILE_IO_ERROR on an I/O error accessing
+ * the file pointed by \p path.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL.
+ */
+int mbedcrypto_md_file( const mbedcrypto_md_info_t *md_info, const char *path,
+ unsigned char *output );
+#endif /* MBEDCRYPTO_FS_IO */
+
+/**
+ * \brief This function sets the HMAC key and prepares to
+ * authenticate a new message.
+ *
+ * Call this function after mbedcrypto_md_setup(), to use
+ * the MD context for an HMAC calculation, then call
+ * mbedcrypto_md_hmac_update() to provide the input data, and
+ * mbedcrypto_md_hmac_finish() to get the HMAC value.
+ *
+ * \param ctx The message digest context containing an embedded HMAC
+ * context.
+ * \param key The HMAC secret key.
+ * \param keylen The length of the HMAC key in Bytes.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ */
+int mbedcrypto_md_hmac_starts( mbedcrypto_md_context_t *ctx, const unsigned char *key,
+ size_t keylen );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing HMAC
+ * computation.
+ *
+ * Call mbedcrypto_md_hmac_starts() or mbedcrypto_md_hmac_reset()
+ * before calling this function.
+ * You may call this function multiple times to pass the
+ * input piecewise.
+ * Afterwards, call mbedcrypto_md_hmac_finish().
+ *
+ * \param ctx The message digest context containing an embedded HMAC
+ * context.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ */
+int mbedcrypto_md_hmac_update( mbedcrypto_md_context_t *ctx, const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief This function finishes the HMAC operation, and writes
+ * the result to the output buffer.
+ *
+ * Call this function after mbedcrypto_md_hmac_starts() and
+ * mbedcrypto_md_hmac_update() to get the HMAC value. Afterwards
+ * you may either call mbedcrypto_md_free() to clear the context,
+ * or call mbedcrypto_md_hmac_reset() to reuse the context with
+ * the same HMAC key.
+ *
+ * \param ctx The message digest context containing an embedded HMAC
+ * context.
+ * \param output The generic HMAC checksum result.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ */
+int mbedcrypto_md_hmac_finish( mbedcrypto_md_context_t *ctx, unsigned char *output);
+
+/**
+ * \brief This function prepares to authenticate a new message with
+ * the same key as the previous HMAC operation.
+ *
+ * You may call this function after mbedcrypto_md_hmac_finish().
+ * Afterwards call mbedcrypto_md_hmac_update() to pass the new
+ * input.
+ *
+ * \param ctx The message digest context containing an embedded HMAC
+ * context.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ */
+int mbedcrypto_md_hmac_reset( mbedcrypto_md_context_t *ctx );
+
+/**
+ * \brief This function calculates the full generic HMAC
+ * on the input buffer with the provided key.
+ *
+ * The function allocates the context, performs the
+ * calculation, and frees the context.
+ *
+ * The HMAC result is calculated as
+ * output = generic HMAC(hmac key, input buffer).
+ *
+ * \param md_info The information structure of the message-digest algorithm
+ * to use.
+ * \param key The HMAC secret key.
+ * \param keylen The length of the HMAC secret key in Bytes.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ * \param output The generic HMAC result.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA on parameter-verification
+ * failure.
+ */
+int mbedcrypto_md_hmac( const mbedcrypto_md_info_t *md_info, const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+/* Internal use */
+int mbedcrypto_md_process( mbedcrypto_md_context_t *ctx, const unsigned char *data );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_MD_H */
diff --git a/include/mbedcrypto/md2.h b/include/mbedcrypto/md2.h
new file mode 100644
index 0000000..dc56387
--- /dev/null
+++ b/include/mbedcrypto/md2.h
@@ -0,0 +1,301 @@
+/**
+ * \file md2.h
+ *
+ * \brief MD2 message digest algorithm (hash function)
+ *
+ * \warning MD2 is considered a weak message digest and its use constitutes a
+ * security risk. We recommend considering stronger message digests
+ * instead.
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+#ifndef MBEDCRYPTO_MD2_H
+#define MBEDCRYPTO_MD2_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#define MBEDCRYPTO_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_MD2_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief MD2 context structure
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+typedef struct
+{
+ unsigned char cksum[16]; /*!< checksum of the data block */
+ unsigned char state[48]; /*!< intermediate digest state */
+ unsigned char buffer[16]; /*!< data block being processed */
+ size_t left; /*!< amount of data in buffer */
+}
+mbedcrypto_md2_context;
+
+#else /* MBEDCRYPTO_MD2_ALT */
+#include "md2_alt.h"
+#endif /* MBEDCRYPTO_MD2_ALT */
+
+/**
+ * \brief Initialize MD2 context
+ *
+ * \param ctx MD2 context to be initialized
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+void mbedcrypto_md2_init( mbedcrypto_md2_context *ctx );
+
+/**
+ * \brief Clear MD2 context
+ *
+ * \param ctx MD2 context to be cleared
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+void mbedcrypto_md2_free( mbedcrypto_md2_context *ctx );
+
+/**
+ * \brief Clone (the state of) an MD2 context
+ *
+ * \param dst The destination context
+ * \param src The context to be cloned
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+void mbedcrypto_md2_clone( mbedcrypto_md2_context *dst,
+ const mbedcrypto_md2_context *src );
+
+/**
+ * \brief MD2 context setup
+ *
+ * \param ctx context to be initialized
+ *
+ * \return 0 if successful
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md2_starts_ret( mbedcrypto_md2_context *ctx );
+
+/**
+ * \brief MD2 process buffer
+ *
+ * \param ctx MD2 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \return 0 if successful
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md2_update_ret( mbedcrypto_md2_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief MD2 final digest
+ *
+ * \param ctx MD2 context
+ * \param output MD2 checksum result
+ *
+ * \return 0 if successful
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md2_finish_ret( mbedcrypto_md2_context *ctx,
+ unsigned char output[16] );
+
+/**
+ * \brief MD2 process data block (internal use only)
+ *
+ * \param ctx MD2 context
+ *
+ * \return 0 if successful
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_internal_md2_process( mbedcrypto_md2_context *ctx );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief MD2 context setup
+ *
+ * \deprecated Superseded by mbedcrypto_md2_starts_ret() in 2.7.0
+ *
+ * \param ctx context to be initialized
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md2_starts( mbedcrypto_md2_context *ctx );
+
+/**
+ * \brief MD2 process buffer
+ *
+ * \deprecated Superseded by mbedcrypto_md2_update_ret() in 2.7.0
+ *
+ * \param ctx MD2 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md2_update( mbedcrypto_md2_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief MD2 final digest
+ *
+ * \deprecated Superseded by mbedcrypto_md2_finish_ret() in 2.7.0
+ *
+ * \param ctx MD2 context
+ * \param output MD2 checksum result
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md2_finish( mbedcrypto_md2_context *ctx,
+ unsigned char output[16] );
+
+/**
+ * \brief MD2 process data block (internal use only)
+ *
+ * \deprecated Superseded by mbedcrypto_internal_md2_process() in 2.7.0
+ *
+ * \param ctx MD2 context
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md2_process( mbedcrypto_md2_context *ctx );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief Output = MD2( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD2 checksum result
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md2_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief Output = MD2( input buffer )
+ *
+ * \deprecated Superseded by mbedcrypto_md2_ret() in 2.7.0
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD2 checksum result
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md2( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ *
+ * \warning MD2 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md2_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_md2.h */
diff --git a/include/mbedcrypto/md4.h b/include/mbedcrypto/md4.h
new file mode 100644
index 0000000..5b61db3
--- /dev/null
+++ b/include/mbedcrypto/md4.h
@@ -0,0 +1,306 @@
+/**
+ * \file md4.h
+ *
+ * \brief MD4 message digest algorithm (hash function)
+ *
+ * \warning MD4 is considered a weak message digest and its use constitutes a
+ * security risk. We recommend considering stronger message digests
+ * instead.
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+#ifndef MBEDCRYPTO_MD4_H
+#define MBEDCRYPTO_MD4_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_MD4_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief MD4 context structure
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[4]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+}
+mbedcrypto_md4_context;
+
+#else /* MBEDCRYPTO_MD4_ALT */
+#include "md4_alt.h"
+#endif /* MBEDCRYPTO_MD4_ALT */
+
+/**
+ * \brief Initialize MD4 context
+ *
+ * \param ctx MD4 context to be initialized
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+void mbedcrypto_md4_init( mbedcrypto_md4_context *ctx );
+
+/**
+ * \brief Clear MD4 context
+ *
+ * \param ctx MD4 context to be cleared
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+void mbedcrypto_md4_free( mbedcrypto_md4_context *ctx );
+
+/**
+ * \brief Clone (the state of) an MD4 context
+ *
+ * \param dst The destination context
+ * \param src The context to be cloned
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+void mbedcrypto_md4_clone( mbedcrypto_md4_context *dst,
+ const mbedcrypto_md4_context *src );
+
+/**
+ * \brief MD4 context setup
+ *
+ * \param ctx context to be initialized
+ *
+ * \return 0 if successful
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ */
+int mbedcrypto_md4_starts_ret( mbedcrypto_md4_context *ctx );
+
+/**
+ * \brief MD4 process buffer
+ *
+ * \param ctx MD4 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \return 0 if successful
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md4_update_ret( mbedcrypto_md4_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief MD4 final digest
+ *
+ * \param ctx MD4 context
+ * \param output MD4 checksum result
+ *
+ * \return 0 if successful
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md4_finish_ret( mbedcrypto_md4_context *ctx,
+ unsigned char output[16] );
+
+/**
+ * \brief MD4 process data block (internal use only)
+ *
+ * \param ctx MD4 context
+ * \param data buffer holding one block of data
+ *
+ * \return 0 if successful
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_internal_md4_process( mbedcrypto_md4_context *ctx,
+ const unsigned char data[64] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief MD4 context setup
+ *
+ * \deprecated Superseded by mbedcrypto_md4_starts_ret() in 2.7.0
+ *
+ * \param ctx context to be initialized
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md4_starts( mbedcrypto_md4_context *ctx );
+
+/**
+ * \brief MD4 process buffer
+ *
+ * \deprecated Superseded by mbedcrypto_md4_update_ret() in 2.7.0
+ *
+ * \param ctx MD4 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md4_update( mbedcrypto_md4_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief MD4 final digest
+ *
+ * \deprecated Superseded by mbedcrypto_md4_finish_ret() in 2.7.0
+ *
+ * \param ctx MD4 context
+ * \param output MD4 checksum result
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md4_finish( mbedcrypto_md4_context *ctx,
+ unsigned char output[16] );
+
+/**
+ * \brief MD4 process data block (internal use only)
+ *
+ * \deprecated Superseded by mbedcrypto_internal_md4_process() in 2.7.0
+ *
+ * \param ctx MD4 context
+ * \param data buffer holding one block of data
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md4_process( mbedcrypto_md4_context *ctx,
+ const unsigned char data[64] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief Output = MD4( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD4 checksum result
+ *
+ * \return 0 if successful
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md4_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief Output = MD4( input buffer )
+ *
+ * \deprecated Superseded by mbedcrypto_md4_ret() in 2.7.0
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD4 checksum result
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md4( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ *
+ * \warning MD4 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md4_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_md4.h */
diff --git a/include/mbedcrypto/md5.h b/include/mbedcrypto/md5.h
new file mode 100644
index 0000000..8d24581
--- /dev/null
+++ b/include/mbedcrypto/md5.h
@@ -0,0 +1,306 @@
+/**
+ * \file md5.h
+ *
+ * \brief MD5 message digest algorithm (hash function)
+ *
+ * \warning MD5 is considered a weak message digest and its use constitutes a
+ * security risk. We recommend considering stronger message
+ * digests instead.
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_MD5_H
+#define MBEDCRYPTO_MD5_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_MD5_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief MD5 context structure
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[4]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+}
+mbedcrypto_md5_context;
+
+#else /* MBEDCRYPTO_MD5_ALT */
+#include "md5_alt.h"
+#endif /* MBEDCRYPTO_MD5_ALT */
+
+/**
+ * \brief Initialize MD5 context
+ *
+ * \param ctx MD5 context to be initialized
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+void mbedcrypto_md5_init( mbedcrypto_md5_context *ctx );
+
+/**
+ * \brief Clear MD5 context
+ *
+ * \param ctx MD5 context to be cleared
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+void mbedcrypto_md5_free( mbedcrypto_md5_context *ctx );
+
+/**
+ * \brief Clone (the state of) an MD5 context
+ *
+ * \param dst The destination context
+ * \param src The context to be cloned
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+void mbedcrypto_md5_clone( mbedcrypto_md5_context *dst,
+ const mbedcrypto_md5_context *src );
+
+/**
+ * \brief MD5 context setup
+ *
+ * \param ctx context to be initialized
+ *
+ * \return 0 if successful
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md5_starts_ret( mbedcrypto_md5_context *ctx );
+
+/**
+ * \brief MD5 process buffer
+ *
+ * \param ctx MD5 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \return 0 if successful
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md5_update_ret( mbedcrypto_md5_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief MD5 final digest
+ *
+ * \param ctx MD5 context
+ * \param output MD5 checksum result
+ *
+ * \return 0 if successful
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md5_finish_ret( mbedcrypto_md5_context *ctx,
+ unsigned char output[16] );
+
+/**
+ * \brief MD5 process data block (internal use only)
+ *
+ * \param ctx MD5 context
+ * \param data buffer holding one block of data
+ *
+ * \return 0 if successful
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_internal_md5_process( mbedcrypto_md5_context *ctx,
+ const unsigned char data[64] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief MD5 context setup
+ *
+ * \deprecated Superseded by mbedcrypto_md5_starts_ret() in 2.7.0
+ *
+ * \param ctx context to be initialized
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md5_starts( mbedcrypto_md5_context *ctx );
+
+/**
+ * \brief MD5 process buffer
+ *
+ * \deprecated Superseded by mbedcrypto_md5_update_ret() in 2.7.0
+ *
+ * \param ctx MD5 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md5_update( mbedcrypto_md5_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief MD5 final digest
+ *
+ * \deprecated Superseded by mbedcrypto_md5_finish_ret() in 2.7.0
+ *
+ * \param ctx MD5 context
+ * \param output MD5 checksum result
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md5_finish( mbedcrypto_md5_context *ctx,
+ unsigned char output[16] );
+
+/**
+ * \brief MD5 process data block (internal use only)
+ *
+ * \deprecated Superseded by mbedcrypto_internal_md5_process() in 2.7.0
+ *
+ * \param ctx MD5 context
+ * \param data buffer holding one block of data
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md5_process( mbedcrypto_md5_context *ctx,
+ const unsigned char data[64] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief Output = MD5( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD5 checksum result
+ *
+ * \return 0 if successful
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md5_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief Output = MD5( input buffer )
+ *
+ * \deprecated Superseded by mbedcrypto_md5_ret() in 2.7.0
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD5 checksum result
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_md5( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ *
+ * \warning MD5 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+int mbedcrypto_md5_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_md5.h */
diff --git a/include/mbedcrypto/md_internal.h b/include/mbedcrypto/md_internal.h
new file mode 100644
index 0000000..bc151e9
--- /dev/null
+++ b/include/mbedcrypto/md_internal.h
@@ -0,0 +1,115 @@
+/**
+ * \file md_internal.h
+ *
+ * \brief Message digest wrappers.
+ *
+ * \warning This in an internal header. Do not include directly.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_MD_WRAP_H
+#define MBEDCRYPTO_MD_WRAP_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Message digest information.
+ * Allows message digest functions to be called in a generic way.
+ */
+struct mbedcrypto_md_info_t
+{
+ /** Digest identifier */
+ mbedcrypto_md_type_t type;
+
+ /** Name of the message digest */
+ const char * name;
+
+ /** Output length of the digest function in bytes */
+ int size;
+
+ /** Block length of the digest function in bytes */
+ int block_size;
+
+ /** Digest initialisation function */
+ int (*starts_func)( void *ctx );
+
+ /** Digest update function */
+ int (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
+
+ /** Digest finalisation function */
+ int (*finish_func)( void *ctx, unsigned char *output );
+
+ /** Generic digest function */
+ int (*digest_func)( const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+ /** Allocate a new context */
+ void * (*ctx_alloc_func)( void );
+
+ /** Free the given context */
+ void (*ctx_free_func)( void *ctx );
+
+ /** Clone state from a context */
+ void (*clone_func)( void *dst, const void *src );
+
+ /** Internal use only */
+ int (*process_func)( void *ctx, const unsigned char *input );
+};
+
+#if defined(MBEDCRYPTO_MD2_C)
+extern const mbedcrypto_md_info_t mbedcrypto_md2_info;
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+extern const mbedcrypto_md_info_t mbedcrypto_md4_info;
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+extern const mbedcrypto_md_info_t mbedcrypto_md5_info;
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+extern const mbedcrypto_md_info_t mbedcrypto_ripemd160_info;
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+extern const mbedcrypto_md_info_t mbedcrypto_sha1_info;
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+extern const mbedcrypto_md_info_t mbedcrypto_sha224_info;
+extern const mbedcrypto_md_info_t mbedcrypto_sha256_info;
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+extern const mbedcrypto_md_info_t mbedcrypto_sha384_info;
+extern const mbedcrypto_md_info_t mbedcrypto_sha512_info;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_MD_WRAP_H */
diff --git a/include/mbedcrypto/oid.h b/include/mbedcrypto/oid.h
new file mode 100644
index 0000000..d162b10
--- /dev/null
+++ b/include/mbedcrypto/oid.h
@@ -0,0 +1,589 @@
+/**
+ * \file oid.h
+ *
+ * \brief Object Identifier (OID) database
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_OID_H
+#define MBEDCRYPTO_OID_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "asn1.h"
+#include "pk.h"
+
+#include <stddef.h>
+
+#if defined(MBEDCRYPTO_CIPHER_C)
+#include "cipher.h"
+#endif
+
+#if defined(MBEDCRYPTO_MD_C)
+#include "md.h"
+#endif
+
+#if defined(MBEDCRYPTO_X509_USE_C) || defined(MBEDCRYPTO_X509_CREATE_C)
+#include "x509.h"
+#endif
+
+#define MBEDCRYPTO_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */
+#define MBEDCRYPTO_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */
+
+/*
+ * Top level OID tuples
+ */
+#define MBEDCRYPTO_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */
+#define MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */
+#define MBEDCRYPTO_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */
+#define MBEDCRYPTO_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */
+
+/*
+ * ISO Member bodies OID parts
+ */
+#define MBEDCRYPTO_OID_COUNTRY_US "\x86\x48" /* {us(840)} */
+#define MBEDCRYPTO_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */
+#define MBEDCRYPTO_OID_RSA_COMPANY MBEDCRYPTO_OID_ISO_MEMBER_BODIES MBEDCRYPTO_OID_COUNTRY_US \
+ MBEDCRYPTO_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */
+#define MBEDCRYPTO_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */
+#define MBEDCRYPTO_OID_ANSI_X9_62 MBEDCRYPTO_OID_ISO_MEMBER_BODIES MBEDCRYPTO_OID_COUNTRY_US \
+ MBEDCRYPTO_OID_ORG_ANSI_X9_62
+
+/*
+ * ISO Identified organization OID parts
+ */
+#define MBEDCRYPTO_OID_ORG_DOD "\x06" /* {dod(6)} */
+#define MBEDCRYPTO_OID_ORG_OIW "\x0e"
+#define MBEDCRYPTO_OID_OIW_SECSIG MBEDCRYPTO_OID_ORG_OIW "\x03"
+#define MBEDCRYPTO_OID_OIW_SECSIG_ALG MBEDCRYPTO_OID_OIW_SECSIG "\x02"
+#define MBEDCRYPTO_OID_OIW_SECSIG_SHA1 MBEDCRYPTO_OID_OIW_SECSIG_ALG "\x1a"
+#define MBEDCRYPTO_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */
+#define MBEDCRYPTO_OID_CERTICOM MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG MBEDCRYPTO_OID_ORG_CERTICOM
+#define MBEDCRYPTO_OID_ORG_TELETRUST "\x24" /* teletrust(36) */
+#define MBEDCRYPTO_OID_TELETRUST MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG MBEDCRYPTO_OID_ORG_TELETRUST
+
+/*
+ * ISO ITU OID parts
+ */
+#define MBEDCRYPTO_OID_ORGANIZATION "\x01" /* {organization(1)} */
+#define MBEDCRYPTO_OID_ISO_ITU_US_ORG MBEDCRYPTO_OID_ISO_ITU_COUNTRY MBEDCRYPTO_OID_COUNTRY_US MBEDCRYPTO_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */
+
+#define MBEDCRYPTO_OID_ORG_GOV "\x65" /* {gov(101)} */
+#define MBEDCRYPTO_OID_GOV MBEDCRYPTO_OID_ISO_ITU_US_ORG MBEDCRYPTO_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */
+
+#define MBEDCRYPTO_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */
+#define MBEDCRYPTO_OID_NETSCAPE MBEDCRYPTO_OID_ISO_ITU_US_ORG MBEDCRYPTO_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */
+
+/* ISO arc for standard certificate and CRL extensions */
+#define MBEDCRYPTO_OID_ID_CE MBEDCRYPTO_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */
+
+/**
+ * Private Internet Extensions
+ * { iso(1) identified-organization(3) dod(6) internet(1)
+ * security(5) mechanisms(5) pkix(7) }
+ */
+#define MBEDCRYPTO_OID_PKIX MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG MBEDCRYPTO_OID_ORG_DOD "\x01\x05\x05\x07"
+
+/*
+ * Arc for standard naming attributes
+ */
+#define MBEDCRYPTO_OID_AT MBEDCRYPTO_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */
+#define MBEDCRYPTO_OID_AT_CN MBEDCRYPTO_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */
+#define MBEDCRYPTO_OID_AT_SUR_NAME MBEDCRYPTO_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */
+#define MBEDCRYPTO_OID_AT_SERIAL_NUMBER MBEDCRYPTO_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */
+#define MBEDCRYPTO_OID_AT_COUNTRY MBEDCRYPTO_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */
+#define MBEDCRYPTO_OID_AT_LOCALITY MBEDCRYPTO_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */
+#define MBEDCRYPTO_OID_AT_STATE MBEDCRYPTO_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */
+#define MBEDCRYPTO_OID_AT_ORGANIZATION MBEDCRYPTO_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */
+#define MBEDCRYPTO_OID_AT_ORG_UNIT MBEDCRYPTO_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */
+#define MBEDCRYPTO_OID_AT_TITLE MBEDCRYPTO_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */
+#define MBEDCRYPTO_OID_AT_POSTAL_ADDRESS MBEDCRYPTO_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */
+#define MBEDCRYPTO_OID_AT_POSTAL_CODE MBEDCRYPTO_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */
+#define MBEDCRYPTO_OID_AT_GIVEN_NAME MBEDCRYPTO_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */
+#define MBEDCRYPTO_OID_AT_INITIALS MBEDCRYPTO_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */
+#define MBEDCRYPTO_OID_AT_GENERATION_QUALIFIER MBEDCRYPTO_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */
+#define MBEDCRYPTO_OID_AT_UNIQUE_IDENTIFIER MBEDCRYPTO_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */
+#define MBEDCRYPTO_OID_AT_DN_QUALIFIER MBEDCRYPTO_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */
+#define MBEDCRYPTO_OID_AT_PSEUDONYM MBEDCRYPTO_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */
+
+#define MBEDCRYPTO_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */
+
+/*
+ * OIDs for standard certificate extensions
+ */
+#define MBEDCRYPTO_OID_AUTHORITY_KEY_IDENTIFIER MBEDCRYPTO_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */
+#define MBEDCRYPTO_OID_SUBJECT_KEY_IDENTIFIER MBEDCRYPTO_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */
+#define MBEDCRYPTO_OID_KEY_USAGE MBEDCRYPTO_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */
+#define MBEDCRYPTO_OID_CERTIFICATE_POLICIES MBEDCRYPTO_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */
+#define MBEDCRYPTO_OID_POLICY_MAPPINGS MBEDCRYPTO_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */
+#define MBEDCRYPTO_OID_SUBJECT_ALT_NAME MBEDCRYPTO_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */
+#define MBEDCRYPTO_OID_ISSUER_ALT_NAME MBEDCRYPTO_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */
+#define MBEDCRYPTO_OID_SUBJECT_DIRECTORY_ATTRS MBEDCRYPTO_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */
+#define MBEDCRYPTO_OID_BASIC_CONSTRAINTS MBEDCRYPTO_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */
+#define MBEDCRYPTO_OID_NAME_CONSTRAINTS MBEDCRYPTO_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */
+#define MBEDCRYPTO_OID_POLICY_CONSTRAINTS MBEDCRYPTO_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */
+#define MBEDCRYPTO_OID_EXTENDED_KEY_USAGE MBEDCRYPTO_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */
+#define MBEDCRYPTO_OID_CRL_DISTRIBUTION_POINTS MBEDCRYPTO_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */
+#define MBEDCRYPTO_OID_INIHIBIT_ANYPOLICY MBEDCRYPTO_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */
+#define MBEDCRYPTO_OID_FRESHEST_CRL MBEDCRYPTO_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */
+
+/*
+ * Netscape certificate extensions
+ */
+#define MBEDCRYPTO_OID_NS_CERT MBEDCRYPTO_OID_NETSCAPE "\x01"
+#define MBEDCRYPTO_OID_NS_CERT_TYPE MBEDCRYPTO_OID_NS_CERT "\x01"
+#define MBEDCRYPTO_OID_NS_BASE_URL MBEDCRYPTO_OID_NS_CERT "\x02"
+#define MBEDCRYPTO_OID_NS_REVOCATION_URL MBEDCRYPTO_OID_NS_CERT "\x03"
+#define MBEDCRYPTO_OID_NS_CA_REVOCATION_URL MBEDCRYPTO_OID_NS_CERT "\x04"
+#define MBEDCRYPTO_OID_NS_RENEWAL_URL MBEDCRYPTO_OID_NS_CERT "\x07"
+#define MBEDCRYPTO_OID_NS_CA_POLICY_URL MBEDCRYPTO_OID_NS_CERT "\x08"
+#define MBEDCRYPTO_OID_NS_SSL_SERVER_NAME MBEDCRYPTO_OID_NS_CERT "\x0C"
+#define MBEDCRYPTO_OID_NS_COMMENT MBEDCRYPTO_OID_NS_CERT "\x0D"
+#define MBEDCRYPTO_OID_NS_DATA_TYPE MBEDCRYPTO_OID_NETSCAPE "\x02"
+#define MBEDCRYPTO_OID_NS_CERT_SEQUENCE MBEDCRYPTO_OID_NS_DATA_TYPE "\x05"
+
+/*
+ * OIDs for CRL extensions
+ */
+#define MBEDCRYPTO_OID_PRIVATE_KEY_USAGE_PERIOD MBEDCRYPTO_OID_ID_CE "\x10"
+#define MBEDCRYPTO_OID_CRL_NUMBER MBEDCRYPTO_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */
+
+/*
+ * X.509 v3 Extended key usage OIDs
+ */
+#define MBEDCRYPTO_OID_ANY_EXTENDED_KEY_USAGE MBEDCRYPTO_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */
+
+#define MBEDCRYPTO_OID_KP MBEDCRYPTO_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */
+#define MBEDCRYPTO_OID_SERVER_AUTH MBEDCRYPTO_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */
+#define MBEDCRYPTO_OID_CLIENT_AUTH MBEDCRYPTO_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */
+#define MBEDCRYPTO_OID_CODE_SIGNING MBEDCRYPTO_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */
+#define MBEDCRYPTO_OID_EMAIL_PROTECTION MBEDCRYPTO_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */
+#define MBEDCRYPTO_OID_TIME_STAMPING MBEDCRYPTO_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */
+#define MBEDCRYPTO_OID_OCSP_SIGNING MBEDCRYPTO_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */
+
+/*
+ * PKCS definition OIDs
+ */
+
+#define MBEDCRYPTO_OID_PKCS MBEDCRYPTO_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */
+#define MBEDCRYPTO_OID_PKCS1 MBEDCRYPTO_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */
+#define MBEDCRYPTO_OID_PKCS5 MBEDCRYPTO_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */
+#define MBEDCRYPTO_OID_PKCS9 MBEDCRYPTO_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */
+#define MBEDCRYPTO_OID_PKCS12 MBEDCRYPTO_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */
+
+/*
+ * PKCS#1 OIDs
+ */
+#define MBEDCRYPTO_OID_PKCS1_RSA MBEDCRYPTO_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */
+#define MBEDCRYPTO_OID_PKCS1_MD2 MBEDCRYPTO_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */
+#define MBEDCRYPTO_OID_PKCS1_MD4 MBEDCRYPTO_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */
+#define MBEDCRYPTO_OID_PKCS1_MD5 MBEDCRYPTO_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */
+#define MBEDCRYPTO_OID_PKCS1_SHA1 MBEDCRYPTO_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */
+#define MBEDCRYPTO_OID_PKCS1_SHA224 MBEDCRYPTO_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */
+#define MBEDCRYPTO_OID_PKCS1_SHA256 MBEDCRYPTO_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */
+#define MBEDCRYPTO_OID_PKCS1_SHA384 MBEDCRYPTO_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */
+#define MBEDCRYPTO_OID_PKCS1_SHA512 MBEDCRYPTO_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */
+
+#define MBEDCRYPTO_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D"
+
+#define MBEDCRYPTO_OID_PKCS9_EMAIL MBEDCRYPTO_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */
+
+/* RFC 4055 */
+#define MBEDCRYPTO_OID_RSASSA_PSS MBEDCRYPTO_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */
+#define MBEDCRYPTO_OID_MGF1 MBEDCRYPTO_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */
+
+/*
+ * Digest algorithms
+ */
+#define MBEDCRYPTO_OID_DIGEST_ALG_MD2 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x02" /**< id-mbedcrypto_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */
+#define MBEDCRYPTO_OID_DIGEST_ALG_MD4 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x04" /**< id-mbedcrypto_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */
+#define MBEDCRYPTO_OID_DIGEST_ALG_MD5 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x05" /**< id-mbedcrypto_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */
+#define MBEDCRYPTO_OID_DIGEST_ALG_SHA1 MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG MBEDCRYPTO_OID_OIW_SECSIG_SHA1 /**< id-mbedcrypto_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */
+#define MBEDCRYPTO_OID_DIGEST_ALG_SHA224 MBEDCRYPTO_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */
+#define MBEDCRYPTO_OID_DIGEST_ALG_SHA256 MBEDCRYPTO_OID_GOV "\x03\x04\x02\x01" /**< id-mbedcrypto_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */
+
+#define MBEDCRYPTO_OID_DIGEST_ALG_SHA384 MBEDCRYPTO_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */
+
+#define MBEDCRYPTO_OID_DIGEST_ALG_SHA512 MBEDCRYPTO_OID_GOV "\x03\x04\x02\x03" /**< id-mbedcrypto_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
+
+#define MBEDCRYPTO_OID_HMAC_SHA1 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */
+
+#define MBEDCRYPTO_OID_HMAC_SHA224 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */
+
+#define MBEDCRYPTO_OID_HMAC_SHA256 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */
+
+#define MBEDCRYPTO_OID_HMAC_SHA384 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */
+
+#define MBEDCRYPTO_OID_HMAC_SHA512 MBEDCRYPTO_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */
+
+/*
+ * Encryption algorithms
+ */
+#define MBEDCRYPTO_OID_DES_CBC MBEDCRYPTO_OID_ISO_IDENTIFIED_ORG MBEDCRYPTO_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */
+#define MBEDCRYPTO_OID_DES_EDE3_CBC MBEDCRYPTO_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */
+
+/*
+ * PKCS#5 OIDs
+ */
+#define MBEDCRYPTO_OID_PKCS5_PBKDF2 MBEDCRYPTO_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */
+#define MBEDCRYPTO_OID_PKCS5_PBES2 MBEDCRYPTO_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */
+#define MBEDCRYPTO_OID_PKCS5_PBMAC1 MBEDCRYPTO_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */
+
+/*
+ * PKCS#5 PBES1 algorithms
+ */
+#define MBEDCRYPTO_OID_PKCS5_PBE_MD2_DES_CBC MBEDCRYPTO_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */
+#define MBEDCRYPTO_OID_PKCS5_PBE_MD2_RC2_CBC MBEDCRYPTO_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */
+#define MBEDCRYPTO_OID_PKCS5_PBE_MD5_DES_CBC MBEDCRYPTO_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */
+#define MBEDCRYPTO_OID_PKCS5_PBE_MD5_RC2_CBC MBEDCRYPTO_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */
+#define MBEDCRYPTO_OID_PKCS5_PBE_SHA1_DES_CBC MBEDCRYPTO_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */
+#define MBEDCRYPTO_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDCRYPTO_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */
+
+/*
+ * PKCS#8 OIDs
+ */
+#define MBEDCRYPTO_OID_PKCS9_CSR_EXT_REQ MBEDCRYPTO_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */
+
+/*
+ * PKCS#12 PBE OIDs
+ */
+#define MBEDCRYPTO_OID_PKCS12_PBE MBEDCRYPTO_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */
+
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_RC4_128 MBEDCRYPTO_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_RC4_40 MBEDCRYPTO_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDCRYPTO_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDCRYPTO_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDCRYPTO_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */
+#define MBEDCRYPTO_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDCRYPTO_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */
+
+/*
+ * EC key algorithms from RFC 5480
+ */
+
+/* id-ecPublicKey OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */
+#define MBEDCRYPTO_OID_EC_ALG_UNRESTRICTED MBEDCRYPTO_OID_ANSI_X9_62 "\x02\01"
+
+/* id-ecDH OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132)
+ * schemes(1) ecdh(12) } */
+#define MBEDCRYPTO_OID_EC_ALG_ECDH MBEDCRYPTO_OID_CERTICOM "\x01\x0c"
+
+/*
+ * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2
+ */
+
+/* secp192r1 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP192R1 MBEDCRYPTO_OID_ANSI_X9_62 "\x03\x01\x01"
+
+/* secp224r1 OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP224R1 MBEDCRYPTO_OID_CERTICOM "\x00\x21"
+
+/* secp256r1 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP256R1 MBEDCRYPTO_OID_ANSI_X9_62 "\x03\x01\x07"
+
+/* secp384r1 OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP384R1 MBEDCRYPTO_OID_CERTICOM "\x00\x22"
+
+/* secp521r1 OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP521R1 MBEDCRYPTO_OID_CERTICOM "\x00\x23"
+
+/* secp192k1 OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP192K1 MBEDCRYPTO_OID_CERTICOM "\x00\x1f"
+
+/* secp224k1 OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP224K1 MBEDCRYPTO_OID_CERTICOM "\x00\x20"
+
+/* secp256k1 OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */
+#define MBEDCRYPTO_OID_EC_GRP_SECP256K1 MBEDCRYPTO_OID_CERTICOM "\x00\x0a"
+
+/* RFC 5639 4.1
+ * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1)
+ * identified-organization(3) teletrust(36) algorithm(3) signature-
+ * algorithm(3) ecSign(2) 8}
+ * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1}
+ * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */
+#define MBEDCRYPTO_OID_EC_BRAINPOOL_V1 MBEDCRYPTO_OID_TELETRUST "\x03\x03\x02\x08\x01\x01"
+
+/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */
+#define MBEDCRYPTO_OID_EC_GRP_BP256R1 MBEDCRYPTO_OID_EC_BRAINPOOL_V1 "\x07"
+
+/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */
+#define MBEDCRYPTO_OID_EC_GRP_BP384R1 MBEDCRYPTO_OID_EC_BRAINPOOL_V1 "\x0B"
+
+/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */
+#define MBEDCRYPTO_OID_EC_GRP_BP512R1 MBEDCRYPTO_OID_EC_BRAINPOOL_V1 "\x0D"
+
+/*
+ * SEC1 C.1
+ *
+ * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
+ * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)}
+ */
+#define MBEDCRYPTO_OID_ANSI_X9_62_FIELD_TYPE MBEDCRYPTO_OID_ANSI_X9_62 "\x01"
+#define MBEDCRYPTO_OID_ANSI_X9_62_PRIME_FIELD MBEDCRYPTO_OID_ANSI_X9_62_FIELD_TYPE "\x01"
+
+/*
+ * ECDSA signature identifiers, from RFC 5480
+ */
+#define MBEDCRYPTO_OID_ANSI_X9_62_SIG MBEDCRYPTO_OID_ANSI_X9_62 "\x04" /* signatures(4) */
+#define MBEDCRYPTO_OID_ANSI_X9_62_SIG_SHA2 MBEDCRYPTO_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */
+
+/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */
+#define MBEDCRYPTO_OID_ECDSA_SHA1 MBEDCRYPTO_OID_ANSI_X9_62_SIG "\x01"
+
+/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ * ecdsa-with-SHA2(3) 1 } */
+#define MBEDCRYPTO_OID_ECDSA_SHA224 MBEDCRYPTO_OID_ANSI_X9_62_SIG_SHA2 "\x01"
+
+/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ * ecdsa-with-SHA2(3) 2 } */
+#define MBEDCRYPTO_OID_ECDSA_SHA256 MBEDCRYPTO_OID_ANSI_X9_62_SIG_SHA2 "\x02"
+
+/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ * ecdsa-with-SHA2(3) 3 } */
+#define MBEDCRYPTO_OID_ECDSA_SHA384 MBEDCRYPTO_OID_ANSI_X9_62_SIG_SHA2 "\x03"
+
+/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= {
+ * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ * ecdsa-with-SHA2(3) 4 } */
+#define MBEDCRYPTO_OID_ECDSA_SHA512 MBEDCRYPTO_OID_ANSI_X9_62_SIG_SHA2 "\x04"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Base OID descriptor structure
+ */
+typedef struct {
+ const char *asn1; /*!< OID ASN.1 representation */
+ size_t asn1_len; /*!< length of asn1 */
+ const char *name; /*!< official name (e.g. from RFC) */
+ const char *description; /*!< human friendly description */
+} mbedcrypto_oid_descriptor_t;
+
+/**
+ * \brief Translate an ASN.1 OID into its numeric representation
+ * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549")
+ *
+ * \param buf buffer to put representation in
+ * \param size size of the buffer
+ * \param oid OID to translate
+ *
+ * \return Length of the string written (excluding final NULL) or
+ * MBEDCRYPTO_ERR_OID_BUF_TOO_SMALL in case of error
+ */
+int mbedcrypto_oid_get_numeric_string( char *buf, size_t size, const mbedcrypto_asn1_buf *oid );
+
+#if defined(MBEDCRYPTO_X509_USE_C) || defined(MBEDCRYPTO_X509_CREATE_C)
+/**
+ * \brief Translate an X.509 extension OID into local values
+ *
+ * \param oid OID to use
+ * \param ext_type place to store the extension type
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_x509_ext_type( const mbedcrypto_asn1_buf *oid, int *ext_type );
+#endif
+
+/**
+ * \brief Translate an X.509 attribute type OID into the short name
+ * (e.g. the OID for an X520 Common Name into "CN")
+ *
+ * \param oid OID to use
+ * \param short_name place to store the string pointer
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_attr_short_name( const mbedcrypto_asn1_buf *oid, const char **short_name );
+
+/**
+ * \brief Translate PublicKeyAlgorithm OID into pk_type
+ *
+ * \param oid OID to use
+ * \param pk_alg place to store public key algorithm
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_pk_alg( const mbedcrypto_asn1_buf *oid, mbedcrypto_pk_type_t *pk_alg );
+
+/**
+ * \brief Translate pk_type into PublicKeyAlgorithm OID
+ *
+ * \param pk_alg Public key type to look for
+ * \param oid place to store ASN.1 OID string pointer
+ * \param olen length of the OID
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_oid_by_pk_alg( mbedcrypto_pk_type_t pk_alg,
+ const char **oid, size_t *olen );
+
+#if defined(MBEDCRYPTO_ECP_C)
+/**
+ * \brief Translate NamedCurve OID into an EC group identifier
+ *
+ * \param oid OID to use
+ * \param grp_id place to store group id
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_ec_grp( const mbedcrypto_asn1_buf *oid, mbedcrypto_ecp_group_id *grp_id );
+
+/**
+ * \brief Translate EC group identifier into NamedCurve OID
+ *
+ * \param grp_id EC group identifier
+ * \param oid place to store ASN.1 OID string pointer
+ * \param olen length of the OID
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_oid_by_ec_grp( mbedcrypto_ecp_group_id grp_id,
+ const char **oid, size_t *olen );
+#endif /* MBEDCRYPTO_ECP_C */
+
+#if defined(MBEDCRYPTO_MD_C)
+/**
+ * \brief Translate SignatureAlgorithm OID into md_type and pk_type
+ *
+ * \param oid OID to use
+ * \param md_alg place to store message digest algorithm
+ * \param pk_alg place to store public key algorithm
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_sig_alg( const mbedcrypto_asn1_buf *oid,
+ mbedcrypto_md_type_t *md_alg, mbedcrypto_pk_type_t *pk_alg );
+
+/**
+ * \brief Translate SignatureAlgorithm OID into description
+ *
+ * \param oid OID to use
+ * \param desc place to store string pointer
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_sig_alg_desc( const mbedcrypto_asn1_buf *oid, const char **desc );
+
+/**
+ * \brief Translate md_type and pk_type into SignatureAlgorithm OID
+ *
+ * \param md_alg message digest algorithm
+ * \param pk_alg public key algorithm
+ * \param oid place to store ASN.1 OID string pointer
+ * \param olen length of the OID
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_oid_by_sig_alg( mbedcrypto_pk_type_t pk_alg, mbedcrypto_md_type_t md_alg,
+ const char **oid, size_t *olen );
+
+/**
+ * \brief Translate hash algorithm OID into md_type
+ *
+ * \param oid OID to use
+ * \param md_alg place to store message digest algorithm
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_md_alg( const mbedcrypto_asn1_buf *oid, mbedcrypto_md_type_t *md_alg );
+
+/**
+ * \brief Translate hmac algorithm OID into md_type
+ *
+ * \param oid OID to use
+ * \param md_hmac place to store message hmac algorithm
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_md_hmac( const mbedcrypto_asn1_buf *oid, mbedcrypto_md_type_t *md_hmac );
+#endif /* MBEDCRYPTO_MD_C */
+
+/**
+ * \brief Translate Extended Key Usage OID into description
+ *
+ * \param oid OID to use
+ * \param desc place to store string pointer
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_extended_key_usage( const mbedcrypto_asn1_buf *oid, const char **desc );
+
+/**
+ * \brief Translate md_type into hash algorithm OID
+ *
+ * \param md_alg message digest algorithm
+ * \param oid place to store ASN.1 OID string pointer
+ * \param olen length of the OID
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_oid_by_md( mbedcrypto_md_type_t md_alg, const char **oid, size_t *olen );
+
+#if defined(MBEDCRYPTO_CIPHER_C)
+/**
+ * \brief Translate encryption algorithm OID into cipher_type
+ *
+ * \param oid OID to use
+ * \param cipher_alg place to store cipher algorithm
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_cipher_alg( const mbedcrypto_asn1_buf *oid, mbedcrypto_cipher_type_t *cipher_alg );
+#endif /* MBEDCRYPTO_CIPHER_C */
+
+#if defined(MBEDCRYPTO_PKCS12_C)
+/**
+ * \brief Translate PKCS#12 PBE algorithm OID into md_type and
+ * cipher_type
+ *
+ * \param oid OID to use
+ * \param md_alg place to store message digest algorithm
+ * \param cipher_alg place to store cipher algorithm
+ *
+ * \return 0 if successful, or MBEDCRYPTO_ERR_OID_NOT_FOUND
+ */
+int mbedcrypto_oid_get_pkcs12_pbe_alg( const mbedcrypto_asn1_buf *oid, mbedcrypto_md_type_t *md_alg,
+ mbedcrypto_cipher_type_t *cipher_alg );
+#endif /* MBEDCRYPTO_PKCS12_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* oid.h */
diff --git a/include/mbedcrypto/pem.h b/include/mbedcrypto/pem.h
new file mode 100644
index 0000000..e742eea
--- /dev/null
+++ b/include/mbedcrypto/pem.h
@@ -0,0 +1,130 @@
+/**
+ * \file pem.h
+ *
+ * \brief Privacy Enhanced Mail (PEM) decoding
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PEM_H
+#define MBEDCRYPTO_PEM_H
+
+#include <stddef.h>
+
+/**
+ * \name PEM Error codes
+ * These error codes are returned in case of errors reading the
+ * PEM data.
+ * \{
+ */
+#define MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */
+#define MBEDCRYPTO_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */
+#define MBEDCRYPTO_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */
+#define MBEDCRYPTO_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */
+#define MBEDCRYPTO_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */
+#define MBEDCRYPTO_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */
+#define MBEDCRYPTO_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */
+#define MBEDCRYPTO_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */
+#define MBEDCRYPTO_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */
+/* \} name */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(MBEDCRYPTO_PEM_PARSE_C)
+/**
+ * \brief PEM context structure
+ */
+typedef struct
+{
+ unsigned char *buf; /*!< buffer for decoded data */
+ size_t buflen; /*!< length of the buffer */
+ unsigned char *info; /*!< buffer for extra header information */
+}
+mbedcrypto_pem_context;
+
+/**
+ * \brief PEM context setup
+ *
+ * \param ctx context to be initialized
+ */
+void mbedcrypto_pem_init( mbedcrypto_pem_context *ctx );
+
+/**
+ * \brief Read a buffer for PEM information and store the resulting
+ * data into the specified context buffers.
+ *
+ * \param ctx context to use
+ * \param header header string to seek and expect
+ * \param footer footer string to seek and expect
+ * \param data source data to look in (must be nul-terminated)
+ * \param pwd password for decryption (can be NULL)
+ * \param pwdlen length of password
+ * \param use_len destination for total length used (set after header is
+ * correctly read, so unless you get
+ * MBEDCRYPTO_ERR_PEM_BAD_INPUT_DATA or
+ * MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is
+ * the length to skip)
+ *
+ * \note Attempts to check password correctness by verifying if
+ * the decrypted text starts with an ASN.1 sequence of
+ * appropriate length
+ *
+ * \return 0 on success, or a specific PEM error code
+ */
+int mbedcrypto_pem_read_buffer( mbedcrypto_pem_context *ctx, const char *header, const char *footer,
+ const unsigned char *data,
+ const unsigned char *pwd,
+ size_t pwdlen, size_t *use_len );
+
+/**
+ * \brief PEM context memory freeing
+ *
+ * \param ctx context to be freed
+ */
+void mbedcrypto_pem_free( mbedcrypto_pem_context *ctx );
+#endif /* MBEDCRYPTO_PEM_PARSE_C */
+
+#if defined(MBEDCRYPTO_PEM_WRITE_C)
+/**
+ * \brief Write a buffer of PEM information from a DER encoded
+ * buffer.
+ *
+ * \param header header string to write
+ * \param footer footer string to write
+ * \param der_data DER data to write
+ * \param der_len length of the DER data
+ * \param buf buffer to write to
+ * \param buf_len length of output buffer
+ * \param olen total length written / required (if buf_len is not enough)
+ *
+ * \return 0 on success, or a specific PEM or BASE64 error code. On
+ * MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL olen is the required
+ * size.
+ */
+int mbedcrypto_pem_write_buffer( const char *header, const char *footer,
+ const unsigned char *der_data, size_t der_len,
+ unsigned char *buf, size_t buf_len, size_t *olen );
+#endif /* MBEDCRYPTO_PEM_WRITE_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pem.h */
diff --git a/include/mbedcrypto/pk.h b/include/mbedcrypto/pk.h
new file mode 100644
index 0000000..469b96c
--- /dev/null
+++ b/include/mbedcrypto/pk.h
@@ -0,0 +1,618 @@
+/**
+ * \file pk.h
+ *
+ * \brief Public Key abstraction layer
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_PK_H
+#define MBEDCRYPTO_PK_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "md.h"
+
+#if defined(MBEDCRYPTO_RSA_C)
+#include "rsa.h"
+#endif
+
+#if defined(MBEDCRYPTO_ECP_C)
+#include "ecp.h"
+#endif
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+#include "ecdsa.h"
+#endif
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#define MBEDCRYPTO_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */
+#define MBEDCRYPTO_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */
+#define MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */
+#define MBEDCRYPTO_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */
+#define MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */
+#define MBEDCRYPTO_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */
+#define MBEDCRYPTO_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */
+#define MBEDCRYPTO_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */
+#define MBEDCRYPTO_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */
+#define MBEDCRYPTO_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */
+#define MBEDCRYPTO_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */
+#define MBEDCRYPTO_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */
+#define MBEDCRYPTO_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */
+#define MBEDCRYPTO_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Public key types
+ */
+typedef enum {
+ MBEDCRYPTO_PK_NONE=0,
+ MBEDCRYPTO_PK_RSA,
+ MBEDCRYPTO_PK_ECKEY,
+ MBEDCRYPTO_PK_ECKEY_DH,
+ MBEDCRYPTO_PK_ECDSA,
+ MBEDCRYPTO_PK_RSA_ALT,
+ MBEDCRYPTO_PK_RSASSA_PSS,
+} mbedcrypto_pk_type_t;
+
+/**
+ * \brief Options for RSASSA-PSS signature verification.
+ * See \c mbedcrypto_rsa_rsassa_pss_verify_ext()
+ */
+typedef struct
+{
+ mbedcrypto_md_type_t mgf1_hash_id;
+ int expected_salt_len;
+
+} mbedcrypto_pk_rsassa_pss_options;
+
+/**
+ * \brief Types for interfacing with the debug module
+ */
+typedef enum
+{
+ MBEDCRYPTO_PK_DEBUG_NONE = 0,
+ MBEDCRYPTO_PK_DEBUG_MPI,
+ MBEDCRYPTO_PK_DEBUG_ECP,
+} mbedcrypto_pk_debug_type;
+
+/**
+ * \brief Item to send to the debug module
+ */
+typedef struct
+{
+ mbedcrypto_pk_debug_type type;
+ const char *name;
+ void *value;
+} mbedcrypto_pk_debug_item;
+
+/** Maximum number of item send for debugging, plus 1 */
+#define MBEDCRYPTO_PK_DEBUG_MAX_ITEMS 3
+
+/**
+ * \brief Public key information and operations
+ */
+typedef struct mbedcrypto_pk_info_t mbedcrypto_pk_info_t;
+
+/**
+ * \brief Public key container
+ */
+typedef struct
+{
+ const mbedcrypto_pk_info_t * pk_info; /**< Public key informations */
+ void * pk_ctx; /**< Underlying public key context */
+} mbedcrypto_pk_context;
+
+#if defined(MBEDCRYPTO_RSA_C)
+/**
+ * Quick access to an RSA context inside a PK context.
+ *
+ * \warning You must make sure the PK context actually holds an RSA context
+ * before using this function!
+ */
+static inline mbedcrypto_rsa_context *mbedcrypto_pk_rsa( const mbedcrypto_pk_context pk )
+{
+ return( (mbedcrypto_rsa_context *) (pk).pk_ctx );
+}
+#endif /* MBEDCRYPTO_RSA_C */
+
+#if defined(MBEDCRYPTO_ECP_C)
+/**
+ * Quick access to an EC context inside a PK context.
+ *
+ * \warning You must make sure the PK context actually holds an EC context
+ * before using this function!
+ */
+static inline mbedcrypto_ecp_keypair *mbedcrypto_pk_ec( const mbedcrypto_pk_context pk )
+{
+ return( (mbedcrypto_ecp_keypair *) (pk).pk_ctx );
+}
+#endif /* MBEDCRYPTO_ECP_C */
+
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+/**
+ * \brief Types for RSA-alt abstraction
+ */
+typedef int (*mbedcrypto_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen,
+ const unsigned char *input, unsigned char *output,
+ size_t output_max_len );
+typedef int (*mbedcrypto_pk_rsa_alt_sign_func)( void *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ int mode, mbedcrypto_md_type_t md_alg, unsigned int hashlen,
+ const unsigned char *hash, unsigned char *sig );
+typedef size_t (*mbedcrypto_pk_rsa_alt_key_len_func)( void *ctx );
+#endif /* MBEDCRYPTO_PK_RSA_ALT_SUPPORT */
+
+/**
+ * \brief Return information associated with the given PK type
+ *
+ * \param pk_type PK type to search for.
+ *
+ * \return The PK info associated with the type or NULL if not found.
+ */
+const mbedcrypto_pk_info_t *mbedcrypto_pk_info_from_type( mbedcrypto_pk_type_t pk_type );
+
+/**
+ * \brief Initialize a mbedcrypto_pk_context (as NONE)
+ */
+void mbedcrypto_pk_init( mbedcrypto_pk_context *ctx );
+
+/**
+ * \brief Free a mbedcrypto_pk_context
+ */
+void mbedcrypto_pk_free( mbedcrypto_pk_context *ctx );
+
+/**
+ * \brief Initialize a PK context with the information given
+ * and allocates the type-specific PK subcontext.
+ *
+ * \param ctx Context to initialize. Must be empty (type NONE).
+ * \param info Information to use
+ *
+ * \return 0 on success,
+ * MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA on invalid input,
+ * MBEDCRYPTO_ERR_PK_ALLOC_FAILED on allocation failure.
+ *
+ * \note For contexts holding an RSA-alt key, use
+ * \c mbedcrypto_pk_setup_rsa_alt() instead.
+ */
+int mbedcrypto_pk_setup( mbedcrypto_pk_context *ctx, const mbedcrypto_pk_info_t *info );
+
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+/**
+ * \brief Initialize an RSA-alt context
+ *
+ * \param ctx Context to initialize. Must be empty (type NONE).
+ * \param key RSA key pointer
+ * \param decrypt_func Decryption function
+ * \param sign_func Signing function
+ * \param key_len_func Function returning key length in bytes
+ *
+ * \return 0 on success, or MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA if the
+ * context wasn't already initialized as RSA_ALT.
+ *
+ * \note This function replaces \c mbedcrypto_pk_setup() for RSA-alt.
+ */
+int mbedcrypto_pk_setup_rsa_alt( mbedcrypto_pk_context *ctx, void * key,
+ mbedcrypto_pk_rsa_alt_decrypt_func decrypt_func,
+ mbedcrypto_pk_rsa_alt_sign_func sign_func,
+ mbedcrypto_pk_rsa_alt_key_len_func key_len_func );
+#endif /* MBEDCRYPTO_PK_RSA_ALT_SUPPORT */
+
+/**
+ * \brief Get the size in bits of the underlying key
+ *
+ * \param ctx Context to use
+ *
+ * \return Key size in bits, or 0 on error
+ */
+size_t mbedcrypto_pk_get_bitlen( const mbedcrypto_pk_context *ctx );
+
+/**
+ * \brief Get the length in bytes of the underlying key
+ * \param ctx Context to use
+ *
+ * \return Key length in bytes, or 0 on error
+ */
+static inline size_t mbedcrypto_pk_get_len( const mbedcrypto_pk_context *ctx )
+{
+ return( ( mbedcrypto_pk_get_bitlen( ctx ) + 7 ) / 8 );
+}
+
+/**
+ * \brief Tell if a context can do the operation given by type
+ *
+ * \param ctx Context to test
+ * \param type Target type
+ *
+ * \return 0 if context can't do the operations,
+ * 1 otherwise.
+ */
+int mbedcrypto_pk_can_do( const mbedcrypto_pk_context *ctx, mbedcrypto_pk_type_t type );
+
+/**
+ * \brief Verify signature (including padding if relevant).
+ *
+ * \param ctx PK context to use
+ * \param md_alg Hash algorithm used (see notes)
+ * \param hash Hash of the message to sign
+ * \param hash_len Hash length or 0 (see notes)
+ * \param sig Signature to verify
+ * \param sig_len Signature length
+ *
+ * \return 0 on success (signature is valid),
+ * #MBEDCRYPTO_ERR_PK_SIG_LEN_MISMATCH if there is a valid
+ * signature in sig but its length is less than \p siglen,
+ * or a specific error code.
+ *
+ * \note For RSA keys, the default padding type is PKCS#1 v1.5.
+ * Use \c mbedcrypto_pk_verify_ext( MBEDCRYPTO_PK_RSASSA_PSS, ... )
+ * to verify RSASSA_PSS signatures.
+ *
+ * \note If hash_len is 0, then the length associated with md_alg
+ * is used instead, or an error returned if it is invalid.
+ *
+ * \note md_alg may be MBEDCRYPTO_MD_NONE, only if hash_len != 0
+ */
+int mbedcrypto_pk_verify( mbedcrypto_pk_context *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len );
+
+/**
+ * \brief Verify signature, with options.
+ * (Includes verification of the padding depending on type.)
+ *
+ * \param type Signature type (inc. possible padding type) to verify
+ * \param options Pointer to type-specific options, or NULL
+ * \param ctx PK context to use
+ * \param md_alg Hash algorithm used (see notes)
+ * \param hash Hash of the message to sign
+ * \param hash_len Hash length or 0 (see notes)
+ * \param sig Signature to verify
+ * \param sig_len Signature length
+ *
+ * \return 0 on success (signature is valid),
+ * #MBEDCRYPTO_ERR_PK_TYPE_MISMATCH if the PK context can't be
+ * used for this type of signatures,
+ * #MBEDCRYPTO_ERR_PK_SIG_LEN_MISMATCH if there is a valid
+ * signature in sig but its length is less than \p siglen,
+ * or a specific error code.
+ *
+ * \note If hash_len is 0, then the length associated with md_alg
+ * is used instead, or an error returned if it is invalid.
+ *
+ * \note md_alg may be MBEDCRYPTO_MD_NONE, only if hash_len != 0
+ *
+ * \note If type is MBEDCRYPTO_PK_RSASSA_PSS, then options must point
+ * to a mbedcrypto_pk_rsassa_pss_options structure,
+ * otherwise it must be NULL.
+ */
+int mbedcrypto_pk_verify_ext( mbedcrypto_pk_type_t type, const void *options,
+ mbedcrypto_pk_context *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len );
+
+/**
+ * \brief Make signature, including padding if relevant.
+ *
+ * \param ctx PK context to use - must hold a private key
+ * \param md_alg Hash algorithm used (see notes)
+ * \param hash Hash of the message to sign
+ * \param hash_len Hash length or 0 (see notes)
+ * \param sig Place to write the signature
+ * \param sig_len Number of bytes written
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 on success, or a specific error code.
+ *
+ * \note For RSA keys, the default padding type is PKCS#1 v1.5.
+ * There is no interface in the PK module to make RSASSA-PSS
+ * signatures yet.
+ *
+ * \note If hash_len is 0, then the length associated with md_alg
+ * is used instead, or an error returned if it is invalid.
+ *
+ * \note For RSA, md_alg may be MBEDCRYPTO_MD_NONE if hash_len != 0.
+ * For ECDSA, md_alg may never be MBEDCRYPTO_MD_NONE.
+ */
+int mbedcrypto_pk_sign( mbedcrypto_pk_context *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief Decrypt message (including padding if relevant).
+ *
+ * \param ctx PK context to use - must hold a private key
+ * \param input Input to decrypt
+ * \param ilen Input size
+ * \param output Decrypted output
+ * \param olen Decrypted message length
+ * \param osize Size of the output buffer
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \note For RSA keys, the default padding type is PKCS#1 v1.5.
+ *
+ * \return 0 on success, or a specific error code.
+ */
+int mbedcrypto_pk_decrypt( mbedcrypto_pk_context *ctx,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen, size_t osize,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief Encrypt message (including padding if relevant).
+ *
+ * \param ctx PK context to use
+ * \param input Message to encrypt
+ * \param ilen Message size
+ * \param output Encrypted output
+ * \param olen Encrypted output length
+ * \param osize Size of the output buffer
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \note For RSA keys, the default padding type is PKCS#1 v1.5.
+ *
+ * \return 0 on success, or a specific error code.
+ */
+int mbedcrypto_pk_encrypt( mbedcrypto_pk_context *ctx,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen, size_t osize,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
+ * \brief Check if a public-private pair of keys matches.
+ *
+ * \param pub Context holding a public key.
+ * \param prv Context holding a private (and public) key.
+ *
+ * \return 0 on success or MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA
+ */
+int mbedcrypto_pk_check_pair( const mbedcrypto_pk_context *pub, const mbedcrypto_pk_context *prv );
+
+/**
+ * \brief Export debug information
+ *
+ * \param ctx Context to use
+ * \param items Place to write debug items
+ *
+ * \return 0 on success or MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA
+ */
+int mbedcrypto_pk_debug( const mbedcrypto_pk_context *ctx, mbedcrypto_pk_debug_item *items );
+
+/**
+ * \brief Access the type name
+ *
+ * \param ctx Context to use
+ *
+ * \return Type name on success, or "invalid PK"
+ */
+const char * mbedcrypto_pk_get_name( const mbedcrypto_pk_context *ctx );
+
+/**
+ * \brief Get the key type
+ *
+ * \param ctx Context to use
+ *
+ * \return Type on success, or MBEDCRYPTO_PK_NONE
+ */
+mbedcrypto_pk_type_t mbedcrypto_pk_get_type( const mbedcrypto_pk_context *ctx );
+
+#if defined(MBEDCRYPTO_PK_PARSE_C)
+/** \ingroup pk_module */
+/**
+ * \brief Parse a private key in PEM or DER format
+ *
+ * \param ctx key to be initialized
+ * \param key input buffer
+ * \param keylen size of the buffer
+ * (including the terminating null byte for PEM data)
+ * \param pwd password for decryption (optional)
+ * \param pwdlen size of the password
+ *
+ * \note On entry, ctx must be empty, either freshly initialised
+ * with mbedcrypto_pk_init() or reset with mbedcrypto_pk_free(). If you need a
+ * specific key type, check the result with mbedcrypto_pk_can_do().
+ *
+ * \note The key is also checked for correctness.
+ *
+ * \return 0 if successful, or a specific PK or PEM error code
+ */
+int mbedcrypto_pk_parse_key( mbedcrypto_pk_context *ctx,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *pwd, size_t pwdlen );
+
+/** \ingroup pk_module */
+/**
+ * \brief Parse a public key in PEM or DER format
+ *
+ * \param ctx key to be initialized
+ * \param key input buffer
+ * \param keylen size of the buffer
+ * (including the terminating null byte for PEM data)
+ *
+ * \note On entry, ctx must be empty, either freshly initialised
+ * with mbedcrypto_pk_init() or reset with mbedcrypto_pk_free(). If you need a
+ * specific key type, check the result with mbedcrypto_pk_can_do().
+ *
+ * \note The key is also checked for correctness.
+ *
+ * \return 0 if successful, or a specific PK or PEM error code
+ */
+int mbedcrypto_pk_parse_public_key( mbedcrypto_pk_context *ctx,
+ const unsigned char *key, size_t keylen );
+
+#if defined(MBEDCRYPTO_FS_IO)
+/** \ingroup pk_module */
+/**
+ * \brief Load and parse a private key
+ *
+ * \param ctx key to be initialized
+ * \param path filename to read the private key from
+ * \param password password to decrypt the file (can be NULL)
+ *
+ * \note On entry, ctx must be empty, either freshly initialised
+ * with mbedcrypto_pk_init() or reset with mbedcrypto_pk_free(). If you need a
+ * specific key type, check the result with mbedcrypto_pk_can_do().
+ *
+ * \note The key is also checked for correctness.
+ *
+ * \return 0 if successful, or a specific PK or PEM error code
+ */
+int mbedcrypto_pk_parse_keyfile( mbedcrypto_pk_context *ctx,
+ const char *path, const char *password );
+
+/** \ingroup pk_module */
+/**
+ * \brief Load and parse a public key
+ *
+ * \param ctx key to be initialized
+ * \param path filename to read the public key from
+ *
+ * \note On entry, ctx must be empty, either freshly initialised
+ * with mbedcrypto_pk_init() or reset with mbedcrypto_pk_free(). If
+ * you need a specific key type, check the result with
+ * mbedcrypto_pk_can_do().
+ *
+ * \note The key is also checked for correctness.
+ *
+ * \return 0 if successful, or a specific PK or PEM error code
+ */
+int mbedcrypto_pk_parse_public_keyfile( mbedcrypto_pk_context *ctx, const char *path );
+#endif /* MBEDCRYPTO_FS_IO */
+#endif /* MBEDCRYPTO_PK_PARSE_C */
+
+#if defined(MBEDCRYPTO_PK_WRITE_C)
+/**
+ * \brief Write a private key to a PKCS#1 or SEC1 DER structure
+ * Note: data is written at the end of the buffer! Use the
+ * return value to determine where you should start
+ * using the buffer
+ *
+ * \param ctx private to write away
+ * \param buf buffer to write to
+ * \param size size of the buffer
+ *
+ * \return length of data written if successful, or a specific
+ * error code
+ */
+int mbedcrypto_pk_write_key_der( mbedcrypto_pk_context *ctx, unsigned char *buf, size_t size );
+
+/**
+ * \brief Write a public key to a SubjectPublicKeyInfo DER structure
+ * Note: data is written at the end of the buffer! Use the
+ * return value to determine where you should start
+ * using the buffer
+ *
+ * \param ctx public key to write away
+ * \param buf buffer to write to
+ * \param size size of the buffer
+ *
+ * \return length of data written if successful, or a specific
+ * error code
+ */
+int mbedcrypto_pk_write_pubkey_der( mbedcrypto_pk_context *ctx, unsigned char *buf, size_t size );
+
+#if defined(MBEDCRYPTO_PEM_WRITE_C)
+/**
+ * \brief Write a public key to a PEM string
+ *
+ * \param ctx public key to write away
+ * \param buf buffer to write to
+ * \param size size of the buffer
+ *
+ * \return 0 if successful, or a specific error code
+ */
+int mbedcrypto_pk_write_pubkey_pem( mbedcrypto_pk_context *ctx, unsigned char *buf, size_t size );
+
+/**
+ * \brief Write a private key to a PKCS#1 or SEC1 PEM string
+ *
+ * \param ctx private to write away
+ * \param buf buffer to write to
+ * \param size size of the buffer
+ *
+ * \return 0 if successful, or a specific error code
+ */
+int mbedcrypto_pk_write_key_pem( mbedcrypto_pk_context *ctx, unsigned char *buf, size_t size );
+#endif /* MBEDCRYPTO_PEM_WRITE_C */
+#endif /* MBEDCRYPTO_PK_WRITE_C */
+
+/*
+ * WARNING: Low-level functions. You probably do not want to use these unless
+ * you are certain you do ;)
+ */
+
+#if defined(MBEDCRYPTO_PK_PARSE_C)
+/**
+ * \brief Parse a SubjectPublicKeyInfo DER structure
+ *
+ * \param p the position in the ASN.1 data
+ * \param end end of the buffer
+ * \param pk the key to fill
+ *
+ * \return 0 if successful, or a specific PK error code
+ */
+int mbedcrypto_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
+ mbedcrypto_pk_context *pk );
+#endif /* MBEDCRYPTO_PK_PARSE_C */
+
+#if defined(MBEDCRYPTO_PK_WRITE_C)
+/**
+ * \brief Write a subjectPublicKey to ASN.1 data
+ * Note: function works backwards in data buffer
+ *
+ * \param p reference to current position pointer
+ * \param start start of the buffer (for bounds-checking)
+ * \param key public key to write away
+ *
+ * \return the length written or a negative error code
+ */
+int mbedcrypto_pk_write_pubkey( unsigned char **p, unsigned char *start,
+ const mbedcrypto_pk_context *key );
+#endif /* MBEDCRYPTO_PK_WRITE_C */
+
+/*
+ * Internal module functions. You probably do not want to use these unless you
+ * know you do.
+ */
+#if defined(MBEDCRYPTO_FS_IO)
+int mbedcrypto_pk_load_file( const char *path, unsigned char **buf, size_t *n );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_PK_H */
diff --git a/include/mbedcrypto/pk_internal.h b/include/mbedcrypto/pk_internal.h
new file mode 100644
index 0000000..b208c6e
--- /dev/null
+++ b/include/mbedcrypto/pk_internal.h
@@ -0,0 +1,115 @@
+/**
+ * \file pk_internal.h
+ *
+ * \brief Public Key abstraction layer: wrapper functions
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef MBEDCRYPTO_PK_WRAP_H
+#define MBEDCRYPTO_PK_WRAP_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "pk.h"
+
+struct mbedcrypto_pk_info_t
+{
+ /** Public key type */
+ mbedcrypto_pk_type_t type;
+
+ /** Type name */
+ const char *name;
+
+ /** Get key size in bits */
+ size_t (*get_bitlen)( const void * );
+
+ /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */
+ int (*can_do)( mbedcrypto_pk_type_t type );
+
+ /** Verify signature */
+ int (*verify_func)( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len );
+
+ /** Make signature */
+ int (*sign_func)( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+ /** Decrypt message */
+ int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen, size_t osize,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+ /** Encrypt message */
+ int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen, size_t osize,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+ /** Check public-private key pair */
+ int (*check_pair_func)( const void *pub, const void *prv );
+
+ /** Allocate a new context */
+ void * (*ctx_alloc_func)( void );
+
+ /** Free the given context */
+ void (*ctx_free_func)( void *ctx );
+
+ /** Interface with the debug module */
+ void (*debug_func)( const void *ctx, mbedcrypto_pk_debug_item *items );
+
+};
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+/* Container for RSA-alt */
+typedef struct
+{
+ void *key;
+ mbedcrypto_pk_rsa_alt_decrypt_func decrypt_func;
+ mbedcrypto_pk_rsa_alt_sign_func sign_func;
+ mbedcrypto_pk_rsa_alt_key_len_func key_len_func;
+} mbedcrypto_rsa_alt_context;
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C)
+extern const mbedcrypto_pk_info_t mbedcrypto_rsa_info;
+#endif
+
+#if defined(MBEDCRYPTO_ECP_C)
+extern const mbedcrypto_pk_info_t mbedcrypto_eckey_info;
+extern const mbedcrypto_pk_info_t mbedcrypto_eckeydh_info;
+#endif
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+extern const mbedcrypto_pk_info_t mbedcrypto_ecdsa_info;
+#endif
+
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+extern const mbedcrypto_pk_info_t mbedcrypto_rsa_alt_info;
+#endif
+
+#endif /* MBEDCRYPTO_PK_WRAP_H */
diff --git a/include/mbedcrypto/pkcs11.h b/include/mbedcrypto/pkcs11.h
new file mode 100644
index 0000000..2233ec8
--- /dev/null
+++ b/include/mbedcrypto/pkcs11.h
@@ -0,0 +1,174 @@
+/**
+ * \file pkcs11.h
+ *
+ * \brief Wrapper for PKCS#11 library libpkcs11-helper
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PKCS11_H
+#define MBEDCRYPTO_PKCS11_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PKCS11_C)
+
+#include "x509_crt.h"
+
+#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Context for PKCS #11 private keys.
+ */
+typedef struct {
+ pkcs11h_certificate_t pkcs11h_cert;
+ int len;
+} mbedcrypto_pkcs11_context;
+
+/**
+ * Initialize a mbedcrypto_pkcs11_context.
+ * (Just making memory references valid.)
+ */
+void mbedcrypto_pkcs11_init( mbedcrypto_pkcs11_context *ctx );
+
+/**
+ * Fill in a Mbed Crypto certificate, based on the given PKCS11 helper certificate.
+ *
+ * \param cert X.509 certificate to fill
+ * \param pkcs11h_cert PKCS #11 helper certificate
+ *
+ * \return 0 on success.
+ */
+int mbedcrypto_pkcs11_x509_cert_bind( mbedcrypto_x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert );
+
+/**
+ * Set up a mbedcrypto_pkcs11_context storing the given certificate. Note that the
+ * mbedcrypto_pkcs11_context will take over control of the certificate, freeing it when
+ * done.
+ *
+ * \param priv_key Private key structure to fill.
+ * \param pkcs11_cert PKCS #11 helper certificate
+ *
+ * \return 0 on success
+ */
+int mbedcrypto_pkcs11_priv_key_bind( mbedcrypto_pkcs11_context *priv_key,
+ pkcs11h_certificate_t pkcs11_cert );
+
+/**
+ * Free the contents of the given private key context. Note that the structure
+ * itself is not freed.
+ *
+ * \param priv_key Private key structure to cleanup
+ */
+void mbedcrypto_pkcs11_priv_key_free( mbedcrypto_pkcs11_context *priv_key );
+
+/**
+ * \brief Do an RSA private key decrypt, then remove the message
+ * padding
+ *
+ * \param ctx PKCS #11 context
+ * \param mode must be MBEDCRYPTO_RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param input buffer holding the encrypted data
+ * \param output buffer that will hold the plaintext
+ * \param olen will contain the plaintext length
+ * \param output_max_len maximum length of the output buffer
+ *
+ * \return 0 if successful, or an MBEDCRYPTO_ERR_RSA_XXX error code
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ * an error is thrown.
+ */
+int mbedcrypto_pkcs11_decrypt( mbedcrypto_pkcs11_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len );
+
+/**
+ * \brief Do a private RSA to sign a message digest
+ *
+ * \param ctx PKCS #11 context
+ * \param mode must be MBEDCRYPTO_RSA_PRIVATE, for compatibility with rsa.c's signature
+ * \param md_alg a MBEDCRYPTO_MD_XXX (use MBEDCRYPTO_MD_NONE for signing raw data)
+ * \param hashlen message digest length (for MBEDCRYPTO_MD_NONE only)
+ * \param hash buffer holding the message digest
+ * \param sig buffer that will hold the ciphertext
+ *
+ * \return 0 if the signing operation was successful,
+ * or an MBEDCRYPTO_ERR_RSA_XXX error code
+ *
+ * \note The "sig" buffer must be as large as the size
+ * of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int mbedcrypto_pkcs11_sign( mbedcrypto_pkcs11_context *ctx,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * SSL/TLS wrappers for PKCS#11 functions
+ */
+static inline int mbedcrypto_ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen,
+ const unsigned char *input, unsigned char *output,
+ size_t output_max_len )
+{
+ return mbedcrypto_pkcs11_decrypt( (mbedcrypto_pkcs11_context *) ctx, mode, olen, input, output,
+ output_max_len );
+}
+
+static inline int mbedcrypto_ssl_pkcs11_sign( void *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ int mode, mbedcrypto_md_type_t md_alg, unsigned int hashlen,
+ const unsigned char *hash, unsigned char *sig )
+{
+ ((void) f_rng);
+ ((void) p_rng);
+ return mbedcrypto_pkcs11_sign( (mbedcrypto_pkcs11_context *) ctx, mode, md_alg,
+ hashlen, hash, sig );
+}
+
+static inline size_t mbedcrypto_ssl_pkcs11_key_len( void *ctx )
+{
+ return ( (mbedcrypto_pkcs11_context *) ctx )->len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_PKCS11_C */
+
+#endif /* MBEDCRYPTO_PKCS11_H */
diff --git a/include/mbedcrypto/pkcs12.h b/include/mbedcrypto/pkcs12.h
new file mode 100644
index 0000000..403f20a
--- /dev/null
+++ b/include/mbedcrypto/pkcs12.h
@@ -0,0 +1,120 @@
+/**
+ * \file pkcs12.h
+ *
+ * \brief PKCS#12 Personal Information Exchange Syntax
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PKCS12_H
+#define MBEDCRYPTO_PKCS12_H
+
+#include "md.h"
+#include "cipher.h"
+#include "asn1.h"
+
+#include <stddef.h>
+
+#define MBEDCRYPTO_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */
+#define MBEDCRYPTO_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */
+#define MBEDCRYPTO_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */
+
+#define MBEDCRYPTO_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */
+#define MBEDCRYPTO_PKCS12_DERIVE_IV 2 /**< initialization vector */
+#define MBEDCRYPTO_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */
+
+#define MBEDCRYPTO_PKCS12_PBE_DECRYPT 0
+#define MBEDCRYPTO_PKCS12_PBE_ENCRYPT 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PKCS12 Password Based function (encryption / decryption)
+ * for pbeWithSHAAnd128BitRC4
+ *
+ * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure
+ * \param mode either MBEDCRYPTO_PKCS12_PBE_ENCRYPT or MBEDCRYPTO_PKCS12_PBE_DECRYPT
+ * \param pwd the password used (may be NULL if no password is used)
+ * \param pwdlen length of the password (may be 0)
+ * \param input the input data
+ * \param len data length
+ * \param output the output buffer
+ *
+ * \return 0 if successful, or a MBEDCRYPTO_ERR_XXX code
+ */
+int mbedcrypto_pkcs12_pbe_sha1_rc4_128( mbedcrypto_asn1_buf *pbe_params, int mode,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *input, size_t len,
+ unsigned char *output );
+
+/**
+ * \brief PKCS12 Password Based function (encryption / decryption)
+ * for cipher-based and mbedcrypto_md-based PBE's
+ *
+ * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure
+ * \param mode either MBEDCRYPTO_PKCS12_PBE_ENCRYPT or MBEDCRYPTO_PKCS12_PBE_DECRYPT
+ * \param cipher_type the cipher used
+ * \param md_type the mbedcrypto_md used
+ * \param pwd the password used (may be NULL if no password is used)
+ * \param pwdlen length of the password (may be 0)
+ * \param input the input data
+ * \param len data length
+ * \param output the output buffer
+ *
+ * \return 0 if successful, or a MBEDCRYPTO_ERR_XXX code
+ */
+int mbedcrypto_pkcs12_pbe( mbedcrypto_asn1_buf *pbe_params, int mode,
+ mbedcrypto_cipher_type_t cipher_type, mbedcrypto_md_type_t md_type,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *input, size_t len,
+ unsigned char *output );
+
+/**
+ * \brief The PKCS#12 derivation function uses a password and a salt
+ * to produce pseudo-random bits for a particular "purpose".
+ *
+ * Depending on the given id, this function can produce an
+ * encryption/decryption key, an nitialization vector or an
+ * integrity key.
+ *
+ * \param data buffer to store the derived data in
+ * \param datalen length to fill
+ * \param pwd password to use (may be NULL if no password is used)
+ * \param pwdlen length of the password (may be 0)
+ * \param salt salt buffer to use
+ * \param saltlen length of the salt
+ * \param mbedcrypto_md mbedcrypto_md type to use during the derivation
+ * \param id id that describes the purpose (can be MBEDCRYPTO_PKCS12_DERIVE_KEY,
+ * MBEDCRYPTO_PKCS12_DERIVE_IV or MBEDCRYPTO_PKCS12_DERIVE_MAC_KEY)
+ * \param iterations number of iterations
+ *
+ * \return 0 if successful, or a MD, BIGNUM type error.
+ */
+int mbedcrypto_pkcs12_derivation( unsigned char *data, size_t datalen,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *salt, size_t saltlen,
+ mbedcrypto_md_type_t mbedcrypto_md, int id, int iterations );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pkcs12.h */
diff --git a/include/mbedcrypto/pkcs5.h b/include/mbedcrypto/pkcs5.h
new file mode 100644
index 0000000..d3921cb
--- /dev/null
+++ b/include/mbedcrypto/pkcs5.h
@@ -0,0 +1,95 @@
+/**
+ * \file pkcs5.h
+ *
+ * \brief PKCS#5 functions
+ *
+ * \author Mathias Olsson <mathias@kompetensum.com>
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PKCS5_H
+#define MBEDCRYPTO_PKCS5_H
+
+#include "asn1.h"
+#include "md.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT -0x2f00 /**< Unexpected ASN.1 data. */
+#define MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /**< Requested encryption or digest alg not available. */
+#define MBEDCRYPTO_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 /**< Given private key password does not allow for correct decryption. */
+
+#define MBEDCRYPTO_PKCS5_DECRYPT 0
+#define MBEDCRYPTO_PKCS5_ENCRYPT 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PKCS#5 PBES2 function
+ *
+ * \param pbe_params the ASN.1 algorithm parameters
+ * \param mode either MBEDCRYPTO_PKCS5_DECRYPT or MBEDCRYPTO_PKCS5_ENCRYPT
+ * \param pwd password to use when generating key
+ * \param pwdlen length of password
+ * \param data data to process
+ * \param datalen length of data
+ * \param output output buffer
+ *
+ * \returns 0 on success, or a MBEDCRYPTO_ERR_XXX code if verification fails.
+ */
+int mbedcrypto_pkcs5_pbes2( const mbedcrypto_asn1_buf *pbe_params, int mode,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *data, size_t datalen,
+ unsigned char *output );
+
+/**
+ * \brief PKCS#5 PBKDF2 using HMAC
+ *
+ * \param ctx Generic HMAC context
+ * \param password Password to use when generating key
+ * \param plen Length of password
+ * \param salt Salt to use when generating key
+ * \param slen Length of salt
+ * \param iteration_count Iteration count
+ * \param key_length Length of generated key in bytes
+ * \param output Generated key. Must be at least as big as key_length
+ *
+ * \returns 0 on success, or a MBEDCRYPTO_ERR_XXX code if verification fails.
+ */
+int mbedcrypto_pkcs5_pbkdf2_hmac( mbedcrypto_md_context_t *ctx, const unsigned char *password,
+ size_t plen, const unsigned char *salt, size_t slen,
+ unsigned int iteration_count,
+ uint32_t key_length, unsigned char *output );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_pkcs5_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* pkcs5.h */
diff --git a/include/mbedcrypto/platform.h b/include/mbedcrypto/platform.h
new file mode 100644
index 0000000..61613f9
--- /dev/null
+++ b/include/mbedcrypto/platform.h
@@ -0,0 +1,363 @@
+/**
+ * \file platform.h
+ *
+ * \brief This file contains the definitions and functions of the
+ * Mbed Crypto platform abstraction layer.
+ *
+ * The platform abstraction layer removes the need for the library
+ * to directly link to standard C library functions or operating
+ * system services, making the library easier to port and embed.
+ * Application developers and users of the library can provide their own
+ * implementations of these functions, or implementations specific to
+ * their platform, which can be statically linked to the library or
+ * dynamically configured at runtime.
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PLATFORM_H
+#define MBEDCRYPTO_PLATFORM_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_HAVE_TIME)
+#include "mbedcrypto/platform_time.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS)
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#if !defined(MBEDCRYPTO_PLATFORM_STD_SNPRINTF)
+#if defined(_WIN32)
+#define MBEDCRYPTO_PLATFORM_STD_SNPRINTF mbedcrypto_platform_win32_snprintf /**< The default \c snprintf function to use. */
+#else
+#define MBEDCRYPTO_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */
+#endif
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_PRINTF)
+#define MBEDCRYPTO_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_FPRINTF)
+#define MBEDCRYPTO_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_CALLOC)
+#define MBEDCRYPTO_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_FREE)
+#define MBEDCRYPTO_PLATFORM_STD_FREE free /**< The default \c free function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_EXIT)
+#define MBEDCRYPTO_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_TIME)
+#define MBEDCRYPTO_PLATFORM_STD_TIME time /**< The default \c time function to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_EXIT_SUCCESS)
+#define MBEDCRYPTO_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_EXIT_FAILURE)
+#define MBEDCRYPTO_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */
+#endif
+#if defined(MBEDCRYPTO_FS_IO)
+#if !defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ)
+#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ mbedcrypto_platform_std_nv_seed_read
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE)
+#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE mbedcrypto_platform_std_nv_seed_write
+#endif
+#if !defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_FILE)
+#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_FILE "seedfile"
+#endif
+#endif /* MBEDCRYPTO_FS_IO */
+#else /* MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS */
+#if defined(MBEDCRYPTO_PLATFORM_STD_MEM_HDR)
+#include MBEDCRYPTO_PLATFORM_STD_MEM_HDR
+#endif
+#endif /* MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS */
+
+
+/* \} name SECTION: Module settings */
+
+/*
+ * The function pointers for calloc and free.
+ */
+#if defined(MBEDCRYPTO_PLATFORM_MEMORY)
+#if defined(MBEDCRYPTO_PLATFORM_FREE_MACRO) && \
+ defined(MBEDCRYPTO_PLATFORM_CALLOC_MACRO)
+#define mbedcrypto_free MBEDCRYPTO_PLATFORM_FREE_MACRO
+#define mbedcrypto_calloc MBEDCRYPTO_PLATFORM_CALLOC_MACRO
+#else
+/* For size_t */
+#include <stddef.h>
+extern void * (*mbedcrypto_calloc)( size_t n, size_t size );
+extern void (*mbedcrypto_free)( void *ptr );
+
+/**
+ * \brief This function dynamically sets the memory-management
+ * functions used by the library, during runtime.
+ *
+ * \param calloc_func The \c calloc function implementation.
+ * \param free_func The \c free function implementation.
+ *
+ * \return \c 0.
+ */
+int mbedcrypto_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
+ void (*free_func)( void * ) );
+#endif /* MBEDCRYPTO_PLATFORM_FREE_MACRO && MBEDCRYPTO_PLATFORM_CALLOC_MACRO */
+#else /* !MBEDCRYPTO_PLATFORM_MEMORY */
+#define mbedcrypto_free free
+#define mbedcrypto_calloc calloc
+#endif /* MBEDCRYPTO_PLATFORM_MEMORY && !MBEDCRYPTO_PLATFORM_{FREE,CALLOC}_MACRO */
+
+/*
+ * The function pointers for fprintf
+ */
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_ALT)
+/* We need FILE * */
+#include <stdio.h>
+extern int (*mbedcrypto_fprintf)( FILE *stream, const char *format, ... );
+
+/**
+ * \brief This function dynamically configures the fprintf
+ * function that is called when the
+ * mbedcrypto_fprintf() function is invoked by the library.
+ *
+ * \param fprintf_func The \c fprintf function implementation.
+ *
+ * \return \c 0.
+ */
+int mbedcrypto_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *,
+ ... ) );
+#else
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_MACRO)
+#define mbedcrypto_fprintf MBEDCRYPTO_PLATFORM_FPRINTF_MACRO
+#else
+#define mbedcrypto_fprintf fprintf
+#endif /* MBEDCRYPTO_PLATFORM_FPRINTF_MACRO */
+#endif /* MBEDCRYPTO_PLATFORM_FPRINTF_ALT */
+
+/*
+ * The function pointers for printf
+ */
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_ALT)
+extern int (*mbedcrypto_printf)( const char *format, ... );
+
+/**
+ * \brief This function dynamically configures the snprintf
+ * function that is called when the mbedcrypto_snprintf()
+ * function is invoked by the library.
+ *
+ * \param printf_func The \c printf function implementation.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_platform_set_printf( int (*printf_func)( const char *, ... ) );
+#else /* !MBEDCRYPTO_PLATFORM_PRINTF_ALT */
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_MACRO)
+#define mbedcrypto_printf MBEDCRYPTO_PLATFORM_PRINTF_MACRO
+#else
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_PRINTF_MACRO */
+#endif /* MBEDCRYPTO_PLATFORM_PRINTF_ALT */
+
+/*
+ * The function pointers for snprintf
+ *
+ * The snprintf implementation should conform to C99:
+ * - it *must* always correctly zero-terminate the buffer
+ * (except when n == 0, then it must leave the buffer untouched)
+ * - however it is acceptable to return -1 instead of the required length when
+ * the destination buffer is too short.
+ */
+#if defined(_WIN32)
+/* For Windows (inc. MSYS2), we provide our own fixed implementation */
+int mbedcrypto_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... );
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT)
+extern int (*mbedcrypto_snprintf)( char * s, size_t n, const char * format, ... );
+
+/**
+ * \brief This function allows configuring a custom
+ * \c snprintf function pointer.
+ *
+ * \param snprintf_func The \c snprintf function implementation.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n,
+ const char * format, ... ) );
+#else /* MBEDCRYPTO_PLATFORM_SNPRINTF_ALT */
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO)
+#define mbedcrypto_snprintf MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO
+#else
+#define mbedcrypto_snprintf MBEDCRYPTO_PLATFORM_STD_SNPRINTF
+#endif /* MBEDCRYPTO_PLATFORM_SNPRINTF_MACRO */
+#endif /* MBEDCRYPTO_PLATFORM_SNPRINTF_ALT */
+
+/*
+ * The function pointers for exit
+ */
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_ALT)
+extern void (*mbedcrypto_exit)( int status );
+
+/**
+ * \brief This function dynamically configures the exit
+ * function that is called when the mbedcrypto_exit()
+ * function is invoked by the library.
+ *
+ * \param exit_func The \c exit function implementation.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_platform_set_exit( void (*exit_func)( int status ) );
+#else
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_MACRO)
+#define mbedcrypto_exit MBEDCRYPTO_PLATFORM_EXIT_MACRO
+#else
+#define mbedcrypto_exit exit
+#endif /* MBEDCRYPTO_PLATFORM_EXIT_MACRO */
+#endif /* MBEDCRYPTO_PLATFORM_EXIT_ALT */
+
+/*
+ * The default exit values
+ */
+#if defined(MBEDCRYPTO_PLATFORM_STD_EXIT_SUCCESS)
+#define MBEDCRYPTO_EXIT_SUCCESS MBEDCRYPTO_PLATFORM_STD_EXIT_SUCCESS
+#else
+#define MBEDCRYPTO_EXIT_SUCCESS 0
+#endif
+#if defined(MBEDCRYPTO_PLATFORM_STD_EXIT_FAILURE)
+#define MBEDCRYPTO_EXIT_FAILURE MBEDCRYPTO_PLATFORM_STD_EXIT_FAILURE
+#else
+#define MBEDCRYPTO_EXIT_FAILURE 1
+#endif
+
+/*
+ * The function pointers for reading from and writing a seed file to
+ * Non-Volatile storage (NV) in a platform-independent way
+ *
+ * Only enabled when the NV seed entropy source is enabled
+ */
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+#if !defined(MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDCRYPTO_FS_IO)
+/* Internal standard platform definitions */
+int mbedcrypto_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len );
+int mbedcrypto_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len );
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT)
+extern int (*mbedcrypto_nv_seed_read)( unsigned char *buf, size_t buf_len );
+extern int (*mbedcrypto_nv_seed_write)( unsigned char *buf, size_t buf_len );
+
+/**
+ * \brief This function allows configuring custom seed file writing and
+ * reading functions.
+ *
+ * \param nv_seed_read_func The seed reading function implementation.
+ * \param nv_seed_write_func The seed writing function implementation.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_platform_set_nv_seed(
+ int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ),
+ int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len )
+ );
+#else
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_READ_MACRO) && \
+ defined(MBEDCRYPTO_PLATFORM_NV_SEED_WRITE_MACRO)
+#define mbedcrypto_nv_seed_read MBEDCRYPTO_PLATFORM_NV_SEED_READ_MACRO
+#define mbedcrypto_nv_seed_write MBEDCRYPTO_PLATFORM_NV_SEED_WRITE_MACRO
+#else
+#define mbedcrypto_nv_seed_read mbedcrypto_platform_std_nv_seed_read
+#define mbedcrypto_nv_seed_write mbedcrypto_platform_std_nv_seed_write
+#endif
+#endif /* MBEDCRYPTO_PLATFORM_NV_SEED_ALT */
+#endif /* MBEDCRYPTO_ENTROPY_NV_SEED */
+
+#if !defined(MBEDCRYPTO_PLATFORM_SETUP_TEARDOWN_ALT)
+
+/**
+ * \brief The platform context structure.
+ *
+ * \note This structure may be used to assist platform-specific
+ * setup or teardown operations.
+ */
+typedef struct {
+ char dummy; /**< A placeholder member, as empty structs are not portable. */
+}
+mbedcrypto_platform_context;
+
+#else
+#include "platform_alt.h"
+#endif /* !MBEDCRYPTO_PLATFORM_SETUP_TEARDOWN_ALT */
+
+/**
+ * \brief This function performs any platform-specific initialization
+ * operations.
+ *
+ * \note This function should be called before any other library functions.
+ *
+ * Its implementation is platform-specific, and unless
+ * platform-specific code is provided, it does nothing.
+ *
+ * \note The usage and necessity of this function is dependent on the platform.
+ *
+ * \param ctx The platform context.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_platform_setup( mbedcrypto_platform_context *ctx );
+/**
+ * \brief This function performs any platform teardown operations.
+ *
+ * \note This function should be called after every other Mbed Crypto module
+ * has been correctly freed using the appropriate free function.
+ *
+ * Its implementation is platform-specific, and unless
+ * platform-specific code is provided, it does nothing.
+ *
+ * \note The usage and necessity of this function is dependent on the platform.
+ *
+ * \param ctx The platform context.
+ *
+ */
+void mbedcrypto_platform_teardown( mbedcrypto_platform_context *ctx );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* platform.h */
diff --git a/include/mbedcrypto/platform_util.h b/include/mbedcrypto/platform_util.h
new file mode 100644
index 0000000..5375313
--- /dev/null
+++ b/include/mbedcrypto/platform_util.h
@@ -0,0 +1,62 @@
+/**
+ * \file platform_util.h
+ *
+ * \brief Common and shared functions used by multiple modules in the Mbed Crypto
+ * library.
+ */
+/*
+ * Copyright (C) 2018, Arm Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_PLATFORM_UTIL_H
+#define MBEDCRYPTO_PLATFORM_UTIL_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Securely zeroize a buffer
+ *
+ * The function is meant to wipe the data contained in a buffer so
+ * that it can no longer be recovered even if the program memory
+ * is later compromised. Call this function on sensitive data
+ * stored on the stack before returning from a function, and on
+ * sensitive data stored on the heap before freeing the heap
+ * object.
+ *
+ * It is extremely difficult to guarantee that calls to
+ * mbedcrypto_platform_zeroize() are not removed by aggressive
+ * compiler optimizations in a portable way. For this reason, Mbed
+ * TLS provides the configuration option
+ * MBEDCRYPTO_PLATFORM_ZEROIZE_ALT, which allows users to configure
+ * mbedcrypto_platform_zeroize() to use a suitable implementation for
+ * their platform and needs
+ *
+ * \param buf Buffer to be zeroized
+ * \param len Length of the buffer in bytes
+ *
+ */
+void mbedcrypto_platform_zeroize( void *buf, size_t len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDCRYPTO_PLATFORM_UTIL_H */
diff --git a/include/mbedcrypto/ripemd160.h b/include/mbedcrypto/ripemd160.h
new file mode 100644
index 0000000..ca245fb
--- /dev/null
+++ b/include/mbedcrypto/ripemd160.h
@@ -0,0 +1,231 @@
+/**
+ * \file ripemd160.h
+ *
+ * \brief RIPE MD-160 message digest
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_RIPEMD160_H
+#define MBEDCRYPTO_RIPEMD160_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_RIPEMD160_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief RIPEMD-160 context structure
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[5]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+}
+mbedcrypto_ripemd160_context;
+
+#else /* MBEDCRYPTO_RIPEMD160_ALT */
+#include "ripemd160.h"
+#endif /* MBEDCRYPTO_RIPEMD160_ALT */
+
+/**
+ * \brief Initialize RIPEMD-160 context
+ *
+ * \param ctx RIPEMD-160 context to be initialized
+ */
+void mbedcrypto_ripemd160_init( mbedcrypto_ripemd160_context *ctx );
+
+/**
+ * \brief Clear RIPEMD-160 context
+ *
+ * \param ctx RIPEMD-160 context to be cleared
+ */
+void mbedcrypto_ripemd160_free( mbedcrypto_ripemd160_context *ctx );
+
+/**
+ * \brief Clone (the state of) an RIPEMD-160 context
+ *
+ * \param dst The destination context
+ * \param src The context to be cloned
+ */
+void mbedcrypto_ripemd160_clone( mbedcrypto_ripemd160_context *dst,
+ const mbedcrypto_ripemd160_context *src );
+
+/**
+ * \brief RIPEMD-160 context setup
+ *
+ * \param ctx context to be initialized
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_ripemd160_starts_ret( mbedcrypto_ripemd160_context *ctx );
+
+/**
+ * \brief RIPEMD-160 process buffer
+ *
+ * \param ctx RIPEMD-160 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_ripemd160_update_ret( mbedcrypto_ripemd160_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief RIPEMD-160 final digest
+ *
+ * \param ctx RIPEMD-160 context
+ * \param output RIPEMD-160 checksum result
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_ripemd160_finish_ret( mbedcrypto_ripemd160_context *ctx,
+ unsigned char output[20] );
+
+/**
+ * \brief RIPEMD-160 process data block (internal use only)
+ *
+ * \param ctx RIPEMD-160 context
+ * \param data buffer holding one block of data
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_internal_ripemd160_process( mbedcrypto_ripemd160_context *ctx,
+ const unsigned char data[64] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief RIPEMD-160 context setup
+ *
+ * \deprecated Superseded by mbedcrypto_ripemd160_starts_ret() in 2.7.0
+ *
+ * \param ctx context to be initialized
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_ripemd160_starts(
+ mbedcrypto_ripemd160_context *ctx );
+
+/**
+ * \brief RIPEMD-160 process buffer
+ *
+ * \deprecated Superseded by mbedcrypto_ripemd160_update_ret() in 2.7.0
+ *
+ * \param ctx RIPEMD-160 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_ripemd160_update(
+ mbedcrypto_ripemd160_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief RIPEMD-160 final digest
+ *
+ * \deprecated Superseded by mbedcrypto_ripemd160_finish_ret() in 2.7.0
+ *
+ * \param ctx RIPEMD-160 context
+ * \param output RIPEMD-160 checksum result
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_ripemd160_finish(
+ mbedcrypto_ripemd160_context *ctx,
+ unsigned char output[20] );
+
+/**
+ * \brief RIPEMD-160 process data block (internal use only)
+ *
+ * \deprecated Superseded by mbedcrypto_internal_ripemd160_process() in 2.7.0
+ *
+ * \param ctx RIPEMD-160 context
+ * \param data buffer holding one block of data
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_ripemd160_process(
+ mbedcrypto_ripemd160_context *ctx,
+ const unsigned char data[64] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief Output = RIPEMD-160( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output RIPEMD-160 checksum result
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_ripemd160_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[20] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief Output = RIPEMD-160( input buffer )
+ *
+ * \deprecated Superseded by mbedcrypto_ripemd160_ret() in 2.7.0
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output RIPEMD-160 checksum result
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_ripemd160( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[20] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_ripemd160_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_ripemd160.h */
diff --git a/include/mbedcrypto/rsa.h b/include/mbedcrypto/rsa.h
new file mode 100644
index 0000000..0c33cae
--- /dev/null
+++ b/include/mbedcrypto/rsa.h
@@ -0,0 +1,1141 @@
+/**
+ * \file rsa.h
+ *
+ * \brief This file provides an API for the RSA public-key cryptosystem.
+ *
+ * The RSA public-key cryptosystem is defined in <em>Public-Key
+ * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption</em>
+ * and <em>Public-Key Cryptography Standards (PKCS) #1 v2.1:
+ * RSA Cryptography Specifications</em>.
+ *
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_RSA_H
+#define MBEDCRYPTO_RSA_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "bignum.h"
+#include "md.h"
+
+#if defined(MBEDCRYPTO_THREADING_C)
+#include "threading.h"
+#endif
+
+/*
+ * RSA Error codes
+ */
+#define MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */
+#define MBEDCRYPTO_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */
+#define MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the validity check of the library. */
+#define MBEDCRYPTO_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */
+#define MBEDCRYPTO_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */
+#define MBEDCRYPTO_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */
+#define MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */
+#define MBEDCRYPTO_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */
+#define MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */
+#define MBEDCRYPTO_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */
+
+/*
+ * RSA constants
+ */
+#define MBEDCRYPTO_RSA_PUBLIC 0 /**< Request private key operation. */
+#define MBEDCRYPTO_RSA_PRIVATE 1 /**< Request public key operation. */
+
+#define MBEDCRYPTO_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */
+#define MBEDCRYPTO_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */
+
+#define MBEDCRYPTO_RSA_SIGN 1 /**< Identifier for RSA signature operations. */
+#define MBEDCRYPTO_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */
+
+#define MBEDCRYPTO_RSA_SALT_LEN_ANY -1
+
+/*
+ * The above constants may be used even if the RSA module is compile out,
+ * eg for alternative (PKCS#11) RSA implemenations in the PK layers.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_RSA_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief The RSA context structure.
+ *
+ * \note Direct manipulation of the members of this structure
+ * is deprecated. All manipulation should instead be done through
+ * the public interface functions.
+ */
+typedef struct
+{
+ int ver; /*!< Always 0.*/
+ size_t len; /*!< The size of \p N in Bytes. */
+
+ mbedcrypto_mpi N; /*!< The public modulus. */
+ mbedcrypto_mpi E; /*!< The public exponent. */
+
+ mbedcrypto_mpi D; /*!< The private exponent. */
+ mbedcrypto_mpi P; /*!< The first prime factor. */
+ mbedcrypto_mpi Q; /*!< The second prime factor. */
+
+ mbedcrypto_mpi DP; /*!< <code>D % (P - 1)</code>. */
+ mbedcrypto_mpi DQ; /*!< <code>D % (Q - 1)</code>. */
+ mbedcrypto_mpi QP; /*!< <code>1 / (Q % P)</code>. */
+
+ mbedcrypto_mpi RN; /*!< cached <code>R^2 mod N</code>. */
+
+ mbedcrypto_mpi RP; /*!< cached <code>R^2 mod P</code>. */
+ mbedcrypto_mpi RQ; /*!< cached <code>R^2 mod Q</code>. */
+
+ mbedcrypto_mpi Vi; /*!< The cached blinding value. */
+ mbedcrypto_mpi Vf; /*!< The cached un-blinding value. */
+
+ int padding; /*!< Selects padding mode:
+ #MBEDCRYPTO_RSA_PKCS_V15 for 1.5 padding and
+ #MBEDCRYPTO_RSA_PKCS_V21 for OAEP or PSS. */
+ int hash_id; /*!< Hash identifier of mbedcrypto_md_type_t type,
+ as specified in md.h for use in the MGF
+ mask generating function used in the
+ EME-OAEP and EMSA-PSS encodings. */
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_threading_mutex_t mutex; /*!< Thread-safety mutex. */
+#endif
+}
+mbedcrypto_rsa_context;
+
+#else /* MBEDCRYPTO_RSA_ALT */
+#include "rsa_alt.h"
+#endif /* MBEDCRYPTO_RSA_ALT */
+
+/**
+ * \brief This function initializes an RSA context.
+ *
+ * \note Set padding to #MBEDCRYPTO_RSA_PKCS_V21 for the RSAES-OAEP
+ * encryption scheme and the RSASSA-PSS signature scheme.
+ *
+ * \note The \p hash_id parameter is ignored when using
+ * #MBEDCRYPTO_RSA_PKCS_V15 padding.
+ *
+ * \note The choice of padding mode is strictly enforced for private key
+ * operations, since there might be security concerns in
+ * mixing padding modes. For public key operations it is
+ * a default value, which can be overriden by calling specific
+ * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions.
+ *
+ * \note The hash selected in \p hash_id is always used for OEAP
+ * encryption. For PSS signatures, it is always used for
+ * making signatures, but can be overriden for verifying them.
+ * If set to #MBEDCRYPTO_MD_NONE, it is always overriden.
+ *
+ * \param ctx The RSA context to initialize.
+ * \param padding Selects padding mode: #MBEDCRYPTO_RSA_PKCS_V15 or
+ * #MBEDCRYPTO_RSA_PKCS_V21.
+ * \param hash_id The hash identifier of #mbedcrypto_md_type_t type, if
+ * \p padding is #MBEDCRYPTO_RSA_PKCS_V21.
+ */
+void mbedcrypto_rsa_init( mbedcrypto_rsa_context *ctx,
+ int padding,
+ int hash_id);
+
+/**
+ * \brief This function imports a set of core parameters into an
+ * RSA context.
+ *
+ * \note This function can be called multiple times for successive
+ * imports, if the parameters are not simultaneously present.
+ *
+ * Any sequence of calls to this function should be followed
+ * by a call to mbedcrypto_rsa_complete(), which checks and
+ * completes the provided information to a ready-for-use
+ * public or private RSA key.
+ *
+ * \note See mbedcrypto_rsa_complete() for more information on which
+ * parameters are necessary to set up a private or public
+ * RSA key.
+ *
+ * \note The imported parameters are copied and need not be preserved
+ * for the lifetime of the RSA context being set up.
+ *
+ * \param ctx The initialized RSA context to store the parameters in.
+ * \param N The RSA modulus, or NULL.
+ * \param P The first prime factor of \p N, or NULL.
+ * \param Q The second prime factor of \p N, or NULL.
+ * \param D The private exponent, or NULL.
+ * \param E The public exponent, or NULL.
+ *
+ * \return \c 0 on success.
+ * \return A non-zero error code on failure.
+ */
+int mbedcrypto_rsa_import( mbedcrypto_rsa_context *ctx,
+ const mbedcrypto_mpi *N,
+ const mbedcrypto_mpi *P, const mbedcrypto_mpi *Q,
+ const mbedcrypto_mpi *D, const mbedcrypto_mpi *E );
+
+/**
+ * \brief This function imports core RSA parameters, in raw big-endian
+ * binary format, into an RSA context.
+ *
+ * \note This function can be called multiple times for successive
+ * imports, if the parameters are not simultaneously present.
+ *
+ * Any sequence of calls to this function should be followed
+ * by a call to mbedcrypto_rsa_complete(), which checks and
+ * completes the provided information to a ready-for-use
+ * public or private RSA key.
+ *
+ * \note See mbedcrypto_rsa_complete() for more information on which
+ * parameters are necessary to set up a private or public
+ * RSA key.
+ *
+ * \note The imported parameters are copied and need not be preserved
+ * for the lifetime of the RSA context being set up.
+ *
+ * \param ctx The initialized RSA context to store the parameters in.
+ * \param N The RSA modulus, or NULL.
+ * \param N_len The Byte length of \p N, ignored if \p N == NULL.
+ * \param P The first prime factor of \p N, or NULL.
+ * \param P_len The Byte length of \p P, ignored if \p P == NULL.
+ * \param Q The second prime factor of \p N, or NULL.
+ * \param Q_len The Byte length of \p Q, ignored if \p Q == NULL.
+ * \param D The private exponent, or NULL.
+ * \param D_len The Byte length of \p D, ignored if \p D == NULL.
+ * \param E The public exponent, or NULL.
+ * \param E_len The Byte length of \p E, ignored if \p E == NULL.
+ *
+ * \return \c 0 on success.
+ * \return A non-zero error code on failure.
+ */
+int mbedcrypto_rsa_import_raw( mbedcrypto_rsa_context *ctx,
+ unsigned char const *N, size_t N_len,
+ unsigned char const *P, size_t P_len,
+ unsigned char const *Q, size_t Q_len,
+ unsigned char const *D, size_t D_len,
+ unsigned char const *E, size_t E_len );
+
+/**
+ * \brief This function completes an RSA context from
+ * a set of imported core parameters.
+ *
+ * To setup an RSA public key, precisely \p N and \p E
+ * must have been imported.
+ *
+ * To setup an RSA private key, sufficient information must
+ * be present for the other parameters to be derivable.
+ *
+ * The default implementation supports the following:
+ * <ul><li>Derive \p P, \p Q from \p N, \p D, \p E.</li>
+ * <li>Derive \p N, \p D from \p P, \p Q, \p E.</li></ul>
+ * Alternative implementations need not support these.
+ *
+ * If this function runs successfully, it guarantees that
+ * the RSA context can be used for RSA operations without
+ * the risk of failure or crash.
+ *
+ * \warning This function need not perform consistency checks
+ * for the imported parameters. In particular, parameters that
+ * are not needed by the implementation might be silently
+ * discarded and left unchecked. To check the consistency
+ * of the key material, see mbedcrypto_rsa_check_privkey().
+ *
+ * \param ctx The initialized RSA context holding imported parameters.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA if the attempted derivations
+ * failed.
+ *
+ */
+int mbedcrypto_rsa_complete( mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief This function exports the core parameters of an RSA key.
+ *
+ * If this function runs successfully, the non-NULL buffers
+ * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully
+ * written, with additional unused space filled leading by
+ * zero Bytes.
+ *
+ * Possible reasons for returning
+ * #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION:<ul>
+ * <li>An alternative RSA implementation is in use, which
+ * stores the key externally, and either cannot or should
+ * not export it into RAM.</li>
+ * <li>A SW or HW implementation might not support a certain
+ * deduction. For example, \p P, \p Q from \p N, \p D,
+ * and \p E if the former are not part of the
+ * implementation.</li></ul>
+ *
+ * If the function fails due to an unsupported operation,
+ * the RSA context stays intact and remains usable.
+ *
+ * \param ctx The initialized RSA context.
+ * \param N The MPI to hold the RSA modulus, or NULL.
+ * \param P The MPI to hold the first prime factor of \p N, or NULL.
+ * \param Q The MPI to hold the second prime factor of \p N, or NULL.
+ * \param D The MPI to hold the private exponent, or NULL.
+ * \param E The MPI to hold the public exponent, or NULL.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION if exporting the
+ * requested parameters cannot be done due to missing
+ * functionality or because of security policies.
+ * \return A non-zero return code on any other failure.
+ *
+ */
+int mbedcrypto_rsa_export( const mbedcrypto_rsa_context *ctx,
+ mbedcrypto_mpi *N, mbedcrypto_mpi *P, mbedcrypto_mpi *Q,
+ mbedcrypto_mpi *D, mbedcrypto_mpi *E );
+
+/**
+ * \brief This function exports core parameters of an RSA key
+ * in raw big-endian binary format.
+ *
+ * If this function runs successfully, the non-NULL buffers
+ * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully
+ * written, with additional unused space filled leading by
+ * zero Bytes.
+ *
+ * Possible reasons for returning
+ * #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION:<ul>
+ * <li>An alternative RSA implementation is in use, which
+ * stores the key externally, and either cannot or should
+ * not export it into RAM.</li>
+ * <li>A SW or HW implementation might not support a certain
+ * deduction. For example, \p P, \p Q from \p N, \p D,
+ * and \p E if the former are not part of the
+ * implementation.</li></ul>
+ * If the function fails due to an unsupported operation,
+ * the RSA context stays intact and remains usable.
+ *
+ * \note The length parameters are ignored if the corresponding
+ * buffer pointers are NULL.
+ *
+ * \param ctx The initialized RSA context.
+ * \param N The Byte array to store the RSA modulus, or NULL.
+ * \param N_len The size of the buffer for the modulus.
+ * \param P The Byte array to hold the first prime factor of \p N, or
+ * NULL.
+ * \param P_len The size of the buffer for the first prime factor.
+ * \param Q The Byte array to hold the second prime factor of \p N, or
+ * NULL.
+ * \param Q_len The size of the buffer for the second prime factor.
+ * \param D The Byte array to hold the private exponent, or NULL.
+ * \param D_len The size of the buffer for the private exponent.
+ * \param E The Byte array to hold the public exponent, or NULL.
+ * \param E_len The size of the buffer for the public exponent.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION if exporting the
+ * requested parameters cannot be done due to missing
+ * functionality or because of security policies.
+ * \return A non-zero return code on any other failure.
+ */
+int mbedcrypto_rsa_export_raw( const mbedcrypto_rsa_context *ctx,
+ unsigned char *N, size_t N_len,
+ unsigned char *P, size_t P_len,
+ unsigned char *Q, size_t Q_len,
+ unsigned char *D, size_t D_len,
+ unsigned char *E, size_t E_len );
+
+/**
+ * \brief This function exports CRT parameters of a private RSA key.
+ *
+ * \note Alternative RSA implementations not using CRT-parameters
+ * internally can implement this function based on
+ * mbedcrypto_rsa_deduce_opt().
+ *
+ * \param ctx The initialized RSA context.
+ * \param DP The MPI to hold D modulo P-1, or NULL.
+ * \param DQ The MPI to hold D modulo Q-1, or NULL.
+ * \param QP The MPI to hold modular inverse of Q modulo P, or NULL.
+ *
+ * \return \c 0 on success.
+ * \return A non-zero error code on failure.
+ *
+ */
+int mbedcrypto_rsa_export_crt( const mbedcrypto_rsa_context *ctx,
+ mbedcrypto_mpi *DP, mbedcrypto_mpi *DQ, mbedcrypto_mpi *QP );
+
+/**
+ * \brief This function sets padding for an already initialized RSA
+ * context. See mbedcrypto_rsa_init() for details.
+ *
+ * \param ctx The RSA context to be set.
+ * \param padding Selects padding mode: #MBEDCRYPTO_RSA_PKCS_V15 or
+ * #MBEDCRYPTO_RSA_PKCS_V21.
+ * \param hash_id The #MBEDCRYPTO_RSA_PKCS_V21 hash identifier.
+ */
+void mbedcrypto_rsa_set_padding( mbedcrypto_rsa_context *ctx, int padding,
+ int hash_id);
+
+/**
+ * \brief This function retrieves the length of RSA modulus in Bytes.
+ *
+ * \param ctx The initialized RSA context.
+ *
+ * \return The length of the RSA modulus in Bytes.
+ *
+ */
+size_t mbedcrypto_rsa_get_len( const mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief This function retrieves the length of the RSA modulus in bits.
+ *
+ * \param ctx The initialized RSA context.
+ *
+ * \return The length of the RSA modulus in bits.
+ *
+ */
+size_t mbedcrypto_rsa_get_bitlen( const mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief This function generates an RSA keypair.
+ *
+ * \note mbedcrypto_rsa_init() must be called before this function,
+ * to set up the RSA context.
+ *
+ * \param ctx The RSA context used to hold the key.
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG context.
+ * \param nbits The size of the public key in bits.
+ * \param exponent The public exponent. For example, 65537.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_gen_key( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ unsigned int nbits, int exponent );
+
+/**
+ * \brief This function checks if a context contains at least an RSA
+ * public key.
+ *
+ * If the function runs successfully, it is guaranteed that
+ * enough information is present to perform an RSA public key
+ * operation using mbedcrypto_rsa_public().
+ *
+ * \param ctx The RSA context to check.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ *
+ */
+int mbedcrypto_rsa_check_pubkey( const mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief This function checks if a context contains an RSA private key
+ * and perform basic consistency checks.
+ *
+ * \note The consistency checks performed by this function not only
+ * ensure that mbedcrypto_rsa_private() can be called successfully
+ * on the given context, but that the various parameters are
+ * mutually consistent with high probability, in the sense that
+ * mbedcrypto_rsa_public() and mbedcrypto_rsa_private() are inverses.
+ *
+ * \warning This function should catch accidental misconfigurations
+ * like swapping of parameters, but it cannot establish full
+ * trust in neither the quality nor the consistency of the key
+ * material that was used to setup the given RSA context:
+ * <ul><li>Consistency: Imported parameters that are irrelevant
+ * for the implementation might be silently dropped. If dropped,
+ * the current function does not have access to them,
+ * and therefore cannot check them. See mbedcrypto_rsa_complete().
+ * If you want to check the consistency of the entire
+ * content of an PKCS1-encoded RSA private key, for example, you
+ * should use mbedcrypto_rsa_validate_params() before setting
+ * up the RSA context.
+ * Additionally, if the implementation performs empirical checks,
+ * these checks substantiate but do not guarantee consistency.</li>
+ * <li>Quality: This function is not expected to perform
+ * extended quality assessments like checking that the prime
+ * factors are safe. Additionally, it is the responsibility of the
+ * user to ensure the trustworthiness of the source of his RSA
+ * parameters, which goes beyond what is effectively checkable
+ * by the library.</li></ul>
+ *
+ * \param ctx The RSA context to check.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_check_privkey( const mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief This function checks a public-private RSA key pair.
+ *
+ * It checks each of the contexts, and makes sure they match.
+ *
+ * \param pub The RSA context holding the public key.
+ * \param prv The RSA context holding the private key.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_check_pub_priv( const mbedcrypto_rsa_context *pub,
+ const mbedcrypto_rsa_context *prv );
+
+/**
+ * \brief This function performs an RSA public key operation.
+ *
+ * \note This function does not handle message padding.
+ *
+ * \note Make sure to set \p input[0] = 0 or ensure that
+ * input is smaller than \p N.
+ *
+ * \note The input and output buffers must be large
+ * enough. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \param ctx The RSA context.
+ * \param input The input buffer.
+ * \param output The output buffer.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_public( mbedcrypto_rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function performs an RSA private key operation.
+ *
+ * \note The input and output buffers must be large
+ * enough. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note Blinding is used if and only if a PRNG is provided.
+ *
+ * \note If blinding is used, both the base of exponentation
+ * and the exponent are blinded, providing protection
+ * against some side-channel attacks.
+ *
+ * \warning It is deprecated and a security risk to not provide
+ * a PRNG here and thereby prevent the use of blinding.
+ * Future versions of the library may enforce the presence
+ * of a PRNG.
+ *
+ * \param ctx The RSA context.
+ * \param f_rng The RNG function. Needed for blinding.
+ * \param p_rng The RNG context.
+ * \param input The input buffer.
+ * \param output The output buffer.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ *
+ */
+int mbedcrypto_rsa_private( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function adds the message padding, then performs an RSA
+ * operation.
+ *
+ * It is the generic wrapper for performing a PKCS#1 encryption
+ * operation using the \p mode from the context.
+ *
+ * \note The input and output buffers must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * implicitly set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA context.
+ * \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1
+ * encoding, and #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param ilen The length of the plaintext.
+ * \param input The buffer holding the data to encrypt.
+ * \param output The buffer used to hold the ciphertext.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_pkcs1_encrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t ilen,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function performs a PKCS#1 v1.5 encryption operation
+ * (RSAES-PKCS1-v1_5-ENCRYPT).
+ *
+ * \note The output buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * implicitly set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA context.
+ * \param f_rng The RNG function. Needed for padding and
+ * #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param ilen The length of the plaintext.
+ * \param input The buffer holding the data to encrypt.
+ * \param output The buffer used to hold the ciphertext.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsaes_pkcs1_v15_encrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t ilen,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function performs a PKCS#1 v2.1 OAEP encryption
+ * operation (RSAES-OAEP-ENCRYPT).
+ *
+ * \note The output buffer must be as large as the size
+ * of ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * implicitly set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA context.
+ * \param f_rng The RNG function. Needed for padding and PKCS#1 v2.1
+ * encoding and #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param label The buffer holding the custom label to use.
+ * \param label_len The length of the label.
+ * \param ilen The length of the plaintext.
+ * \param input The buffer holding the data to encrypt.
+ * \param output The buffer used to hold the ciphertext.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsaes_oaep_encrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ const unsigned char *label, size_t label_len,
+ size_t ilen,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function performs an RSA operation, then removes the
+ * message padding.
+ *
+ * It is the generic wrapper for performing a PKCS#1 decryption
+ * operation using the \p mode from the context.
+ *
+ * \note The output buffer length \c output_max_len should be
+ * as large as the size \p ctx->len of \p ctx->N (for example,
+ * 128 Bytes if RSA-1024 is used) to be able to hold an
+ * arbitrary decrypted message. If it is not large enough to
+ * hold the decryption of the particular ciphertext provided,
+ * the function returns \c MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE.
+ *
+ * \note The input buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA context.
+ * \param f_rng The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param olen The length of the plaintext.
+ * \param input The buffer holding the encrypted data.
+ * \param output The buffer used to hold the plaintext.
+ * \param output_max_len The maximum length of the output buffer.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_pkcs1_decrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len );
+
+/**
+ * \brief This function performs a PKCS#1 v1.5 decryption
+ * operation (RSAES-PKCS1-v1_5-DECRYPT).
+ *
+ * \note The output buffer length \c output_max_len should be
+ * as large as the size \p ctx->len of \p ctx->N, for example,
+ * 128 Bytes if RSA-1024 is used, to be able to hold an
+ * arbitrary decrypted message. If it is not large enough to
+ * hold the decryption of the particular ciphertext provided,
+ * the function returns #MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE.
+ *
+ * \note The input buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA context.
+ * \param f_rng The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param olen The length of the plaintext.
+ * \param input The buffer holding the encrypted data.
+ * \param output The buffer to hold the plaintext.
+ * \param output_max_len The maximum length of the output buffer.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ *
+ */
+int mbedcrypto_rsa_rsaes_pkcs1_v15_decrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len );
+
+/**
+ * \brief This function performs a PKCS#1 v2.1 OAEP decryption
+ * operation (RSAES-OAEP-DECRYPT).
+ *
+ * \note The output buffer length \c output_max_len should be
+ * as large as the size \p ctx->len of \p ctx->N, for
+ * example, 128 Bytes if RSA-1024 is used, to be able to
+ * hold an arbitrary decrypted message. If it is not
+ * large enough to hold the decryption of the particular
+ * ciphertext provided, the function returns
+ * #MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE.
+ *
+ * \note The input buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA context.
+ * \param f_rng The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param label The buffer holding the custom label to use.
+ * \param label_len The length of the label.
+ * \param olen The length of the plaintext.
+ * \param input The buffer holding the encrypted data.
+ * \param output The buffer to hold the plaintext.
+ * \param output_max_len The maximum length of the output buffer.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsaes_oaep_decrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ const unsigned char *label, size_t label_len,
+ size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len );
+
+/**
+ * \brief This function performs a private RSA operation to sign
+ * a message digest using PKCS#1.
+ *
+ * It is the generic wrapper for performing a PKCS#1
+ * signature using the \p mode from the context.
+ *
+ * \note The \p sig buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note For PKCS#1 v2.1 encoding, see comments on
+ * mbedcrypto_rsa_rsassa_pss_sign() for details on
+ * \p md_alg and \p hash_id.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA context.
+ * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for
+ * #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg The message-digest algorithm used to hash the original data.
+ * Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash The buffer holding the message digest.
+ * \param sig The buffer to hold the ciphertext.
+ *
+ * \return \c 0 if the signing operation was successful.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_pkcs1_sign( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief This function performs a PKCS#1 v1.5 signature
+ * operation (RSASSA-PKCS1-v1_5-SIGN).
+ *
+ * \note The \p sig buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA context.
+ * \param f_rng The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg The message-digest algorithm used to hash the original data.
+ * Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash The buffer holding the message digest.
+ * \param sig The buffer to hold the ciphertext.
+ *
+ * \return \c 0 if the signing operation was successful.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsassa_pkcs1_v15_sign( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief This function performs a PKCS#1 v2.1 PSS signature
+ * operation (RSASSA-PSS-SIGN).
+ *
+ * \note The \p sig buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note The \p hash_id in the RSA context is the one used for the
+ * encoding. \p md_alg in the function call is the type of hash
+ * that is encoded. According to <em>RFC-3447: Public-Key
+ * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography
+ * Specifications</em> it is advised to keep both hashes the
+ * same.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PUBLIC mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * implicitly set to #MBEDCRYPTO_RSA_PRIVATE.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PUBLIC and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA context.
+ * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for
+ * #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg The message-digest algorithm used to hash the original data.
+ * Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash The buffer holding the message digest.
+ * \param sig The buffer to hold the ciphertext.
+ *
+ * \return \c 0 if the signing operation was successful.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsassa_pss_sign( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
+
+/**
+ * \brief This function performs a public RSA operation and checks
+ * the message digest.
+ *
+ * This is the generic wrapper for performing a PKCS#1
+ * verification using the mode from the context.
+ *
+ * \note The \p sig buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note For PKCS#1 v2.1 encoding, see comments on
+ * mbedcrypto_rsa_rsassa_pss_verify() about \p md_alg and
+ * \p hash_id.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA public key context.
+ * \param f_rng The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg The message-digest algorithm used to hash the original data.
+ * Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash The buffer holding the message digest.
+ * \param sig The buffer holding the ciphertext.
+ *
+ * \return \c 0 if the verify operation was successful.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_pkcs1_verify( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ const unsigned char *sig );
+
+/**
+ * \brief This function performs a PKCS#1 v1.5 verification
+ * operation (RSASSA-PKCS1-v1_5-VERIFY).
+ *
+ * \note The \p sig buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA public key context.
+ * \param f_rng The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg The message-digest algorithm used to hash the original data.
+ * Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash The buffer holding the message digest.
+ * \param sig The buffer holding the ciphertext.
+ *
+ * \return \c 0 if the verify operation was successful.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsassa_pkcs1_v15_verify( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ const unsigned char *sig );
+
+/**
+ * \brief This function performs a PKCS#1 v2.1 PSS verification
+ * operation (RSASSA-PSS-VERIFY).
+ *
+ * The hash function for the MGF mask generating function
+ * is that specified in the RSA context.
+ *
+ * \note The \p sig buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note The \p hash_id in the RSA context is the one used for the
+ * verification. \p md_alg in the function call is the type of
+ * hash that is verified. According to <em>RFC-3447: Public-Key
+ * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography
+ * Specifications</em> it is advised to keep both hashes the
+ * same. If \p hash_id in the RSA context is unset,
+ * the \p md_alg from the function call is used.
+ *
+ * \deprecated It is deprecated and discouraged to call this function
+ * in #MBEDCRYPTO_RSA_PRIVATE mode. Future versions of the library
+ * are likely to remove the \p mode argument and have it
+ * implicitly set to #MBEDCRYPTO_RSA_PUBLIC.
+ *
+ * \note Alternative implementations of RSA need not support
+ * mode being set to #MBEDCRYPTO_RSA_PRIVATE and might instead
+ * return #MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION.
+ *
+ * \param ctx The RSA public key context.
+ * \param f_rng The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg The message-digest algorithm used to hash the original data.
+ * Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDCRYPTO_MD_NONE.
+ * \param hash The buffer holding the message digest.
+ * \param sig The buffer holding the ciphertext.
+ *
+ * \return \c 0 if the verify operation was successful.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsassa_pss_verify( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ const unsigned char *sig );
+
+/**
+ * \brief This function performs a PKCS#1 v2.1 PSS verification
+ * operation (RSASSA-PSS-VERIFY).
+ *
+ * The hash function for the MGF mask generating function
+ * is that specified in \p mgf1_hash_id.
+ *
+ * \note The \p sig buffer must be as large as the size
+ * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
+ *
+ * \note The \p hash_id in the RSA context is ignored.
+ *
+ * \param ctx The RSA public key context.
+ * \param f_rng The RNG function. Only needed for #MBEDCRYPTO_RSA_PRIVATE.
+ * \param p_rng The RNG context.
+ * \param mode #MBEDCRYPTO_RSA_PUBLIC or #MBEDCRYPTO_RSA_PRIVATE.
+ * \param md_alg The message-digest algorithm used to hash the original data.
+ * Use #MBEDCRYPTO_MD_NONE for signing raw data.
+ * \param hashlen The length of the message digest. Only used if \p md_alg is
+ * #MBEDCRYPTO_MD_NONE.
+ * \param hash The buffer holding the message digest.
+ * \param mgf1_hash_id The message digest used for mask generation.
+ * \param expected_salt_len The length of the salt used in padding. Use
+ * #MBEDCRYPTO_RSA_SALT_LEN_ANY to accept any salt length.
+ * \param sig The buffer holding the ciphertext.
+ *
+ * \return \c 0 if the verify operation was successful.
+ * \return An \c MBEDCRYPTO_ERR_RSA_XXX error code on failure.
+ */
+int mbedcrypto_rsa_rsassa_pss_verify_ext( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ mbedcrypto_md_type_t mgf1_hash_id,
+ int expected_salt_len,
+ const unsigned char *sig );
+
+/**
+ * \brief This function copies the components of an RSA context.
+ *
+ * \param dst The destination context.
+ * \param src The source context.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDCRYPTO_ERR_MPI_ALLOC_FAILED on memory allocation failure.
+ */
+int mbedcrypto_rsa_copy( mbedcrypto_rsa_context *dst, const mbedcrypto_rsa_context *src );
+
+/**
+ * \brief This function frees the components of an RSA key.
+ *
+ * \param ctx The RSA Context to free.
+ */
+void mbedcrypto_rsa_free( mbedcrypto_rsa_context *ctx );
+
+/**
+ * \brief The RSA checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedcrypto_rsa_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* rsa.h */
diff --git a/include/mbedcrypto/rsa_internal.h b/include/mbedcrypto/rsa_internal.h
new file mode 100644
index 0000000..635fa18
--- /dev/null
+++ b/include/mbedcrypto/rsa_internal.h
@@ -0,0 +1,226 @@
+/**
+ * \file rsa_internal.h
+ *
+ * \brief Context-independent RSA helper functions
+ *
+ * This module declares some RSA-related helper functions useful when
+ * implementing the RSA interface. These functions are provided in a separate
+ * compilation unit in order to make it easy for designers of alternative RSA
+ * implementations to use them in their own code, as it is conceived that the
+ * functionality they provide will be necessary for most complete
+ * implementations.
+ *
+ * End-users of Mbed Crypto who are not providing their own alternative RSA
+ * implementations should not use these functions directly, and should instead
+ * use only the functions declared in rsa.h.
+ *
+ * The interface provided by this module will be maintained through LTS (Long
+ * Term Support) branches of Mbed Crypto, but may otherwise be subject to change,
+ * and must be considered an internal interface of the library.
+ *
+ * There are two classes of helper functions:
+ *
+ * (1) Parameter-generating helpers. These are:
+ * - mbedcrypto_rsa_deduce_primes
+ * - mbedcrypto_rsa_deduce_private_exponent
+ * - mbedcrypto_rsa_deduce_crt
+ * Each of these functions takes a set of core RSA parameters and
+ * generates some other, or CRT related parameters.
+ *
+ * (2) Parameter-checking helpers. These are:
+ * - mbedcrypto_rsa_validate_params
+ * - mbedcrypto_rsa_validate_crt
+ * They take a set of core or CRT related RSA parameters and check their
+ * validity.
+ *
+ */
+/*
+ * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+
+#ifndef MBEDCRYPTO_RSA_INTERNAL_H
+#define MBEDCRYPTO_RSA_INTERNAL_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "bignum.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \brief Compute RSA prime moduli P, Q from public modulus N=PQ
+ * and a pair of private and public key.
+ *
+ * \note This is a 'static' helper function not operating on
+ * an RSA context. Alternative implementations need not
+ * overwrite it.
+ *
+ * \param N RSA modulus N = PQ, with P, Q to be found
+ * \param E RSA public exponent
+ * \param D RSA private exponent
+ * \param P Pointer to MPI holding first prime factor of N on success
+ * \param Q Pointer to MPI holding second prime factor of N on success
+ *
+ * \return
+ * - 0 if successful. In this case, P and Q constitute a
+ * factorization of N.
+ * - A non-zero error code otherwise.
+ *
+ * \note It is neither checked that P, Q are prime nor that
+ * D, E are modular inverses wrt. P-1 and Q-1. For that,
+ * use the helper function \c mbedcrypto_rsa_validate_params.
+ *
+ */
+int mbedcrypto_rsa_deduce_primes( mbedcrypto_mpi const *N, mbedcrypto_mpi const *E,
+ mbedcrypto_mpi const *D,
+ mbedcrypto_mpi *P, mbedcrypto_mpi *Q );
+
+/**
+ * \brief Compute RSA private exponent from
+ * prime moduli and public key.
+ *
+ * \note This is a 'static' helper function not operating on
+ * an RSA context. Alternative implementations need not
+ * overwrite it.
+ *
+ * \param P First prime factor of RSA modulus
+ * \param Q Second prime factor of RSA modulus
+ * \param E RSA public exponent
+ * \param D Pointer to MPI holding the private exponent on success.
+ *
+ * \return
+ * - 0 if successful. In this case, D is set to a simultaneous
+ * modular inverse of E modulo both P-1 and Q-1.
+ * - A non-zero error code otherwise.
+ *
+ * \note This function does not check whether P and Q are primes.
+ *
+ */
+int mbedcrypto_rsa_deduce_private_exponent( mbedcrypto_mpi const *P,
+ mbedcrypto_mpi const *Q,
+ mbedcrypto_mpi const *E,
+ mbedcrypto_mpi *D );
+
+
+/**
+ * \brief Generate RSA-CRT parameters
+ *
+ * \note This is a 'static' helper function not operating on
+ * an RSA context. Alternative implementations need not
+ * overwrite it.
+ *
+ * \param P First prime factor of N
+ * \param Q Second prime factor of N
+ * \param D RSA private exponent
+ * \param DP Output variable for D modulo P-1
+ * \param DQ Output variable for D modulo Q-1
+ * \param QP Output variable for the modular inverse of Q modulo P.
+ *
+ * \return 0 on success, non-zero error code otherwise.
+ *
+ * \note This function does not check whether P, Q are
+ * prime and whether D is a valid private exponent.
+ *
+ */
+int mbedcrypto_rsa_deduce_crt( const mbedcrypto_mpi *P, const mbedcrypto_mpi *Q,
+ const mbedcrypto_mpi *D, mbedcrypto_mpi *DP,
+ mbedcrypto_mpi *DQ, mbedcrypto_mpi *QP );
+
+
+/**
+ * \brief Check validity of core RSA parameters
+ *
+ * \note This is a 'static' helper function not operating on
+ * an RSA context. Alternative implementations need not
+ * overwrite it.
+ *
+ * \param N RSA modulus N = PQ
+ * \param P First prime factor of N
+ * \param Q Second prime factor of N
+ * \param D RSA private exponent
+ * \param E RSA public exponent
+ * \param f_rng PRNG to be used for primality check, or NULL
+ * \param p_rng PRNG context for f_rng, or NULL
+ *
+ * \return
+ * - 0 if the following conditions are satisfied
+ * if all relevant parameters are provided:
+ * - P prime if f_rng != NULL (%)
+ * - Q prime if f_rng != NULL (%)
+ * - 1 < N = P * Q
+ * - 1 < D, E < N
+ * - D and E are modular inverses modulo P-1 and Q-1
+ * (%) This is only done if MBEDCRYPTO_GENPRIME is defined.
+ * - A non-zero error code otherwise.
+ *
+ * \note The function can be used with a restricted set of arguments
+ * to perform specific checks only. E.g., calling it with
+ * (-,P,-,-,-) and a PRNG amounts to a primality check for P.
+ */
+int mbedcrypto_rsa_validate_params( const mbedcrypto_mpi *N, const mbedcrypto_mpi *P,
+ const mbedcrypto_mpi *Q, const mbedcrypto_mpi *D,
+ const mbedcrypto_mpi *E,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
+/**
+ * \brief Check validity of RSA CRT parameters
+ *
+ * \note This is a 'static' helper function not operating on
+ * an RSA context. Alternative implementations need not
+ * overwrite it.
+ *
+ * \param P First prime factor of RSA modulus
+ * \param Q Second prime factor of RSA modulus
+ * \param D RSA private exponent
+ * \param DP MPI to check for D modulo P-1
+ * \param DQ MPI to check for D modulo P-1
+ * \param QP MPI to check for the modular inverse of Q modulo P.
+ *
+ * \return
+ * - 0 if the following conditions are satisfied:
+ * - D = DP mod P-1 if P, D, DP != NULL
+ * - Q = DQ mod P-1 if P, D, DQ != NULL
+ * - QP = Q^-1 mod P if P, Q, QP != NULL
+ * - \c MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED if check failed,
+ * potentially including \c MBEDCRYPTO_ERR_MPI_XXX if some
+ * MPI calculations failed.
+ * - \c MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA if insufficient
+ * data was provided to check DP, DQ or QP.
+ *
+ * \note The function can be used with a restricted set of arguments
+ * to perform specific checks only. E.g., calling it with the
+ * parameters (P, -, D, DP, -, -) will check DP = D mod P-1.
+ */
+int mbedcrypto_rsa_validate_crt( const mbedcrypto_mpi *P, const mbedcrypto_mpi *Q,
+ const mbedcrypto_mpi *D, const mbedcrypto_mpi *DP,
+ const mbedcrypto_mpi *DQ, const mbedcrypto_mpi *QP );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* rsa_internal.h */
diff --git a/include/mbedcrypto/sha1.h b/include/mbedcrypto/sha1.h
new file mode 100644
index 0000000..9f7fe5a
--- /dev/null
+++ b/include/mbedcrypto/sha1.h
@@ -0,0 +1,324 @@
+/**
+ * \file sha1.h
+ *
+ * \brief This file contains SHA-1 definitions and functions.
+ *
+ * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in
+ * <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use constitutes
+ * a security risk. We recommend considering stronger message
+ * digests instead.
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_SHA1_H
+#define MBEDCRYPTO_SHA1_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_SHA1_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief The SHA-1 context structure.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< The number of Bytes processed. */
+ uint32_t state[5]; /*!< The intermediate digest state. */
+ unsigned char buffer[64]; /*!< The data block being processed. */
+}
+mbedcrypto_sha1_context;
+
+#else /* MBEDCRYPTO_SHA1_ALT */
+#include "sha1_alt.h"
+#endif /* MBEDCRYPTO_SHA1_ALT */
+
+/**
+ * \brief This function initializes a SHA-1 context.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \param ctx The SHA-1 context to initialize.
+ *
+ */
+void mbedcrypto_sha1_init( mbedcrypto_sha1_context *ctx );
+
+/**
+ * \brief This function clears a SHA-1 context.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \param ctx The SHA-1 context to clear.
+ *
+ */
+void mbedcrypto_sha1_free( mbedcrypto_sha1_context *ctx );
+
+/**
+ * \brief This function clones the state of a SHA-1 context.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \param dst The SHA-1 context to clone to.
+ * \param src The SHA-1 context to clone from.
+ *
+ */
+void mbedcrypto_sha1_clone( mbedcrypto_sha1_context *dst,
+ const mbedcrypto_sha1_context *src );
+
+/**
+ * \brief This function starts a SHA-1 checksum calculation.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \param ctx The SHA-1 context to initialize.
+ *
+ * \return \c 0 on success.
+ *
+ */
+int mbedcrypto_sha1_starts_ret( mbedcrypto_sha1_context *ctx );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing SHA-1
+ * checksum calculation.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \param ctx The SHA-1 context.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_sha1_update_ret( mbedcrypto_sha1_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief This function finishes the SHA-1 operation, and writes
+ * the result to the output buffer.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \param ctx The SHA-1 context.
+ * \param output The SHA-1 checksum result.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_sha1_finish_ret( mbedcrypto_sha1_context *ctx,
+ unsigned char output[20] );
+
+/**
+ * \brief SHA-1 process data block (internal use only).
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \param ctx The SHA-1 context.
+ * \param data The data block being processed.
+ *
+ * \return \c 0 on success.
+ *
+ */
+int mbedcrypto_internal_sha1_process( mbedcrypto_sha1_context *ctx,
+ const unsigned char data[64] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief This function starts a SHA-1 checksum calculation.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \deprecated Superseded by mbedcrypto_sha1_starts_ret() in 2.7.0.
+ *
+ * \param ctx The SHA-1 context to initialize.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha1_starts( mbedcrypto_sha1_context *ctx );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing SHA-1
+ * checksum calculation.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \deprecated Superseded by mbedcrypto_sha1_update_ret() in 2.7.0.
+ *
+ * \param ctx The SHA-1 context.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha1_update( mbedcrypto_sha1_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief This function finishes the SHA-1 operation, and writes
+ * the result to the output buffer.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \deprecated Superseded by mbedcrypto_sha1_finish_ret() in 2.7.0.
+ *
+ * \param ctx The SHA-1 context.
+ * \param output The SHA-1 checksum result.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha1_finish( mbedcrypto_sha1_context *ctx,
+ unsigned char output[20] );
+
+/**
+ * \brief SHA-1 process data block (internal use only).
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \deprecated Superseded by mbedcrypto_internal_sha1_process() in 2.7.0.
+ *
+ * \param ctx The SHA-1 context.
+ * \param data The data block being processed.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha1_process( mbedcrypto_sha1_context *ctx,
+ const unsigned char data[64] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief This function calculates the SHA-1 checksum of a buffer.
+ *
+ * The function allocates the context, performs the
+ * calculation, and frees the context.
+ *
+ * The SHA-1 result is calculated as
+ * output = SHA-1(input buffer).
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ * \param output The SHA-1 checksum result.
+ *
+ * \return \c 0 on success.
+ *
+ */
+int mbedcrypto_sha1_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[20] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief This function calculates the SHA-1 checksum of a buffer.
+ *
+ * The function allocates the context, performs the
+ * calculation, and frees the context.
+ *
+ * The SHA-1 result is calculated as
+ * output = SHA-1(input buffer).
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \deprecated Superseded by mbedcrypto_sha1_ret() in 2.7.0
+ *
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ * \param output The SHA-1 checksum result.
+ *
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha1( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[20] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief The SHA-1 checkup routine.
+ *
+ * \warning SHA-1 is considered a weak message digest and its use
+ * constitutes a security risk. We recommend considering
+ * stronger message digests instead.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ *
+ */
+int mbedcrypto_sha1_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_sha1.h */
diff --git a/include/mbedcrypto/sha256.h b/include/mbedcrypto/sha256.h
new file mode 100644
index 0000000..edeb157
--- /dev/null
+++ b/include/mbedcrypto/sha256.h
@@ -0,0 +1,272 @@
+/**
+ * \file sha256.h
+ *
+ * \brief This file contains SHA-224 and SHA-256 definitions and functions.
+ *
+ * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic
+ * hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_SHA256_H
+#define MBEDCRYPTO_SHA256_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_SHA256_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief The SHA-256 context structure.
+ *
+ * The structure is used both for SHA-256 and for SHA-224
+ * checksum calculations. The choice between these two is
+ * made in the call to mbedcrypto_sha256_starts_ret().
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< The number of Bytes processed. */
+ uint32_t state[8]; /*!< The intermediate digest state. */
+ unsigned char buffer[64]; /*!< The data block being processed. */
+ int is224; /*!< Determines which function to use:
+ 0: Use SHA-256, or 1: Use SHA-224. */
+}
+mbedcrypto_sha256_context;
+
+#else /* MBEDCRYPTO_SHA256_ALT */
+#include "sha256_alt.h"
+#endif /* MBEDCRYPTO_SHA256_ALT */
+
+/**
+ * \brief This function initializes a SHA-256 context.
+ *
+ * \param ctx The SHA-256 context to initialize.
+ */
+void mbedcrypto_sha256_init( mbedcrypto_sha256_context *ctx );
+
+/**
+ * \brief This function clears a SHA-256 context.
+ *
+ * \param ctx The SHA-256 context to clear.
+ */
+void mbedcrypto_sha256_free( mbedcrypto_sha256_context *ctx );
+
+/**
+ * \brief This function clones the state of a SHA-256 context.
+ *
+ * \param dst The destination context.
+ * \param src The context to clone.
+ */
+void mbedcrypto_sha256_clone( mbedcrypto_sha256_context *dst,
+ const mbedcrypto_sha256_context *src );
+
+/**
+ * \brief This function starts a SHA-224 or SHA-256 checksum
+ * calculation.
+ *
+ * \param ctx The context to initialize.
+ * \param is224 Determines which function to use:
+ * 0: Use SHA-256, or 1: Use SHA-224.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_sha256_starts_ret( mbedcrypto_sha256_context *ctx, int is224 );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing
+ * SHA-256 checksum calculation.
+ *
+ * \param ctx The SHA-256 context.
+ * \param input The buffer holding the data.
+ * \param ilen The length of the input data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_sha256_update_ret( mbedcrypto_sha256_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief This function finishes the SHA-256 operation, and writes
+ * the result to the output buffer.
+ *
+ * \param ctx The SHA-256 context.
+ * \param output The SHA-224 or SHA-256 checksum result.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_sha256_finish_ret( mbedcrypto_sha256_context *ctx,
+ unsigned char output[32] );
+
+/**
+ * \brief This function processes a single data block within
+ * the ongoing SHA-256 computation. This function is for
+ * internal use only.
+ *
+ * \param ctx The SHA-256 context.
+ * \param data The buffer holding one block of data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_internal_sha256_process( mbedcrypto_sha256_context *ctx,
+ const unsigned char data[64] );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief This function starts a SHA-224 or SHA-256 checksum
+ * calculation.
+ *
+ *
+ * \deprecated Superseded by mbedcrypto_sha256_starts_ret() in 2.7.0.
+ *
+ * \param ctx The context to initialize.
+ * \param is224 Determines which function to use:
+ * 0: Use SHA-256, or 1: Use SHA-224.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha256_starts( mbedcrypto_sha256_context *ctx,
+ int is224 );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing
+ * SHA-256 checksum calculation.
+ *
+ * \deprecated Superseded by mbedcrypto_sha256_update_ret() in 2.7.0.
+ *
+ * \param ctx The SHA-256 context to initialize.
+ * \param input The buffer holding the data.
+ * \param ilen The length of the input data.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha256_update( mbedcrypto_sha256_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief This function finishes the SHA-256 operation, and writes
+ * the result to the output buffer.
+ *
+ * \deprecated Superseded by mbedcrypto_sha256_finish_ret() in 2.7.0.
+ *
+ * \param ctx The SHA-256 context.
+ * \param output The SHA-224 or SHA-256 checksum result.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha256_finish( mbedcrypto_sha256_context *ctx,
+ unsigned char output[32] );
+
+/**
+ * \brief This function processes a single data block within
+ * the ongoing SHA-256 computation. This function is for
+ * internal use only.
+ *
+ * \deprecated Superseded by mbedcrypto_internal_sha256_process() in 2.7.0.
+ *
+ * \param ctx The SHA-256 context.
+ * \param data The buffer holding one block of data.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha256_process( mbedcrypto_sha256_context *ctx,
+ const unsigned char data[64] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief This function calculates the SHA-224 or SHA-256
+ * checksum of a buffer.
+ *
+ * The function allocates the context, performs the
+ * calculation, and frees the context.
+ *
+ * The SHA-256 result is calculated as
+ * output = SHA-256(input buffer).
+ *
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ * \param output The SHA-224 or SHA-256 checksum result.
+ * \param is224 Determines which function to use:
+ * 0: Use SHA-256, or 1: Use SHA-224.
+ */
+int mbedcrypto_sha256_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[32],
+ int is224 );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+
+/**
+ * \brief This function calculates the SHA-224 or SHA-256 checksum
+ * of a buffer.
+ *
+ * The function allocates the context, performs the
+ * calculation, and frees the context.
+ *
+ * The SHA-256 result is calculated as
+ * output = SHA-256(input buffer).
+ *
+ * \deprecated Superseded by mbedcrypto_sha256_ret() in 2.7.0.
+ *
+ * \param input The buffer holding the data.
+ * \param ilen The length of the input data.
+ * \param output The SHA-224 or SHA-256 checksum result.
+ * \param is224 Determines which function to use:
+ * 0: Use SHA-256, or 1: Use SHA-224.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha256( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[32],
+ int is224 );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief The SHA-224 and SHA-256 checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedcrypto_sha256_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_sha256.h */
diff --git a/include/mbedcrypto/sha512.h b/include/mbedcrypto/sha512.h
new file mode 100644
index 0000000..f3f0fdf
--- /dev/null
+++ b/include/mbedcrypto/sha512.h
@@ -0,0 +1,270 @@
+/**
+ * \file sha512.h
+ * \brief This file contains SHA-384 and SHA-512 definitions and functions.
+ *
+ * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic
+ * hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_SHA512_H
+#define MBEDCRYPTO_SHA512_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_SHA512_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief The SHA-512 context structure.
+ *
+ * The structure is used both for SHA-384 and for SHA-512
+ * checksum calculations. The choice between these two is
+ * made in the call to mbedcrypto_sha512_starts_ret().
+ */
+typedef struct
+{
+ uint64_t total[2]; /*!< The number of Bytes processed. */
+ uint64_t state[8]; /*!< The intermediate digest state. */
+ unsigned char buffer[128]; /*!< The data block being processed. */
+ int is384; /*!< Determines which function to use:
+ 0: Use SHA-512, or 1: Use SHA-384. */
+}
+mbedcrypto_sha512_context;
+
+#else /* MBEDCRYPTO_SHA512_ALT */
+#include "sha512_alt.h"
+#endif /* MBEDCRYPTO_SHA512_ALT */
+
+/**
+ * \brief This function initializes a SHA-512 context.
+ *
+ * \param ctx The SHA-512 context to initialize.
+ */
+void mbedcrypto_sha512_init( mbedcrypto_sha512_context *ctx );
+
+/**
+ * \brief This function clears a SHA-512 context.
+ *
+ * \param ctx The SHA-512 context to clear.
+ */
+void mbedcrypto_sha512_free( mbedcrypto_sha512_context *ctx );
+
+/**
+ * \brief This function clones the state of a SHA-512 context.
+ *
+ * \param dst The destination context.
+ * \param src The context to clone.
+ */
+void mbedcrypto_sha512_clone( mbedcrypto_sha512_context *dst,
+ const mbedcrypto_sha512_context *src );
+
+/**
+ * \brief This function starts a SHA-384 or SHA-512 checksum
+ * calculation.
+ *
+ * \param ctx The SHA-512 context to initialize.
+ * \param is384 Determines which function to use:
+ * 0: Use SHA-512, or 1: Use SHA-384.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_sha512_starts_ret( mbedcrypto_sha512_context *ctx, int is384 );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing
+ * SHA-512 checksum calculation.
+ *
+ * \param ctx The SHA-512 context.
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_sha512_update_ret( mbedcrypto_sha512_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief This function finishes the SHA-512 operation, and writes
+ * the result to the output buffer. This function is for
+ * internal use only.
+ *
+ * \param ctx The SHA-512 context.
+ * \param output The SHA-384 or SHA-512 checksum result.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_sha512_finish_ret( mbedcrypto_sha512_context *ctx,
+ unsigned char output[64] );
+
+/**
+ * \brief This function processes a single data block within
+ * the ongoing SHA-512 computation.
+ *
+ * \param ctx The SHA-512 context.
+ * \param data The buffer holding one block of data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_internal_sha512_process( mbedcrypto_sha512_context *ctx,
+ const unsigned char data[128] );
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief This function starts a SHA-384 or SHA-512 checksum
+ * calculation.
+ *
+ * \deprecated Superseded by mbedcrypto_sha512_starts_ret() in 2.7.0
+ *
+ * \param ctx The SHA-512 context to initialize.
+ * \param is384 Determines which function to use:
+ * 0: Use SHA-512, or 1: Use SHA-384.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha512_starts( mbedcrypto_sha512_context *ctx,
+ int is384 );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing
+ * SHA-512 checksum calculation.
+ *
+ * \deprecated Superseded by mbedcrypto_sha512_update_ret() in 2.7.0.
+ *
+ * \param ctx The SHA-512 context.
+ * \param input The buffer holding the data.
+ * \param ilen The length of the input data.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha512_update( mbedcrypto_sha512_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief This function finishes the SHA-512 operation, and writes
+ * the result to the output buffer.
+ *
+ * \deprecated Superseded by mbedcrypto_sha512_finish_ret() in 2.7.0.
+ *
+ * \param ctx The SHA-512 context.
+ * \param output The SHA-384 or SHA-512 checksum result.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha512_finish( mbedcrypto_sha512_context *ctx,
+ unsigned char output[64] );
+
+/**
+ * \brief This function processes a single data block within
+ * the ongoing SHA-512 computation. This function is for
+ * internal use only.
+ *
+ * \deprecated Superseded by mbedcrypto_internal_sha512_process() in 2.7.0.
+ *
+ * \param ctx The SHA-512 context.
+ * \param data The buffer holding one block of data.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha512_process(
+ mbedcrypto_sha512_context *ctx,
+ const unsigned char data[128] );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/**
+ * \brief This function calculates the SHA-512 or SHA-384
+ * checksum of a buffer.
+ *
+ * The function allocates the context, performs the
+ * calculation, and frees the context.
+ *
+ * The SHA-512 result is calculated as
+ * output = SHA-512(input buffer).
+ *
+ * \param input The buffer holding the input data.
+ * \param ilen The length of the input data.
+ * \param output The SHA-384 or SHA-512 checksum result.
+ * \param is384 Determines which function to use:
+ * 0: Use SHA-512, or 1: Use SHA-384.
+ *
+ * \return \c 0 on success.
+ */
+int mbedcrypto_sha512_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[64],
+ int is384 );
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+#if defined(MBEDCRYPTO_DEPRECATED_WARNING)
+#define MBEDCRYPTO_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDCRYPTO_DEPRECATED
+#endif
+/**
+ * \brief This function calculates the SHA-512 or SHA-384
+ * checksum of a buffer.
+ *
+ * The function allocates the context, performs the
+ * calculation, and frees the context.
+ *
+ * The SHA-512 result is calculated as
+ * output = SHA-512(input buffer).
+ *
+ * \deprecated Superseded by mbedcrypto_sha512_ret() in 2.7.0
+ *
+ * \param input The buffer holding the data.
+ * \param ilen The length of the input data.
+ * \param output The SHA-384 or SHA-512 checksum result.
+ * \param is384 Determines which function to use:
+ * 0: Use SHA-512, or 1: Use SHA-384.
+ */
+MBEDCRYPTO_DEPRECATED void mbedcrypto_sha512( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[64],
+ int is384 );
+
+#undef MBEDCRYPTO_DEPRECATED
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+ /**
+ * \brief The SHA-384 or SHA-512 checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedcrypto_sha512_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedcrypto_sha512.h */
diff --git a/include/mbedcrypto/threading.h b/include/mbedcrypto/threading.h
new file mode 100644
index 0000000..8e14f6b
--- /dev/null
+++ b/include/mbedcrypto/threading.h
@@ -0,0 +1,111 @@
+/**
+ * \file threading.h
+ *
+ * \brief Threading abstraction layer
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_THREADING_H
+#define MBEDCRYPTO_THREADING_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MBEDCRYPTO_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */
+#define MBEDCRYPTO_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */
+#define MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */
+
+#if defined(MBEDCRYPTO_THREADING_PTHREAD)
+#include <pthread.h>
+typedef struct
+{
+ pthread_mutex_t mutex;
+ char is_valid;
+} mbedcrypto_threading_mutex_t;
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_ALT)
+/* You should define the mbedcrypto_threading_mutex_t type in your header */
+#include "threading_alt.h"
+
+/**
+ * \brief Set your alternate threading implementation function
+ * pointers and initialize global mutexes. If used, this
+ * function must be called once in the main thread before any
+ * other Mbed Crypto function is called, and
+ * mbedcrypto_threading_free_alt() must be called once in the main
+ * thread after all other Mbed Crypto functions.
+ *
+ * \note mutex_init() and mutex_free() don't return a status code.
+ * If mutex_init() fails, it should leave its argument (the
+ * mutex) in a state such that mutex_lock() will fail when
+ * called with this argument.
+ *
+ * \param mutex_init the init function implementation
+ * \param mutex_free the free function implementation
+ * \param mutex_lock the lock function implementation
+ * \param mutex_unlock the unlock function implementation
+ */
+void mbedcrypto_threading_set_alt( void (*mutex_init)( mbedcrypto_threading_mutex_t * ),
+ void (*mutex_free)( mbedcrypto_threading_mutex_t * ),
+ int (*mutex_lock)( mbedcrypto_threading_mutex_t * ),
+ int (*mutex_unlock)( mbedcrypto_threading_mutex_t * ) );
+
+/**
+ * \brief Free global mutexes.
+ */
+void mbedcrypto_threading_free_alt( void );
+#endif /* MBEDCRYPTO_THREADING_ALT */
+
+#if defined(MBEDCRYPTO_THREADING_C)
+/*
+ * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock
+ *
+ * All these functions are expected to work or the result will be undefined.
+ */
+extern void (*mbedcrypto_mutex_init)( mbedcrypto_threading_mutex_t *mutex );
+extern void (*mbedcrypto_mutex_free)( mbedcrypto_threading_mutex_t *mutex );
+extern int (*mbedcrypto_mutex_lock)( mbedcrypto_threading_mutex_t *mutex );
+extern int (*mbedcrypto_mutex_unlock)( mbedcrypto_threading_mutex_t *mutex );
+
+/*
+ * Global mutexes
+ */
+#if defined(MBEDCRYPTO_FS_IO)
+extern mbedcrypto_threading_mutex_t mbedcrypto_threading_readdir_mutex;
+#endif
+#if defined(MBEDCRYPTO_HAVE_TIME_DATE)
+extern mbedcrypto_threading_mutex_t mbedcrypto_threading_gmtime_mutex;
+#endif
+#endif /* MBEDCRYPTO_THREADING_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* threading.h */
diff --git a/include/mbedcrypto/xtea.h b/include/mbedcrypto/xtea.h
new file mode 100644
index 0000000..5db947d
--- /dev/null
+++ b/include/mbedcrypto/xtea.h
@@ -0,0 +1,133 @@
+/**
+ * \file xtea.h
+ *
+ * \brief XTEA block cipher (32-bit)
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+#ifndef MBEDCRYPTO_XTEA_H
+#define MBEDCRYPTO_XTEA_H
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define MBEDCRYPTO_XTEA_ENCRYPT 1
+#define MBEDCRYPTO_XTEA_DECRYPT 0
+
+#define MBEDCRYPTO_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */
+#define MBEDCRYPTO_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDCRYPTO_XTEA_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief XTEA context structure
+ */
+typedef struct
+{
+ uint32_t k[4]; /*!< key */
+}
+mbedcrypto_xtea_context;
+
+#else /* MBEDCRYPTO_XTEA_ALT */
+#include "xtea_alt.h"
+#endif /* MBEDCRYPTO_XTEA_ALT */
+
+/**
+ * \brief Initialize XTEA context
+ *
+ * \param ctx XTEA context to be initialized
+ */
+void mbedcrypto_xtea_init( mbedcrypto_xtea_context *ctx );
+
+/**
+ * \brief Clear XTEA context
+ *
+ * \param ctx XTEA context to be cleared
+ */
+void mbedcrypto_xtea_free( mbedcrypto_xtea_context *ctx );
+
+/**
+ * \brief XTEA key schedule
+ *
+ * \param ctx XTEA context to be initialized
+ * \param key the secret key
+ */
+void mbedcrypto_xtea_setup( mbedcrypto_xtea_context *ctx, const unsigned char key[16] );
+
+/**
+ * \brief XTEA cipher function
+ *
+ * \param ctx XTEA context
+ * \param mode MBEDCRYPTO_XTEA_ENCRYPT or MBEDCRYPTO_XTEA_DECRYPT
+ * \param input 8-byte input block
+ * \param output 8-byte output block
+ *
+ * \return 0 if successful
+ */
+int mbedcrypto_xtea_crypt_ecb( mbedcrypto_xtea_context *ctx,
+ int mode,
+ const unsigned char input[8],
+ unsigned char output[8] );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/**
+ * \brief XTEA CBC cipher function
+ *
+ * \param ctx XTEA context
+ * \param mode MBEDCRYPTO_XTEA_ENCRYPT or MBEDCRYPTO_XTEA_DECRYPT
+ * \param length the length of input, multiple of 8
+ * \param iv initialization vector for CBC mode
+ * \param input input block
+ * \param output output block
+ *
+ * \return 0 if successful,
+ * MBEDCRYPTO_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0
+ */
+int mbedcrypto_xtea_crypt_cbc( mbedcrypto_xtea_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output);
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedcrypto_xtea_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* xtea.h */
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
new file mode 100644
index 0000000..6d31322
--- /dev/null
+++ b/include/psa/crypto.h
@@ -0,0 +1,2839 @@
+/**
+ * \file psa/crypto.h
+ * \brief Platform Security Architecture cryptography module
+ */
+/*
+ * Copyright (C) 2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_H
+#define PSA_CRYPTO_H
+
+#include "crypto_platform.h"
+
+#include <stddef.h>
+
+#ifdef __DOXYGEN_ONLY__
+/* This __DOXYGEN_ONLY__ block contains mock definitions for things that
+ * must be defined in the crypto_platform.h header. These mock definitions
+ * are present in this file as a convenience to generate pretty-printed
+ * documentation that includes those definitions. */
+
+/** \defgroup platform Implementation-specific definitions
+ * @{
+ */
+
+/** \brief Key slot number.
+ *
+ * This type represents key slots. It must be an unsigned integral
+ * type. The choice of type is implementation-dependent.
+ * 0 is not a valid key slot number. The meaning of other values is
+ * implementation dependent.
+ *
+ * At any given point in time, each key slot either contains a
+ * cryptographic object, or is empty. Key slots are persistent:
+ * once set, the cryptographic object remains in the key slot until
+ * explicitly destroyed.
+ */
+typedef _unsigned_integral_type_ psa_key_slot_t;
+
+/**@}*/
+#endif /* __DOXYGEN_ONLY__ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \defgroup basic Basic definitions
+ * @{
+ */
+
+#if defined(PSA_SUCCESS)
+/* If PSA_SUCCESS is defined, assume that PSA crypto is being used
+ * together with PSA IPC, which also defines the identifier
+ * PSA_SUCCESS. We must not define PSA_SUCCESS ourselves in that case;
+ * the other error code names don't clash. Also define psa_status_t as
+ * an alias for the type used by PSA IPC. This is a temporary hack
+ * until we unify error reporting in PSA IPC and PSA crypto.
+ *
+ * Note that psa_defs.h must be included before this header!
+ */
+typedef psa_error_t psa_status_t;
+
+#else /* defined(PSA_SUCCESS) */
+
+/**
+ * \brief Function return status.
+ *
+ * This is either #PSA_SUCCESS (which is zero), indicating success,
+ * or a nonzero value indicating that an error occurred. Errors are
+ * encoded as one of the \c PSA_ERROR_xxx values defined here.
+ */
+typedef int32_t psa_status_t;
+
+/** The action was completed successfully. */
+#define PSA_SUCCESS ((psa_status_t)0)
+
+#endif /* !defined(PSA_SUCCESS) */
+
+/** An error occurred that does not correspond to any defined
+ * failure cause.
+ *
+ * Implementations may use this error code if none of the other standard
+ * error codes are applicable. */
+#define PSA_ERROR_UNKNOWN_ERROR ((psa_status_t)1)
+
+/** The requested operation or a parameter is not supported
+ * by this implementation.
+ *
+ * Implementations should return this error code when an enumeration
+ * parameter such as a key type, algorithm, etc. is not recognized.
+ * If a combination of parameters is recognized and identified as
+ * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */
+#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)2)
+
+/** The requested action is denied by a policy.
+ *
+ * Implementations should return this error code when the parameters
+ * are recognized as valid and supported, and a policy explicitly
+ * denies the requested operation.
+ *
+ * If a subset of the parameters of a function call identify a
+ * forbidden operation, and another subset of the parameters are
+ * not valid or not supported, it is unspecified whether the function
+ * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or
+ * #PSA_ERROR_INVALID_ARGUMENT. */
+#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)3)
+
+/** An output buffer is too small.
+ *
+ * Applications can call the \c PSA_xxx_SIZE macro listed in the function
+ * description to determine a sufficient buffer size.
+ *
+ * Implementations should preferably return this error code only
+ * in cases when performing the operation with a larger output
+ * buffer would succeed. However implementations may return this
+ * error if a function has invalid or unsupported parameters in addition
+ * to the parameters that determine the necessary output buffer size. */
+#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)4)
+
+/** A slot is occupied, but must be empty to carry out the
+ * requested action.
+ *
+ * If the slot number is invalid (i.e. the requested action could
+ * not be performed even after erasing the slot's content),
+ * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */
+#define PSA_ERROR_OCCUPIED_SLOT ((psa_status_t)5)
+
+/** A slot is empty, but must be occupied to carry out the
+ * requested action.
+ *
+ * If the slot number is invalid (i.e. the requested action could
+ * not be performed even after creating appropriate content in the slot),
+ * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */
+#define PSA_ERROR_EMPTY_SLOT ((psa_status_t)6)
+
+/** The requested action cannot be performed in the current state.
+ *
+ * Multipart operations return this error when one of the
+ * functions is called out of sequence. Refer to the function
+ * descriptions for permitted sequencing of functions.
+ *
+ * Implementations shall not return this error code to indicate
+ * that a key slot is occupied when it needs to be free or vice versa,
+ * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT
+ * as applicable. */
+#define PSA_ERROR_BAD_STATE ((psa_status_t)7)
+
+/** The parameters passed to the function are invalid.
+ *
+ * Implementations may return this error any time a parameter or
+ * combination of parameters are recognized as invalid.
+ *
+ * Implementations shall not return this error code to indicate
+ * that a key slot is occupied when it needs to be free or vice versa,
+ * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT
+ * as applicable. */
+#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)8)
+
+/** There is not enough runtime memory.
+ *
+ * If the action is carried out across multiple security realms, this
+ * error can refer to available memory in any of the security realms. */
+#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)9)
+
+/** There is not enough persistent storage.
+ *
+ * Functions that modify the key storage return this error code if
+ * there is insufficient storage space on the host media. In addition,
+ * many functions that do not otherwise access storage may return this
+ * error code if the implementation requires a mandatory log entry for
+ * the requested action and the log storage space is full. */
+#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)10)
+
+/** There was a communication failure inside the implementation.
+ *
+ * This can indicate a communication failure between the application
+ * and an external cryptoprocessor or between the cryptoprocessor and
+ * an external volatile or persistent memory. A communication failure
+ * may be transient or permanent depending on the cause.
+ *
+ * \warning If a function returns this error, it is undetermined
+ * whether the requested action has completed or not. Implementations
+ * should return #PSA_SUCCESS on successful completion whenver
+ * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE
+ * if the requested action was completed successfully in an external
+ * cryptoprocessor but there was a breakdown of communication before
+ * the cryptoprocessor could report the status to the application.
+ */
+#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)11)
+
+/** There was a storage failure that may have led to data loss.
+ *
+ * This error indicates that some persistent storage is corrupted.
+ * It should not be used for a corruption of volatile memory
+ * (use #PSA_ERROR_TAMPERING_DETECTED), for a communication error
+ * between the cryptoprocessor and its external storage (use
+ * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is
+ * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE).
+ *
+ * Note that a storage failure does not indicate that any data that was
+ * previously read is invalid. However this previously read data may no
+ * longer be readable from storage.
+ *
+ * When a storage failure occurs, it is no longer possible to ensure
+ * the global integrity of the keystore. Depending on the global
+ * integrity guarantees offered by the implementation, access to other
+ * data may or may not fail even if the data is still readable but
+ * its integrity canont be guaranteed.
+ *
+ * Implementations should only use this error code to report a
+ * permanent storage corruption. However application writers should
+ * keep in mind that transient errors while reading the storage may be
+ * reported using this error code. */
+#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)12)
+
+/** A hardware failure was detected.
+ *
+ * A hardware failure may be transient or permanent depending on the
+ * cause. */
+#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)13)
+
+/** A tampering attempt was detected.
+ *
+ * If an application receives this error code, there is no guarantee
+ * that previously accessed or computed data was correct and remains
+ * confidential. Applications should not perform any security function
+ * and should enter a safe failure state.
+ *
+ * Implementations may return this error code if they detect an invalid
+ * state that cannot happen during normal operation and that indicates
+ * that the implementation's security guarantees no longer hold. Depending
+ * on the implementation architecture and on its security and safety goals,
+ * the implementation may forcibly terminate the application.
+ *
+ * This error code is intended as a last resort when a security breach
+ * is detected and it is unsure whether the keystore data is still
+ * protected. Implementations shall only return this error code
+ * to report an alarm from a tampering detector, to indicate that
+ * the confidentiality of stored data can no longer be guaranteed,
+ * or to indicate that the integrity of previously returned data is now
+ * considered compromised. Implementations shall not use this error code
+ * to indicate a hardware failure that merely makes it impossible to
+ * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE,
+ * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE,
+ * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code
+ * instead).
+ *
+ * This error indicates an attack against the application. Implementations
+ * shall not return this error code as a consequence of the behavior of
+ * the application itself. */
+#define PSA_ERROR_TAMPERING_DETECTED ((psa_status_t)14)
+
+/** There is not enough entropy to generate random data needed
+ * for the requested action.
+ *
+ * This error indicates a failure of a hardware random generator.
+ * Application writers should note that this error can be returned not
+ * only by functions whose purpose is to generate random data, such
+ * as key, IV or nonce generation, but also by functions that execute
+ * an algorithm with a randomized result, as well as functions that
+ * use randomization of intermediate computations as a countermeasure
+ * to certain attacks.
+ *
+ * Implementations should avoid returning this error after psa_crypto_init()
+ * has succeeded. Implementations should generate sufficient
+ * entropy during initialization and subsequently use a cryptographically
+ * secure pseudorandom generator (PRNG). However implementations may return
+ * this error at any time if a policy requires the PRNG to be reseeded
+ * during normal operation. */
+#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)15)
+
+/** The signature, MAC or hash is incorrect.
+ *
+ * Verification functions return this error if the verification
+ * calculations completed successfully, and the value to be verified
+ * was determined to be incorrect.
+ *
+ * If the value to verify has an invalid size, implementations may return
+ * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */
+#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)16)
+
+/** The decrypted padding is incorrect.
+ *
+ * \warning In some protocols, when decrypting data, it is essential that
+ * the behavior of the application does not depend on whether the padding
+ * is correct, down to precise timing. Applications should prefer
+ * protocols that use authenticated encryption rather than plain
+ * encryption. If the application must perform a decryption of
+ * unauthenticated data, the application writer should take care not
+ * to reveal whether the padding is invalid.
+ *
+ * Implementations should strive to make valid and invalid padding
+ * as close as possible to indistinguishable to an external observer.
+ * In particular, the timing of a decryption operation should not
+ * depend on the validity of the padding. */
+#define PSA_ERROR_INVALID_PADDING ((psa_status_t)17)
+
+/** The generator has insufficient capacity left.
+ *
+ * Once a function returns this error, attempts to read from the
+ * generator will always return this error. */
+#define PSA_ERROR_INSUFFICIENT_CAPACITY ((psa_status_t)18)
+
+/**
+ * \brief Library initialization.
+ *
+ * Applications must call this function before calling any other
+ * function in this module.
+ *
+ * Applications may call this function more than once. Once a call
+ * succeeds, subsequent calls are guaranteed to succeed.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+psa_status_t psa_crypto_init(void);
+
+#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8)
+#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8)
+
+/**@}*/
+
+/** \defgroup crypto_types Key and algorithm types
+ * @{
+ */
+
+/** \brief Encoding of a key type.
+ */
+typedef uint32_t psa_key_type_t;
+
+/** An invalid key type value.
+ *
+ * Zero is not the encoding of any key type.
+ */
+#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000)
+
+/** Vendor-defined flag
+ *
+ * Key types defined by this standard will never have the
+ * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types
+ * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should
+ * respect the bitwise structure used by standard encodings whenever practical.
+ */
+#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000)
+
+#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x7e000000)
+
+/** Raw data.
+ *
+ * A "key" of this type cannot be used for any cryptographic operation.
+ * Applications may use this type to store arbitrary data in the keystore. */
+#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x02000000)
+
+#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x04000000)
+#define PSA_KEY_TYPE_CATEGORY_ASYMMETRIC ((psa_key_type_t)0x06000000)
+#define PSA_KEY_TYPE_PAIR_FLAG ((psa_key_type_t)0x01000000)
+
+/** HMAC key.
+ *
+ * The key policy determines which underlying hash algorithm the key can be
+ * used for.
+ *
+ * HMAC keys should generally have the same size as the underlying hash.
+ * This size can be calculated with #PSA_HASH_SIZE(\c alg) where
+ * \c alg is the HMAC algorithm or the underlying hash algorithm. */
+#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x02000001)
+
+/** A secret for key derivation.
+ *
+ * The key policy determines which key derivation algorithm the key
+ * can be used for.
+ */
+#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x02000101)
+
+/** Key for an cipher, AEAD or MAC algorithm based on the AES block cipher.
+ *
+ * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or
+ * 32 bytes (AES-256).
+ */
+#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x04000001)
+
+/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES).
+ *
+ * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or
+ * 24 bytes (3-key 3DES).
+ *
+ * Note that single DES and 2-key 3DES are weak and strongly
+ * deprecated and should only be used to decrypt legacy data. 3-key 3DES
+ * is weak and deprecated and should only be used in legacy protocols.
+ */
+#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x04000002)
+
+/** Key for an cipher, AEAD or MAC algorithm based on the
+ * Camellia block cipher. */
+#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x04000003)
+
+/** Key for the RC4 stream cipher.
+ *
+ * Note that RC4 is weak and deprecated and should only be used in
+ * legacy protocols. */
+#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x04000004)
+
+/** RSA public key. */
+#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x06010000)
+/** RSA key pair (private and public key). */
+#define PSA_KEY_TYPE_RSA_KEYPAIR ((psa_key_type_t)0x07010000)
+
+/** DSA public key. */
+#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x06020000)
+/** DSA key pair (private and public key). */
+#define PSA_KEY_TYPE_DSA_KEYPAIR ((psa_key_type_t)0x07020000)
+
+#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x06030000)
+#define PSA_KEY_TYPE_ECC_KEYPAIR_BASE ((psa_key_type_t)0x07030000)
+#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff)
+/** Elliptic curve key pair. */
+#define PSA_KEY_TYPE_ECC_KEYPAIR(curve) \
+ (PSA_KEY_TYPE_ECC_KEYPAIR_BASE | (curve))
+/** Elliptic curve public key. */
+#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \
+ (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve))
+
+/** Whether a key type is vendor-defined. */
+#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \
+ (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0)
+
+/** Whether a key type is asymmetric: either a key pair or a public key. */
+#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \
+ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)
+/** Whether a key type is the public part of a key pair. */
+#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \
+ (((type) & (PSA_KEY_TYPE_CATEGORY_MASK | PSA_KEY_TYPE_PAIR_FLAG)) == \
+ PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)
+/** Whether a key type is a key pair containing a private part and a public
+ * part. */
+#define PSA_KEY_TYPE_IS_KEYPAIR(type) \
+ (((type) & (PSA_KEY_TYPE_CATEGORY_MASK | PSA_KEY_TYPE_PAIR_FLAG)) == \
+ (PSA_KEY_TYPE_CATEGORY_ASYMMETRIC | PSA_KEY_TYPE_PAIR_FLAG))
+/** The key pair type corresponding to a public key type. */
+#define PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY(type) \
+ ((type) | PSA_KEY_TYPE_PAIR_FLAG)
+/** The public key type corresponding to a key pair type. */
+#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) \
+ ((type) & ~PSA_KEY_TYPE_PAIR_FLAG)
+/** Whether a key type is an RSA key (pair or public-only). */
+#define PSA_KEY_TYPE_IS_RSA(type) \
+ (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY)
+
+/** Whether a key type is an elliptic curve key (pair or public-only). */
+#define PSA_KEY_TYPE_IS_ECC(type) \
+ ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) & \
+ ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE)
+#define PSA_KEY_TYPE_IS_ECC_KEYPAIR(type) \
+ (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \
+ PSA_KEY_TYPE_ECC_KEYPAIR_BASE)
+#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \
+ (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \
+ PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE)
+
+/** The type of PSA elliptic curve identifiers. */
+typedef uint16_t psa_ecc_curve_t;
+/** Extract the curve from an elliptic curve key type. */
+#define PSA_KEY_TYPE_GET_CURVE(type) \
+ ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \
+ ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \
+ 0))
+
+/* The encoding of curve identifiers is currently aligned with the
+ * TLS Supported Groups Registry (formerly known as the
+ * TLS EC Named Curve Registry)
+ * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
+ * The values are defined by RFC 4492, RFC 7027 and RFC 7919. */
+#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001)
+#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002)
+#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003)
+#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004)
+#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005)
+#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006)
+#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007)
+#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008)
+#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009)
+#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a)
+#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b)
+#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c)
+#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d)
+#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e)
+#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f)
+#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010)
+#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011)
+#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012)
+#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013)
+#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014)
+#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015)
+#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016)
+#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017)
+#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018)
+#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019)
+#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a)
+#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b)
+#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c)
+#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d)
+#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e)
+#define PSA_ECC_CURVE_FFDHE_2048 ((psa_ecc_curve_t) 0x0100)
+#define PSA_ECC_CURVE_FFDHE_3072 ((psa_ecc_curve_t) 0x0101)
+#define PSA_ECC_CURVE_FFDHE_4096 ((psa_ecc_curve_t) 0x0102)
+#define PSA_ECC_CURVE_FFDHE_6144 ((psa_ecc_curve_t) 0x0103)
+#define PSA_ECC_CURVE_FFDHE_8192 ((psa_ecc_curve_t) 0x0104)
+
+/** The block size of a block cipher.
+ *
+ * \param type A cipher key type (value of type #psa_key_type_t).
+ *
+ * \return The block size for a block cipher, or 1 for a stream cipher.
+ * The return value is undefined if \p type is not a supported
+ * cipher key type.
+ *
+ * \note It is possible to build stream cipher algorithms on top of a block
+ * cipher, for example CTR mode (#PSA_ALG_CTR).
+ * This macro only takes the key type into account, so it cannot be
+ * used to determine the size of the data that #psa_cipher_update()
+ * might buffer for future processing in general.
+ *
+ * \note This macro returns a compile-time constant if its argument is one.
+ *
+ * \warning This macro may evaluate its argument multiple times.
+ */
+#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \
+ ( \
+ (type) == PSA_KEY_TYPE_AES ? 16 : \
+ (type) == PSA_KEY_TYPE_DES ? 8 : \
+ (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \
+ (type) == PSA_KEY_TYPE_ARC4 ? 1 : \
+ 0)
+
+/** \brief Encoding of a cryptographic algorithm.
+ *
+ * For algorithms that can be applied to multiple key types, this type
+ * does not encode the key type. For example, for symmetric ciphers
+ * based on a block cipher, #psa_algorithm_t encodes the block cipher
+ * mode and the padding mode while the block cipher itself is encoded
+ * via #psa_key_type_t.
+ */
+typedef uint32_t psa_algorithm_t;
+
+#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000)
+#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000)
+#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000)
+#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000)
+#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000)
+#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000)
+#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000)
+#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000)
+#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x22000000)
+#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x30000000)
+
+#define PSA_ALG_IS_VENDOR_DEFINED(alg) \
+ (((alg) & PSA_ALG_VENDOR_FLAG) != 0)
+
+/** Whether the specified algorithm is a hash algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a hash algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier.
+ */
+#define PSA_ALG_IS_HASH(alg) \
+ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH)
+
+/** Whether the specified algorithm is a MAC algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a MAC algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier.
+ */
+#define PSA_ALG_IS_MAC(alg) \
+ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC)
+
+/** Whether the specified algorithm is a symmetric cipher algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier.
+ */
+#define PSA_ALG_IS_CIPHER(alg) \
+ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER)
+
+/** Whether the specified algorithm is an authenticated encryption
+ * with associated data (AEAD) algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is an AEAD algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier.
+ */
+#define PSA_ALG_IS_AEAD(alg) \
+ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD)
+
+/** Whether the specified algorithm is a public-key signature algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a public-key signature algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier.
+ */
+#define PSA_ALG_IS_SIGN(alg) \
+ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN)
+
+/** Whether the specified algorithm is a public-key encryption algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a public-key encryption algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier.
+ */
+#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \
+ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION)
+
+/** Whether the specified algorithm is a key agreement algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a key agreement algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier.
+ */
+#define PSA_ALG_IS_KEY_AGREEMENT(alg) \
+ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT)
+
+/** Whether the specified algorithm is a key derivation algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a key derivation algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier.
+ */
+#define PSA_ALG_IS_KEY_DERIVATION(alg) \
+ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)
+
+#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff)
+#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001)
+#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002)
+#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003)
+#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004)
+#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005)
+/** SHA2-224 */
+#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008)
+/** SHA2-256 */
+#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009)
+/** SHA2-384 */
+#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a)
+/** SHA2-512 */
+#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b)
+/** SHA2-512/224 */
+#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c)
+/** SHA2-512/256 */
+#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d)
+/** SHA3-224 */
+#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010)
+/** SHA3-256 */
+#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011)
+/** SHA3-384 */
+#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012)
+/** SHA3-512 */
+#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013)
+
+#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000)
+#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000)
+/** Macro to build an HMAC algorithm.
+ *
+ * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256.
+ *
+ * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return The corresponding HMAC algorithm.
+ * \return Unspecified if \p alg is not a supported
+ * hash algorithm.
+ */
+#define PSA_ALG_HMAC(hash_alg) \
+ (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+
+#define PSA_ALG_HMAC_HASH(hmac_alg) \
+ (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK))
+
+/** Whether the specified algorithm is an HMAC algorithm.
+ *
+ * HMAC is a family of MAC algorithms that are based on a hash function.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is an HMAC algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier.
+ */
+#define PSA_ALG_IS_HMAC(alg) \
+ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \
+ PSA_ALG_HMAC_BASE)
+
+#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000)
+#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001)
+#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002)
+#define PSA_ALG_GMAC ((psa_algorithm_t)0x02c00003)
+
+/** Whether the specified algorithm is a MAC algorithm based on a block cipher.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier.
+ */
+#define PSA_ALG_IS_CIPHER_MAC(alg) \
+ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \
+ PSA_ALG_CIPHER_MAC_BASE)
+
+#define PSA_ALG_CIPHER_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000)
+#define PSA_ALG_BLOCK_CIPHER_BASE ((psa_algorithm_t)0x04000000)
+#define PSA_ALG_BLOCK_CIPHER_MODE_MASK ((psa_algorithm_t)0x000000ff)
+#define PSA_ALG_BLOCK_CIPHER_PADDING_MASK ((psa_algorithm_t)0x003f0000)
+
+/** Use a block cipher mode without padding.
+ *
+ * This padding mode may only be used with messages whose lengths are a
+ * whole number of blocks for the chosen block cipher.
+ */
+#define PSA_ALG_BLOCK_CIPHER_PAD_NONE ((psa_algorithm_t)0x00000000)
+
+#define PSA_ALG_BLOCK_CIPHER_PAD_PKCS7 ((psa_algorithm_t)0x00010000)
+
+/** Whether the specified algorithm is a block cipher.
+ *
+ * A block cipher is a symmetric cipher that encrypts or decrypts messages
+ * by chopping them into fixed-size blocks. Processing a message requires
+ * applying a _padding mode_ to transform the message into one whose
+ * length is a whole number of blocks. To construct an algorithm
+ * identifier for a block cipher, apply a bitwise-or between the block
+ * cipher mode and the padding mode. For example, CBC with PKCS#7 padding
+ * is `PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7`.
+ *
+ * The transformation applied to each block is determined by the key type.
+ * For example, to use AES-128-CBC-PKCS7, use the algorithm above with
+ * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes).
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a block cipher algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier or if it is not a symmetric cipher algorithm.
+ */
+#define PSA_ALG_IS_BLOCK_CIPHER(alg) \
+ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_SUBCATEGORY_MASK)) == \
+ PSA_ALG_BLOCK_CIPHER_BASE)
+
+/** The CBC block cipher mode.
+ */
+#define PSA_ALG_CBC_BASE ((psa_algorithm_t)0x04000001)
+#define PSA_ALG_CFB_BASE ((psa_algorithm_t)0x04000002)
+#define PSA_ALG_OFB_BASE ((psa_algorithm_t)0x04000003)
+#define PSA_ALG_XTS_BASE ((psa_algorithm_t)0x04000004)
+
+#define PSA_ALG_STREAM_CIPHER_BASE ((psa_algorithm_t)0x04800000)
+
+/** The CTR stream cipher mode.
+ *
+ * CTR is a stream cipher which is built from a block cipher. The
+ * underlying block cipher is determined by the key type. For example,
+ * to use AES-128-CTR, use this algorithm with
+ * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes).
+ */
+#define PSA_ALG_CTR ((psa_algorithm_t)0x04800001)
+
+/** The ARC4 stream cipher algorithm.
+ */
+#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800002)
+
+/** Whether the specified algorithm is a stream cipher.
+ *
+ * A stream cipher is a symmetric cipher that encrypts or decrypts messages
+ * by applying a bitwise-xor with a stream of bytes that is generated
+ * from a key.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \p alg is not a supported
+ * algorithm identifier or if it is not a symmetric cipher algorithm.
+ */
+#define PSA_ALG_IS_STREAM_CIPHER(alg) \
+ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_SUBCATEGORY_MASK)) == \
+ PSA_ALG_STREAM_CIPHER_BASE)
+
+#define PSA_ALG_CCM ((psa_algorithm_t)0x06000001)
+#define PSA_ALG_GCM ((psa_algorithm_t)0x06000002)
+
+#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000)
+/** RSA PKCS#1 v1.5 signature with hashing.
+ *
+ * This is the signature scheme defined by RFC 8017
+ * (PKCS#1: RSA Cryptography Specifications) under the name
+ * RSASSA-PKCS1-v1_5.
+ *
+ * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return The corresponding RSA PKCS#1 v1.5 signature algorithm.
+ * \return Unspecified if \p alg is not a supported
+ * hash algorithm.
+ */
+#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \
+ (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+/** Raw PKCS#1 v1.5 signature.
+ *
+ * The input to this algorithm is the DigestInfo structure used by
+ * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2
+ * steps 3–6.
+ */
+#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE
+#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \
+ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE)
+
+#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000)
+/** RSA PSS signature with hashing.
+ *
+ * This is the signature scheme defined by RFC 8017
+ * (PKCS#1: RSA Cryptography Specifications) under the name
+ * RSASSA-PSS, with the message generation function MGF1, and with
+ * a salt length equal to the length of the hash. The specified
+ * hash algorithm is used to hash the input message, to create the
+ * salted hash, and for the mask generation.
+ *
+ * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return The corresponding RSA PSS signature algorithm.
+ * \return Unspecified if \p alg is not a supported
+ * hash algorithm.
+ */
+#define PSA_ALG_RSA_PSS(hash_alg) \
+ (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_IS_RSA_PSS(alg) \
+ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE)
+
+#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x10040000)
+/** DSA signature with hashing.
+ *
+ * This is the signature scheme defined by FIPS 186-4,
+ * with a random per-message secret number (*k*).
+ *
+ * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return The corresponding DSA signature algorithm.
+ * \return Unspecified if \p alg is not a supported
+ * hash algorithm.
+ */
+#define PSA_ALG_DSA(hash_alg) \
+ (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x10050000)
+#define PSA_ALG_DSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000)
+#define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \
+ (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_IS_DSA(alg) \
+ (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \
+ PSA_ALG_DSA_BASE)
+#define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \
+ (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)
+#define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \
+ (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg))
+#define PSA_ALG_IS_RANDOMIZED_DSA(alg) \
+ (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg))
+
+#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000)
+/** ECDSA signature with hashing.
+ *
+ * This is the ECDSA signature scheme defined by ANSI X9.62,
+ * with a random per-message secret number (*k*).
+ *
+ * The representation of the signature as a byte string consists of
+ * the concatentation of the signature values *r* and *s*. Each of
+ * *r* and *s* is encoded as an *N*-octet string, where *N* is the length
+ * of the base point of the curve in octets. Each value is represented
+ * in big-endian order (most significant octet first).
+ *
+ * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return The corresponding ECDSA signature algorithm.
+ * \return Unspecified if \p alg is not a supported
+ * hash algorithm.
+ */
+#define PSA_ALG_ECDSA(hash_alg) \
+ (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+/** ECDSA signature without hashing.
+ *
+ * This is the same signature scheme as #PSA_ALG_ECDSA(), but
+ * without specifying a hash algorithm. This algorithm may only be
+ * used to sign or verify a sequence of bytes that should be an
+ * already-calculated hash. Note that the input is padded with
+ * zeros on the left or truncated on the left as required to fit
+ * the curve size.
+ */
+#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE
+#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000)
+/** Deterministic ECDSA signature with hashing.
+ *
+ * This is the deterministic ECDSA signature scheme defined by RFC 6979.
+ *
+ * The representation of a signature is the same as with #PSA_ALG_ECDSA().
+ *
+ * Note that when this algorithm is used for verification, signatures
+ * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the
+ * same private key are accepted. In other words,
+ * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from
+ * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification.
+ *
+ * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return The corresponding deterministic ECDSA signature
+ * algorithm.
+ * \return Unspecified if \p alg is not a supported
+ * hash algorithm.
+ */
+#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \
+ (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_IS_ECDSA(alg) \
+ (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \
+ PSA_ALG_ECDSA_BASE)
+#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \
+ (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)
+#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \
+ (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))
+#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \
+ (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))
+
+/** Get the hash used by a hash-and-sign signature algorithm.
+ *
+ * A hash-and-sign algorithm is a signature algorithm which is
+ * composed of two phases: first a hashing phase which does not use
+ * the key and produces a hash of the input message, then a signing
+ * phase which only uses the hash and the key and not the message
+ * itself.
+ *
+ * \param alg A signature algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_SIGN(\p alg) is true).
+ *
+ * \return The underlying hash algorithm if \p alg is a hash-and-sign
+ * algorithm.
+ * \return 0 if \p alg is a signature algorithm that does not
+ * follow the hash-and-sign structure.
+ * \return Unspecified if \p alg is not a signature algorithm or
+ * if it is not supported by the implementation.
+ */
+#define PSA_ALG_SIGN_GET_HASH(alg) \
+ (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \
+ PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg) ? \
+ ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \
+ ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \
+ 0)
+
+/** RSA PKCS#1 v1.5 encryption.
+ */
+#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000)
+
+#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000)
+/** RSA OAEP encryption.
+ *
+ * This is the encryption scheme defined by RFC 8017
+ * (PKCS#1: RSA Cryptography Specifications) under the name
+ * RSAES-OAEP, with the message generation function MGF1.
+ *
+ * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use
+ * for MGF1.
+ *
+ * \return The corresponding RSA OAEP signature algorithm.
+ * \return Unspecified if \p alg is not a supported
+ * hash algorithm.
+ */
+#define PSA_ALG_RSA_OAEP(hash_alg) \
+ (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_IS_RSA_OAEP(alg) \
+ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE)
+#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \
+ (PSA_ALG_IS_RSA_OAEP(alg) ? \
+ ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \
+ 0)
+
+#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x30000100)
+/** Macro to build an HKDF algorithm.
+ *
+ * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256.
+ *
+ * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return The corresponding HKDF algorithm.
+ * \return Unspecified if \p alg is not a supported
+ * hash algorithm.
+ */
+#define PSA_ALG_HKDF(hash_alg) \
+ (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+/** Whether the specified algorithm is an HKDF algorithm.
+ *
+ * HKDF is a family of key derivation algorithms that are based on a hash
+ * function and the HMAC construction.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \c alg is an HKDF algorithm, 0 otherwise.
+ * This macro may return either 0 or 1 if \c alg is not a supported
+ * key derivation algorithm identifier.
+ */
+#define PSA_ALG_IS_HKDF(alg) \
+ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE)
+#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \
+ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK))
+
+/**@}*/
+
+/** \defgroup key_management Key management
+ * @{
+ */
+
+/**
+ * \brief Import a key in binary format.
+ *
+ * This function supports any output from psa_export_key(). Refer to the
+ * documentation of psa_export_key() for the format for each key type.
+ *
+ * \param key Slot where the key will be stored. This must be a
+ * valid slot for a key of the chosen type. It must
+ * be unoccupied.
+ * \param type Key type (a \c PSA_KEY_TYPE_XXX value).
+ * \param[in] data Buffer containing the key data.
+ * \param data_length Size of the \p data buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * The key type or key size is not supported, either by the
+ * implementation in general or in this particular slot.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The key slot is invalid,
+ * or the key data is not correctly formatted.
+ * \retval #PSA_ERROR_OCCUPIED_SLOT
+ * There is already a key in the specified slot.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_import_key(psa_key_slot_t key,
+ psa_key_type_t type,
+ const uint8_t *data,
+ size_t data_length);
+
+/**
+ * \brief Destroy a key and restore the slot to its default state.
+ *
+ * This function destroys the content of the key slot from both volatile
+ * memory and, if applicable, non-volatile storage. Implementations shall
+ * make a best effort to ensure that any previous content of the slot is
+ * unrecoverable.
+ *
+ * This function also erases any metadata such as policies. It returns the
+ * specified slot to its default state.
+ *
+ * \param key The key slot to erase.
+ *
+ * \retval #PSA_SUCCESS
+ * The slot's content, if any, has been erased.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * The slot holds content and cannot be erased because it is
+ * read-only, either due to a policy or due to physical restrictions.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The specified slot number does not designate a valid slot.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * There was an failure in communication with the cryptoprocessor.
+ * The key material may still be present in the cryptoprocessor.
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * The storage is corrupted. Implementations shall make a best effort
+ * to erase key material even in this stage, however applications
+ * should be aware that it may be impossible to guarantee that the
+ * key material is not recoverable in such cases.
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * An unexpected condition which is not a storage corruption or
+ * a communication failure occurred. The cryptoprocessor may have
+ * been compromised.
+ */
+psa_status_t psa_destroy_key(psa_key_slot_t key);
+
+/**
+ * \brief Get basic metadata about a key.
+ *
+ * \param key Slot whose content is queried. This must
+ * be an occupied key slot.
+ * \param[out] type On success, the key type (a \c PSA_KEY_TYPE_XXX value).
+ * This may be a null pointer, in which case the key type
+ * is not written.
+ * \param[out] bits On success, the key size in bits.
+ * This may be a null pointer, in which case the key size
+ * is not written.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_get_key_information(psa_key_slot_t key,
+ psa_key_type_t *type,
+ size_t *bits);
+
+/**
+ * \brief Export a key in binary format.
+ *
+ * The output of this function can be passed to psa_import_key() to
+ * create an equivalent object.
+ *
+ * If a key is created with psa_import_key() and then exported with
+ * this function, it is not guaranteed that the resulting data is
+ * identical: the implementation may choose a different representation
+ * of the same key if the format permits it.
+ *
+ * For standard key types, the output format is as follows:
+ *
+ * - For symmetric keys (including MAC keys), the format is the
+ * raw bytes of the key.
+ * - For DES, the key data consists of 8 bytes. The parity bits must be
+ * correct.
+ * - For Triple-DES, the format is the concatenation of the
+ * two or three DES keys.
+ * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEYPAIR), the format
+ * is the non-encrypted DER representation defined by PKCS\#1 (RFC 8017)
+ * as RSAPrivateKey.
+ * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the format
+ * is the DER representation defined by RFC 5280 as SubjectPublicKeyInfo.
+ *
+ * \param key Slot whose content is to be exported. This must
+ * be an occupied key slot.
+ * \param[out] data Buffer where the key data is to be written.
+ * \param data_size Size of the \p data buffer in bytes.
+ * \param[out] data_length On success, the number of bytes
+ * that make up the key data.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_export_key(psa_key_slot_t key,
+ uint8_t *data,
+ size_t data_size,
+ size_t *data_length);
+
+/**
+ * \brief Export a public key or the public part of a key pair in binary format.
+ *
+ * The output of this function can be passed to psa_import_key() to
+ * create an object that is equivalent to the public key.
+ *
+ * For standard key types, the output format is as follows:
+ *
+ * - For RSA keys (#PSA_KEY_TYPE_RSA_KEYPAIR or #PSA_KEY_TYPE_RSA_PUBLIC_KEY),
+ * the format is the DER representation of the public key defined by RFC 5280
+ * as SubjectPublicKeyInfo.
+ *
+ * \param key Slot whose content is to be exported. This must
+ * be an occupied key slot.
+ * \param[out] data Buffer where the key data is to be written.
+ * \param data_size Size of the \p data buffer in bytes.
+ * \param[out] data_length On success, the number of bytes
+ * that make up the key data.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_export_public_key(psa_key_slot_t key,
+ uint8_t *data,
+ size_t data_size,
+ size_t *data_length);
+
+/**@}*/
+
+/** \defgroup policy Key policies
+ * @{
+ */
+
+/** \brief Encoding of permitted usage on a key. */
+typedef uint32_t psa_key_usage_t;
+
+/** Whether the key may be exported.
+ *
+ * A public key or the public part of a key pair may always be exported
+ * regardless of the value of this permission flag.
+ *
+ * If a key does not have export permission, implementations shall not
+ * allow the key to be exported in plain form from the cryptoprocessor,
+ * whether through psa_export_key() or through a proprietary interface.
+ * The key may however be exportable in a wrapped form, i.e. in a form
+ * where it is encrypted by another key.
+ */
+#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001)
+
+/** Whether the key may be used to encrypt a message.
+ *
+ * This flag allows the key to be used for a symmetric encryption operation,
+ * for an AEAD encryption-and-authentication operation,
+ * or for an asymmetric encryption operation,
+ * if otherwise permitted by the key's type and policy.
+ *
+ * For a key pair, this concerns the public key.
+ */
+#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100)
+
+/** Whether the key may be used to decrypt a message.
+ *
+ * This flag allows the key to be used for a symmetric decryption operation,
+ * for an AEAD decryption-and-verification operation,
+ * or for an asymmetric decryption operation,
+ * if otherwise permitted by the key's type and policy.
+ *
+ * For a key pair, this concerns the private key.
+ */
+#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200)
+
+/** Whether the key may be used to sign a message.
+ *
+ * This flag allows the key to be used for a MAC calculation operation
+ * or for an asymmetric signature operation,
+ * if otherwise permitted by the key's type and policy.
+ *
+ * For a key pair, this concerns the private key.
+ */
+#define PSA_KEY_USAGE_SIGN ((psa_key_usage_t)0x00000400)
+
+/** Whether the key may be used to verify a message signature.
+ *
+ * This flag allows the key to be used for a MAC verification operation
+ * or for an asymmetric signature verification operation,
+ * if otherwise permitted by by the key's type and policy.
+ *
+ * For a key pair, this concerns the public key.
+ */
+#define PSA_KEY_USAGE_VERIFY ((psa_key_usage_t)0x00000800)
+
+/** Whether the key may be used to derive other keys.
+ */
+#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000)
+
+/** The type of the key policy data structure.
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure except
+ * as directed by the documentation of a specific implementation. */
+typedef struct psa_key_policy_s psa_key_policy_t;
+
+/** \brief Initialize a key policy structure to a default that forbids all
+ * usage of the key.
+ *
+ * \param[out] policy The policy object to initialize.
+ */
+void psa_key_policy_init(psa_key_policy_t *policy);
+
+/** \brief Set the standard fields of a policy structure.
+ *
+ * Note that this function does not make any consistency check of the
+ * parameters. The values are only checked when applying the policy to
+ * a key slot with psa_set_key_policy().
+ *
+ * \param[out] policy The policy object to modify.
+ * \param usage The permitted uses for the key.
+ * \param alg The algorithm that the key may be used for.
+ */
+void psa_key_policy_set_usage(psa_key_policy_t *policy,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg);
+
+/** \brief Retrieve the usage field of a policy structure.
+ *
+ * \param[in] policy The policy object to query.
+ *
+ * \return The permitted uses for a key with this policy.
+ */
+psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy);
+
+/** \brief Retrieve the algorithm field of a policy structure.
+ *
+ * \param[in] policy The policy object to query.
+ *
+ * \return The permitted algorithm for a key with this policy.
+ */
+psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy);
+
+/** \brief Set the usage policy on a key slot.
+ *
+ * This function must be called on an empty key slot, before importing,
+ * generating or creating a key in the slot. Changing the policy of an
+ * existing key is not permitted.
+ *
+ * Implementations may set restrictions on supported key policies
+ * depending on the key type and the key slot.
+ *
+ * \param key The key slot whose policy is to be changed.
+ * \param[in] policy The policy object to query.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_OCCUPIED_SLOT
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_set_key_policy(psa_key_slot_t key,
+ const psa_key_policy_t *policy);
+
+/** \brief Get the usage policy for a key slot.
+ *
+ * \param key The key slot whose policy is being queried.
+ * \param[out] policy On success, the key's policy.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_get_key_policy(psa_key_slot_t key,
+ psa_key_policy_t *policy);
+
+/**@}*/
+
+/** \defgroup persistence Key lifetime
+ * @{
+ */
+
+/** Encoding of key lifetimes.
+ */
+typedef uint32_t psa_key_lifetime_t;
+
+/** A volatile key slot retains its content as long as the application is
+ * running. It is guaranteed to be erased on a power reset.
+ */
+#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000)
+
+/** A persistent key slot retains its content as long as it is not explicitly
+ * destroyed.
+ */
+#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001)
+
+/** A write-once key slot may not be modified once a key has been set.
+ * It will retain its content as long as the device remains operational.
+ */
+#define PSA_KEY_LIFETIME_WRITE_ONCE ((psa_key_lifetime_t)0x7fffffff)
+
+/** \brief Retrieve the lifetime of a key slot.
+ *
+ * The assignment of lifetimes to slots is implementation-dependent.
+ *
+ * \param key Slot to query.
+ * \param[out] lifetime On success, the lifetime value.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The key slot is invalid.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_get_key_lifetime(psa_key_slot_t key,
+ psa_key_lifetime_t *lifetime);
+
+/** \brief Change the lifetime of a key slot.
+ *
+ * Whether the lifetime of a key slot can be changed at all, and if so
+ * whether the lifetime of an occupied key slot can be changed, is
+ * implementation-dependent.
+ *
+ * \param key Slot whose lifetime is to be changed.
+ * \param lifetime The lifetime value to set for the given key slot.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The key slot is invalid,
+ * or the lifetime value is invalid.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * The implementation does not support the specified lifetime value,
+ * at least for the specified key slot.
+ * \retval #PSA_ERROR_OCCUPIED_SLOT
+ * The slot contains a key, and the implementation does not support
+ * changing the lifetime of an occupied slot.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_set_key_lifetime(psa_key_slot_t key,
+ psa_key_lifetime_t lifetime);
+
+/**@}*/
+
+/** \defgroup hash Message digests
+ * @{
+ */
+
+/** The type of the state data structure for multipart hash operations.
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure except
+ * as directed by the documentation of a specific implementation. */
+typedef struct psa_hash_operation_s psa_hash_operation_t;
+
+/** The size of the output of psa_hash_finish(), in bytes.
+ *
+ * This is also the hash size that psa_hash_verify() expects.
+ *
+ * \param alg A hash algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm
+ * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a
+ * hash algorithm).
+ *
+ * \return The hash size for the specified hash algorithm.
+ * If the hash algorithm is not recognized, return 0.
+ * An implementation may return either 0 or the correct size
+ * for a hash algorithm that it recognizes, but does not support.
+ */
+#define PSA_HASH_SIZE(alg) \
+ ( \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD2 ? 16 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD4 ? 16 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_MD5 ? 16 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \
+ PSA_ALG_HMAC_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \
+ 0)
+
+/** Start a multipart hash operation.
+ *
+ * The sequence of operations to calculate a hash (message digest)
+ * is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ * listed here.
+ * -# Call psa_hash_setup() to specify the algorithm.
+ * -# Call psa_hash_update() zero, one or more times, passing a fragment
+ * of the message each time. The hash that is calculated is the hash
+ * of the concatenation of these messages in order.
+ * -# To calculate the hash, call psa_hash_finish().
+ * To compare the hash with an expected value, call psa_hash_verify().
+ *
+ * The application may call psa_hash_abort() at any time after the operation
+ * has been initialized with psa_hash_setup().
+ *
+ * After a successful call to psa_hash_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A failed call to psa_hash_update().
+ * - A call to psa_hash_finish(), psa_hash_verify() or psa_hash_abort().
+ *
+ * \param[out] operation The operation object to use.
+ * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value
+ * such that #PSA_ALG_IS_HASH(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \p alg is not supported or is not a hash algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
+ psa_algorithm_t alg);
+
+/** Add a message fragment to a multipart hash operation.
+ *
+ * The application must call psa_hash_setup() before calling this function.
+ *
+ * If this function returns an error status, the operation becomes inactive.
+ *
+ * \param[in,out] operation Active hash operation.
+ * \param[in] input Buffer containing the message fragment to hash.
+ * \param input_length Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_update(psa_hash_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length);
+
+/** Finish the calculation of the hash of a message.
+ *
+ * The application must call psa_hash_setup() before calling this function.
+ * This function calculates the hash of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_hash_update().
+ *
+ * When this function returns, the operation becomes inactive.
+ *
+ * \warning Applications should not call this function if they expect
+ * a specific value for the hash. Call psa_hash_verify() instead.
+ * Beware that comparing integrity or authenticity data such as
+ * hash values with a function such as \c memcmp is risky
+ * because the time taken by the comparison may leak information
+ * about the hashed data which could allow an attacker to guess
+ * a valid hash and thereby bypass security controls.
+ *
+ * \param[in,out] operation Active hash operation.
+ * \param[out] hash Buffer where the hash is to be written.
+ * \param hash_size Size of the \p hash buffer in bytes.
+ * \param[out] hash_length On success, the number of bytes
+ * that make up the hash value. This is always
+ * #PSA_HASH_SIZE(\c alg) where \c alg is the
+ * hash algorithm that is calculated.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p hash buffer is too small. You can determine a
+ * sufficient buffer size by calling #PSA_HASH_SIZE(\c alg)
+ * where \c alg is the hash algorithm that is calculated.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
+ uint8_t *hash,
+ size_t hash_size,
+ size_t *hash_length);
+
+/** Finish the calculation of the hash of a message and compare it with
+ * an expected value.
+ *
+ * The application must call psa_hash_setup() before calling this function.
+ * This function calculates the hash of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_hash_update(). It then
+ * compares the calculated hash with the expected hash passed as a
+ * parameter to this function.
+ *
+ * When this function returns, the operation becomes inactive.
+ *
+ * \note Implementations shall make the best effort to ensure that the
+ * comparison between the actual hash and the expected hash is performed
+ * in constant time.
+ *
+ * \param[in,out] operation Active hash operation.
+ * \param[in] hash Buffer containing the expected hash value.
+ * \param hash_length Size of the \p hash buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * The expected hash is identical to the actual hash of the message.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ * The hash of the message was calculated successfully, but it
+ * differs from the expected hash.
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
+ const uint8_t *hash,
+ size_t hash_length);
+
+/** Abort a hash operation.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * psa_hash_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized by any of the following methods:
+ * - A call to psa_hash_setup(), whether it succeeds or not.
+ * - Initializing the \c struct to all-bits-zero.
+ * - Initializing the \c struct to logical zeros, e.g.
+ * `psa_hash_operation_t operation = {0}`.
+ *
+ * In particular, calling psa_hash_abort() after the operation has been
+ * terminated by a call to psa_hash_abort(), psa_hash_finish() or
+ * psa_hash_verify() is safe and has no effect.
+ *
+ * \param[in,out] operation Initialized hash operation.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BAD_STATE
+ * \p operation is not an active hash operation.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_hash_abort(psa_hash_operation_t *operation);
+
+/**@}*/
+
+/** \defgroup MAC Message authentication codes
+ * @{
+ */
+
+/** The type of the state data structure for multipart MAC operations.
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure except
+ * as directed by the documentation of a specific implementation. */
+typedef struct psa_mac_operation_s psa_mac_operation_t;
+
+/** Start a multipart MAC calculation operation.
+ *
+ * This function sets up the calculation of the MAC
+ * (message authentication code) of a byte string.
+ * To verify the MAC of a message against an
+ * expected value, use psa_mac_verify_setup() instead.
+ *
+ * The sequence of operations to calculate a MAC is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ * listed here.
+ * -# Call psa_mac_sign_setup() to specify the algorithm and key.
+ * The key remains associated with the operation even if the content
+ * of the key slot changes.
+ * -# Call psa_mac_update() zero, one or more times, passing a fragment
+ * of the message each time. The MAC that is calculated is the MAC
+ * of the concatenation of these messages in order.
+ * -# At the end of the message, call psa_mac_sign_finish() to finish
+ * calculating the MAC value and retrieve it.
+ *
+ * The application may call psa_mac_abort() at any time after the operation
+ * has been initialized with psa_mac_sign_setup().
+ *
+ * After a successful call to psa_mac_sign_setup(), the application must
+ * eventually terminate the operation through one of the following methods:
+ * - A failed call to psa_mac_update().
+ * - A call to psa_mac_sign_finish() or psa_mac_abort().
+ *
+ * \param[out] operation The operation object to use.
+ * \param key Slot containing the key to use for the operation.
+ * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value
+ * such that #PSA_ALG_IS_MAC(alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \p alg is not supported or is not a MAC algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg);
+
+/** Start a multipart MAC verification operation.
+ *
+ * This function sets up the verification of the MAC
+ * (message authentication code) of a byte string against an expected value.
+ *
+ * The sequence of operations to verify a MAC is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ * listed here.
+ * -# Call psa_mac_verify_setup() to specify the algorithm and key.
+ * The key remains associated with the operation even if the content
+ * of the key slot changes.
+ * -# Call psa_mac_update() zero, one or more times, passing a fragment
+ * of the message each time. The MAC that is calculated is the MAC
+ * of the concatenation of these messages in order.
+ * -# At the end of the message, call psa_mac_verify_finish() to finish
+ * calculating the actual MAC of the message and verify it against
+ * the expected value.
+ *
+ * The application may call psa_mac_abort() at any time after the operation
+ * has been initialized with psa_mac_verify_setup().
+ *
+ * After a successful call to psa_mac_verify_setup(), the application must
+ * eventually terminate the operation through one of the following methods:
+ * - A failed call to psa_mac_update().
+ * - A call to psa_mac_verify_finish() or psa_mac_abort().
+ *
+ * \param[out] operation The operation object to use.
+ * \param key Slot containing the key to use for the operation.
+ * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value
+ * such that #PSA_ALG_IS_MAC(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \c key is not compatible with \c alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \c alg is not supported or is not a MAC algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg);
+
+/** Add a message fragment to a multipart MAC operation.
+ *
+ * The application must call psa_mac_sign_setup() or psa_mac_verify_setup()
+ * before calling this function.
+ *
+ * If this function returns an error status, the operation becomes inactive.
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[in] input Buffer containing the message fragment to add to
+ * the MAC calculation.
+ * \param input_length Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_update(psa_mac_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length);
+
+/** Finish the calculation of the MAC of a message.
+ *
+ * The application must call psa_mac_sign_setup() before calling this function.
+ * This function calculates the MAC of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_mac_update().
+ *
+ * When this function returns, the operation becomes inactive.
+ *
+ * \warning Applications should not call this function if they expect
+ * a specific value for the MAC. Call psa_mac_verify_finish() instead.
+ * Beware that comparing integrity or authenticity data such as
+ * MAC values with a function such as \c memcmp is risky
+ * because the time taken by the comparison may leak information
+ * about the MAC value which could allow an attacker to guess
+ * a valid MAC and thereby bypass security controls.
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[out] mac Buffer where the MAC value is to be written.
+ * \param mac_size Size of the \p mac buffer in bytes.
+ * \param[out] mac_length On success, the number of bytes
+ * that make up the MAC value. This is always
+ * #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg)
+ * where \c key_type and \c key_bits are the type and
+ * bit-size respectively of the key and \c alg is the
+ * MAC algorithm that is calculated.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p mac buffer is too small. You can determine a
+ * sufficient buffer size by calling PSA_MAC_FINAL_SIZE().
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
+ uint8_t *mac,
+ size_t mac_size,
+ size_t *mac_length);
+
+/** Finish the calculation of the MAC of a message and compare it with
+ * an expected value.
+ *
+ * The application must call psa_mac_verify_setup() before calling this function.
+ * This function calculates the MAC of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_mac_update(). It then
+ * compares the calculated MAC with the expected MAC passed as a
+ * parameter to this function.
+ *
+ * When this function returns, the operation becomes inactive.
+ *
+ * \note Implementations shall make the best effort to ensure that the
+ * comparison between the actual MAC and the expected MAC is performed
+ * in constant time.
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[in] mac Buffer containing the expected MAC value.
+ * \param mac_length Size of the \p mac buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * The expected MAC is identical to the actual MAC of the message.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ * The MAC of the message was calculated successfully, but it
+ * differs from the expected MAC.
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (not started, or already completed).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
+ const uint8_t *mac,
+ size_t mac_length);
+
+/** Abort a MAC operation.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * psa_mac_sign_setup() or psa_mac_verify_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized by any of the following methods:
+ * - A call to psa_mac_sign_setup() or psa_mac_verify_setup(), whether
+ * it succeeds or not.
+ * - Initializing the \c struct to all-bits-zero.
+ * - Initializing the \c struct to logical zeros, e.g.
+ * `psa_mac_operation_t operation = {0}`.
+ *
+ * In particular, calling psa_mac_abort() after the operation has been
+ * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or
+ * psa_mac_verify_finish() is safe and has no effect.
+ *
+ * \param[in,out] operation Initialized MAC operation.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BAD_STATE
+ * \p operation is not an active MAC operation.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_mac_abort(psa_mac_operation_t *operation);
+
+/**@}*/
+
+/** \defgroup cipher Symmetric ciphers
+ * @{
+ */
+
+/** The type of the state data structure for multipart cipher operations.
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure except
+ * as directed by the documentation of a specific implementation. */
+typedef struct psa_cipher_operation_s psa_cipher_operation_t;
+
+/** Set the key for a multipart symmetric encryption operation.
+ *
+ * The sequence of operations to encrypt a message with a symmetric cipher
+ * is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ * listed here.
+ * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key.
+ * The key remains associated with the operation even if the content
+ * of the key slot changes.
+ * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to
+ * generate or set the IV (initialization vector). You should use
+ * psa_cipher_generate_iv() unless the protocol you are implementing
+ * requires a specific IV value.
+ * -# Call psa_cipher_update() zero, one or more times, passing a fragment
+ * of the message each time.
+ * -# Call psa_cipher_finish().
+ *
+ * The application may call psa_cipher_abort() at any time after the operation
+ * has been initialized with psa_cipher_encrypt_setup().
+ *
+ * After a successful call to psa_cipher_encrypt_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A failed call to psa_cipher_generate_iv(), psa_cipher_set_iv()
+ * or psa_cipher_update().
+ * - A call to psa_cipher_finish() or psa_cipher_abort().
+ *
+ * \param[out] operation The operation object to use.
+ * \param key Slot containing the key to use for the operation.
+ * \param alg The cipher algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_CIPHER(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \p alg is not supported or is not a cipher algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg);
+
+/** Set the key for a multipart symmetric decryption operation.
+ *
+ * The sequence of operations to decrypt a message with a symmetric cipher
+ * is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ * listed here.
+ * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key.
+ * The key remains associated with the operation even if the content
+ * of the key slot changes.
+ * -# Call psa_cipher_update() with the IV (initialization vector) for the
+ * decryption. If the IV is prepended to the ciphertext, you can call
+ * psa_cipher_update() on a buffer containing the IV followed by the
+ * beginning of the message.
+ * -# Call psa_cipher_update() zero, one or more times, passing a fragment
+ * of the message each time.
+ * -# Call psa_cipher_finish().
+ *
+ * The application may call psa_cipher_abort() at any time after the operation
+ * has been initialized with psa_cipher_decrypt_setup().
+ *
+ * After a successful call to psa_cipher_decrypt_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A failed call to psa_cipher_update().
+ * - A call to psa_cipher_finish() or psa_cipher_abort().
+ *
+ * \param[out] operation The operation object to use.
+ * \param key Slot containing the key to use for the operation.
+ * \param alg The cipher algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_CIPHER(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \p alg is not supported or is not a cipher algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg);
+
+/** Generate an IV for a symmetric encryption operation.
+ *
+ * This function generates a random IV (initialization vector), nonce
+ * or initial counter value for the encryption operation as appropriate
+ * for the chosen algorithm, key type and key size.
+ *
+ * The application must call psa_cipher_encrypt_setup() before
+ * calling this function.
+ *
+ * If this function returns an error status, the operation becomes inactive.
+ *
+ * \param[in,out] operation Active cipher operation.
+ * \param[out] iv Buffer where the generated IV is to be written.
+ * \param iv_size Size of the \p iv buffer in bytes.
+ * \param[out] iv_length On success, the number of bytes of the
+ * generated IV.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (not started, or IV already set).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p iv buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,
+ unsigned char *iv,
+ size_t iv_size,
+ size_t *iv_length);
+
+/** Set the IV for a symmetric encryption or decryption operation.
+ *
+ * This function sets the random IV (initialization vector), nonce
+ * or initial counter value for the encryption or decryption operation.
+ *
+ * The application must call psa_cipher_encrypt_setup() before
+ * calling this function.
+ *
+ * If this function returns an error status, the operation becomes inactive.
+ *
+ * \note When encrypting, applications should use psa_cipher_generate_iv()
+ * instead of this function, unless implementing a protocol that requires
+ * a non-random IV.
+ *
+ * \param[in,out] operation Active cipher operation.
+ * \param[in] iv Buffer containing the IV to use.
+ * \param iv_length Size of the IV in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (not started, or IV already set).
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The size of \p iv is not acceptable for the chosen algorithm,
+ * or the chosen algorithm does not use an IV.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
+ const unsigned char *iv,
+ size_t iv_length);
+
+/** Encrypt or decrypt a message fragment in an active cipher operation.
+ *
+ * Before calling this function, you must:
+ * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup().
+ * The choice of setup function determines whether this function
+ * encrypts or decrypts its input.
+ * 2. If the algorithm requires an IV, call psa_cipher_generate_iv()
+ * (recommended when encrypting) or psa_cipher_set_iv().
+ *
+ * If this function returns an error status, the operation becomes inactive.
+ *
+ * \param[in,out] operation Active cipher operation.
+ * \param[in] input Buffer containing the message fragment to
+ * encrypt or decrypt.
+ * \param input_length Size of the \p input buffer in bytes.
+ * \param[out] output Buffer where the output is to be written.
+ * \param output_size Size of the \p output buffer in bytes.
+ * \param[out] output_length On success, the number of bytes
+ * that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (not started, IV required but
+ * not set, or already completed).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length,
+ unsigned char *output,
+ size_t output_size,
+ size_t *output_length);
+
+/** Finish encrypting or decrypting a message in a cipher operation.
+ *
+ * The application must call psa_cipher_encrypt_setup() or
+ * psa_cipher_decrypt_setup() before calling this function. The choice
+ * of setup function determines whether this function encrypts or
+ * decrypts its input.
+ *
+ * This function finishes the encryption or decryption of the message
+ * formed by concatenating the inputs passed to preceding calls to
+ * psa_cipher_update().
+ *
+ * When this function returns, the operation becomes inactive.
+ *
+ * \param[in,out] operation Active cipher operation.
+ * \param[out] output Buffer where the output is to be written.
+ * \param output_size Size of the \p output buffer in bytes.
+ * \param[out] output_length On success, the number of bytes
+ * that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (not started, IV required but
+ * not set, or already completed).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length);
+
+/** Abort a cipher operation.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized by any of the following methods:
+ * - A call to psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(),
+ * whether it succeeds or not.
+ * - Initializing the \c struct to all-bits-zero.
+ * - Initializing the \c struct to logical zeros, e.g.
+ * `psa_cipher_operation_t operation = {0}`.
+ *
+ * In particular, calling psa_cipher_abort() after the operation has been
+ * terminated by a call to psa_cipher_abort() or psa_cipher_finish()
+ * is safe and has no effect.
+ *
+ * \param[in,out] operation Initialized cipher operation.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BAD_STATE
+ * \p operation is not an active cipher operation.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation);
+
+/**@}*/
+
+/** \defgroup aead Authenticated encryption with associated data (AEAD)
+ * @{
+ */
+
+/** The tag size for an AEAD algorithm, in bytes.
+ *
+ * \param alg An AEAD algorithm
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \return The tag size for the specified algorithm.
+ * If the AEAD algorithm does not have an identified
+ * tag that can be distinguished from the rest of
+ * the ciphertext, return 0.
+ * If the AEAD algorithm is not recognized, return 0.
+ * An implementation may return either 0 or a
+ * correct size for an AEAD algorithm that it
+ * recognizes, but does not support.
+ */
+#define PSA_AEAD_TAG_SIZE(alg) \
+ ((alg) == PSA_ALG_GCM ? 16 : \
+ (alg) == PSA_ALG_CCM ? 16 : \
+ 0)
+
+/** Process an authenticated encryption operation.
+ *
+ * \param key Slot containing the key to use.
+ * \param alg The AEAD algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_AEAD(\p alg) is true).
+ * \param[in] nonce Nonce or IV to use.
+ * \param nonce_length Size of the \p nonce buffer in bytes.
+ * \param[in] additional_data Additional data that will be authenticated
+ * but not encrypted.
+ * \param additional_data_length Size of \p additional_data in bytes.
+ * \param[in] plaintext Data that will be authenticated and
+ * encrypted.
+ * \param plaintext_length Size of \p plaintext in bytes.
+ * \param[out] ciphertext Output buffer for the authenticated and
+ * encrypted data. The additional data is not
+ * part of this output. For algorithms where the
+ * encrypted data and the authentication tag
+ * are defined as separate outputs, the
+ * authentication tag is appended to the
+ * encrypted data.
+ * \param ciphertext_size Size of the \p ciphertext buffer in bytes.
+ * This must be at least
+ * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg,
+ * \p plaintext_length).
+ * \param[out] ciphertext_length On success, the size of the output
+ * in the \b ciphertext buffer.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \p alg is not supported or is not an AEAD algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_aead_encrypt(psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce,
+ size_t nonce_length,
+ const uint8_t *additional_data,
+ size_t additional_data_length,
+ const uint8_t *plaintext,
+ size_t plaintext_length,
+ uint8_t *ciphertext,
+ size_t ciphertext_size,
+ size_t *ciphertext_length);
+
+/** Process an authenticated decryption operation.
+ *
+ * \param key Slot containing the key to use.
+ * \param alg The AEAD algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_AEAD(\p alg) is true).
+ * \param[in] nonce Nonce or IV to use.
+ * \param nonce_length Size of the \p nonce buffer in bytes.
+ * \param[in] additional_data Additional data that has been authenticated
+ * but not encrypted.
+ * \param additional_data_length Size of \p additional_data in bytes.
+ * \param[in] ciphertext Data that has been authenticated and
+ * encrypted. For algorithms where the
+ * encrypted data and the authentication tag
+ * are defined as separate inputs, the buffer
+ * must contain the encrypted data followed
+ * by the authentication tag.
+ * \param ciphertext_length Size of \p ciphertext in bytes.
+ * \param[out] plaintext Output buffer for the decrypted data.
+ * \param plaintext_size Size of the \p plaintext buffer in bytes.
+ * This must be at least
+ * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg,
+ * \p ciphertext_length).
+ * \param[out] plaintext_length On success, the size of the output
+ * in the \b plaintext buffer.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ * The ciphertext is not authentic.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \p key is not compatible with \p alg.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \p alg is not supported or is not an AEAD algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_aead_decrypt(psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce,
+ size_t nonce_length,
+ const uint8_t *additional_data,
+ size_t additional_data_length,
+ const uint8_t *ciphertext,
+ size_t ciphertext_length,
+ uint8_t *plaintext,
+ size_t plaintext_size,
+ size_t *plaintext_length);
+
+/**@}*/
+
+/** \defgroup asymmetric Asymmetric cryptography
+ * @{
+ */
+
+/**
+ * \brief ECDSA signature size for a given curve bit size
+ *
+ * \param curve_bits Curve size in bits.
+ * \return Signature size in bytes.
+ *
+ * \note This macro returns a compile-time constant if its argument is one.
+ */
+#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \
+ (PSA_BITS_TO_BYTES(curve_bits) * 2)
+
+/**
+ * \brief Sign a hash or short message with a private key.
+ *
+ * Note that to perform a hash-and-sign signature algorithm, you must
+ * first calculate the hash by calling psa_hash_setup(), psa_hash_update()
+ * and psa_hash_finish(). Then pass the resulting hash as the \p hash
+ * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
+ * to determine the hash algorithm to use.
+ *
+ * \param key Key slot containing an asymmetric key pair.
+ * \param alg A signature algorithm that is compatible with
+ * the type of \p key.
+ * \param[in] hash The hash or message to sign.
+ * \param hash_length Size of the \p hash buffer in bytes.
+ * \param[out] signature Buffer where the signature is to be written.
+ * \param signature_size Size of the \p signature buffer in bytes.
+ * \param[out] signature_length On success, the number of bytes
+ * that make up the returned signature value.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p signature buffer is too small. You can
+ * determine a sufficient buffer size by calling
+ * #PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ * where \c key_type and \c key_bits are the type and bit-size
+ * respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+psa_status_t psa_asymmetric_sign(psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ uint8_t *signature,
+ size_t signature_size,
+ size_t *signature_length);
+
+/**
+ * \brief Verify the signature a hash or short message using a public key.
+ *
+ * Note that to perform a hash-and-sign signature algorithm, you must
+ * first calculate the hash by calling psa_hash_setup(), psa_hash_update()
+ * and psa_hash_finish(). Then pass the resulting hash as the \p hash
+ * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
+ * to determine the hash algorithm to use.
+ *
+ * \param key Key slot containing a public key or an
+ * asymmetric key pair.
+ * \param alg A signature algorithm that is compatible with
+ * the type of \p key.
+ * \param[in] hash The hash or message whose signature is to be
+ * verified.
+ * \param hash_length Size of the \p hash buffer in bytes.
+ * \param[in] signature Buffer containing the signature to verify.
+ * \param signature_length Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * The signature is valid.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ * The calculation was perfomed successfully, but the passed
+ * signature is not a valid signature.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_asymmetric_verify(psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ const uint8_t *signature,
+ size_t signature_length);
+
+#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \
+ (PSA_ALG_IS_RSA_OAEP(alg) ? \
+ 2 * PSA_HASH_FINAL_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \
+ 11 /*PKCS#1v1.5*/)
+
+/**
+ * \brief Encrypt a short message with a public key.
+ *
+ * \param key Key slot containing a public key or an
+ * asymmetric key pair.
+ * \param alg An asymmetric encryption algorithm that is
+ * compatible with the type of \p key.
+ * \param[in] input The message to encrypt.
+ * \param input_length Size of the \p input buffer in bytes.
+ * \param[in] salt A salt or label, if supported by the
+ * encryption algorithm.
+ * If the algorithm does not support a
+ * salt, pass \c NULL.
+ * If the algorithm supports an optional
+ * salt and you do not want to pass a salt,
+ * pass \c NULL.
+ *
+ * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is
+ * supported.
+ * \param salt_length Size of the \p salt buffer in bytes.
+ * If \p salt is \c NULL, pass 0.
+ * \param[out] output Buffer where the encrypted message is to
+ * be written.
+ * \param output_size Size of the \p output buffer in bytes.
+ * \param[out] output_length On success, the number of bytes
+ * that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p output buffer is too small. You can
+ * determine a sufficient buffer size by calling
+ * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ * where \c key_type and \c key_bits are the type and bit-size
+ * respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+psa_status_t psa_asymmetric_encrypt(psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *input,
+ size_t input_length,
+ const uint8_t *salt,
+ size_t salt_length,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length);
+
+/**
+ * \brief Decrypt a short message with a private key.
+ *
+ * \param key Key slot containing an asymmetric key pair.
+ * \param alg An asymmetric encryption algorithm that is
+ * compatible with the type of \p key.
+ * \param[in] input The message to decrypt.
+ * \param input_length Size of the \p input buffer in bytes.
+ * \param[in] salt A salt or label, if supported by the
+ * encryption algorithm.
+ * If the algorithm does not support a
+ * salt, pass \c NULL.
+ * If the algorithm supports an optional
+ * salt and you do not want to pass a salt,
+ * pass \c NULL.
+ *
+ * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is
+ * supported.
+ * \param salt_length Size of the \p salt buffer in bytes.
+ * If \p salt is \c NULL, pass 0.
+ * \param[out] output Buffer where the decrypted message is to
+ * be written.
+ * \param output_size Size of the \c output buffer in bytes.
+ * \param[out] output_length On success, the number of bytes
+ * that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of the \p output buffer is too small. You can
+ * determine a sufficient buffer size by calling
+ * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ * where \c key_type and \c key_bits are the type and bit-size
+ * respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_INVALID_PADDING
+ */
+psa_status_t psa_asymmetric_decrypt(psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *input,
+ size_t input_length,
+ const uint8_t *salt,
+ size_t salt_length,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length);
+
+/**@}*/
+
+/** \defgroup generators Generators
+ * @{
+ */
+
+/** The type of the state data structure for generators.
+ *
+ * Before calling any function on a generator, the application must
+ * initialize it by any of the following means:
+ * - Set the structure to all-bits-zero, for example:
+ * \code
+ * psa_crypto_generator_t generator;
+ * memset(&generator, 0, sizeof(generator));
+ * \endcode
+ * - Initialize the structure to logical zero values, for example:
+ * \code
+ * psa_crypto_generator_t generator = {0};
+ * \endcode
+ * - Initialize the structure to the initializer #PSA_CRYPTO_GENERATOR_INIT,
+ * for example:
+ * \code
+ * psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ * \endcode
+ * - Assign the result of the function psa_crypto_generator_init()
+ * to the structure, for example:
+ * \code
+ * psa_crypto_generator_t generator;
+ * generator = psa_crypto_generator_init();
+ * \endcode
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure except
+ * as directed by the documentation of a specific implementation.
+ */
+typedef struct psa_crypto_generator_s psa_crypto_generator_t;
+
+/** \def PSA_CRYPTO_GENERATOR_INIT
+ *
+ * This macro returns a suitable initializer for a generator object
+ * of type #psa_crypto_generator_t.
+ */
+#ifdef __DOXYGEN_ONLY__
+/* This is an example definition for documentation purposes.
+ * Implementations should define a suitable value in `crypto_struct.h`.
+ */
+#define PSA_CRYPTO_GENERATOR_INIT {0}
+#endif
+
+/** Return an initial value for a generator object.
+ */
+static psa_crypto_generator_t psa_crypto_generator_init(void);
+
+/** Retrieve the current capacity of a generator.
+ *
+ * The capacity of a generator is the maximum number of bytes that it can
+ * return. Reading *N* bytes from a generator reduces its capacity by *N*.
+ *
+ * \param[in] generator The generator to query.
+ * \param[out] capacity On success, the capacity of the generator.
+ *
+ * \retval PSA_SUCCESS
+ * \retval PSA_ERROR_BAD_STATE
+ * \retval PSA_ERROR_COMMUNICATION_FAILURE
+ */
+psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator,
+ size_t *capacity);
+
+/** Read some data from a generator.
+ *
+ * This function reads and returns a sequence of bytes from a generator.
+ * The data that is read is discarded from the generator. The generator's
+ * capacity is decreased by the number of bytes read.
+ *
+ * \param[in,out] generator The generator object to read from.
+ * \param[out] output Buffer where the generator output will be
+ * written.
+ * \param output_length Number of bytes to output.
+ *
+ * \retval PSA_SUCCESS
+ * \retval PSA_ERROR_INSUFFICIENT_CAPACITY
+ * There were fewer than \p output_length bytes
+ * in the generator. Note that in this case, no
+ * output is written to the output buffer.
+ * The generator's capacity is set to 0, thus
+ * subsequent calls to this function will not
+ * succeed, even with a smaller output buffer.
+ * \retval PSA_ERROR_BAD_STATE
+ * \retval PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval PSA_ERROR_HARDWARE_FAILURE
+ * \retval PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_generator_read(psa_crypto_generator_t *generator,
+ uint8_t *output,
+ size_t output_length);
+
+/** Create a symmetric key from data read from a generator.
+ *
+ * This function reads a sequence of bytes from a generator and imports
+ * these bytes as a key.
+ * The data that is read is discarded from the generator. The generator's
+ * capacity is decreased by the number of bytes read.
+ *
+ * This function is equivalent to calling #psa_generator_read and
+ * passing the resulting output to #psa_import_key, but
+ * if the implementation provides an isolation boundary then
+ * the key material is not exposed outside the isolation boundary.
+ *
+ * \param key Slot where the key will be stored. This must be a
+ * valid slot for a key of the chosen type. It must
+ * be unoccupied.
+ * \param type Key type (a \c PSA_KEY_TYPE_XXX value).
+ * This must be a symmetric key type.
+ * \param bits Key size in bits.
+ * \param[in,out] generator The generator object to read from.
+ *
+ * \retval PSA_SUCCESS
+ * Success.
+ * \retval PSA_ERROR_INSUFFICIENT_CAPACITY
+ * There were fewer than \p output_length bytes
+ * in the generator. Note that in this case, no
+ * output is written to the output buffer.
+ * The generator's capacity is set to 0, thus
+ * subsequent calls to this function will not
+ * succeed, even with a smaller output buffer.
+ * \retval PSA_ERROR_NOT_SUPPORTED
+ * The key type or key size is not supported, either by the
+ * implementation in general or in this particular slot.
+ * \retval PSA_ERROR_BAD_STATE
+ * \retval PSA_ERROR_INVALID_ARGUMENT
+ * The key slot is invalid.
+ * \retval PSA_ERROR_OCCUPIED_SLOT
+ * There is already a key in the specified slot.
+ * \retval PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval PSA_ERROR_HARDWARE_FAILURE
+ * \retval PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_generator_import_key(psa_key_slot_t key,
+ psa_key_type_t type,
+ size_t bits,
+ psa_crypto_generator_t *generator);
+
+/** Abort a generator.
+ *
+ * Once a generator has been aborted, its capacity is zero.
+ * Aborting a generator frees all associated resources except for the
+ * \c generator structure itself.
+ *
+ * This function may be called at any time as long as the generator
+ * object has been initialized to #PSA_CRYPTO_GENERATOR_INIT, to
+ * psa_crypto_generator_init() or a zero value. In particular, it is valid
+ * to call psa_generator_abort() twice, or to call psa_generator_abort()
+ * on a generator that has not been set up.
+ *
+ * Once aborted, the generator object may be called.
+ *
+ * \param[in,out] generator The generator to abort.
+ *
+ * \retval PSA_SUCCESS
+ * \retval PSA_ERROR_BAD_STATE
+ * \retval PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval PSA_ERROR_HARDWARE_FAILURE
+ * \retval PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_generator_abort(psa_crypto_generator_t *generator);
+
+/**@}*/
+
+/** \defgroup derivation Key derivation
+ * @{
+ */
+
+/** Set up a key derivation operation.
+ *
+ * A key derivation algorithm takes three inputs: a secret input \p key and
+ * two non-secret inputs \p label and p salt.
+ * The result of this function is a byte generator which can
+ * be used to produce keys and other cryptographic material.
+ *
+ * The role of \p label and \p salt is as follows:
+ * - For HKDF (#PSA_ALG_HKDF), \p salt is the salt used in the "extract" step
+ * and \p label is the info string used in the "expand" step.
+ *
+ * \param[in,out] generator The generator object to set up. It must
+ * have been initialized to .
+ * \param key Slot containing the secret key to use.
+ * \param alg The key derivation algorithm to compute
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true).
+ * \param[in] salt Salt to use.
+ * \param salt_length Size of the \p salt buffer in bytes.
+ * \param[in] label Label to use.
+ * \param label_length Size of the \p label buffer in bytes.
+ * \param capacity The maximum number of bytes that the
+ * generator will be able to provide.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \c key is not compatible with \c alg,
+ * or \p capacity is too large for the specified algorithm and key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \c alg is not supported or is not a key derivation algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_key_derivation(psa_crypto_generator_t *generator,
+ psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *salt,
+ size_t salt_length,
+ const uint8_t *label,
+ size_t label_length,
+ size_t capacity);
+
+/**@}*/
+
+/** \defgroup random Random generation
+ * @{
+ */
+
+/**
+ * \brief Generate random bytes.
+ *
+ * \warning This function **can** fail! Callers MUST check the return status
+ * and MUST NOT use the content of the output buffer if the return
+ * status is not #PSA_SUCCESS.
+ *
+ * \note To generate a key, use psa_generate_key() instead.
+ *
+ * \param[out] output Output buffer for the generated data.
+ * \param output_size Number of bytes to generate and output.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_generate_random(uint8_t *output,
+ size_t output_size);
+
+/** Extra parameters for RSA key generation.
+ *
+ * You may pass a pointer to a structure of this type as the \c extra
+ * parameter to psa_generate_key().
+ */
+typedef struct {
+ uint32_t e; /**< Public exponent value. Default: 65537. */
+} psa_generate_key_extra_rsa;
+
+/**
+ * \brief Generate a key or key pair.
+ *
+ * \param key Slot where the key will be stored. This must be a
+ * valid slot for a key of the chosen type. It must
+ * be unoccupied.
+ * \param type Key type (a \c PSA_KEY_TYPE_XXX value).
+ * \param bits Key size in bits.
+ * \param[in] extra Extra parameters for key generation. The
+ * interpretation of this parameter depends on
+ * \p type. All types support \c NULL to use
+ * default parameters. Implementation that support
+ * the generation of vendor-specific key types
+ * that allow extra parameters shall document
+ * the format of these extra parameters and
+ * the default values. For standard parameters,
+ * the meaning of \p extra is as follows:
+ * - For a symmetric key type (a type such
+ * that #PSA_KEY_TYPE_IS_ASYMMETRIC(\p type) is
+ * false), \p extra must be \c NULL.
+ * - For an elliptic curve key type (a type
+ * such that #PSA_KEY_TYPE_IS_ECC(\p type) is
+ * false), \p extra must be \c NULL.
+ * - For an RSA key (\p type is
+ * #PSA_KEY_TYPE_RSA_KEYPAIR), \p extra is an
+ * optional #psa_generate_key_extra_rsa structure
+ * specifying the public exponent. The
+ * default public exponent used when \p extra
+ * is \c NULL is 65537.
+ * \param extra_size Size of the buffer that \p extra
+ * points to, in bytes. Note that if \p extra is
+ * \c NULL then \p extra_size must be zero.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_generate_key(psa_key_slot_t key,
+ psa_key_type_t type,
+ size_t bits,
+ const void *extra,
+ size_t extra_size);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+/* The file "crypto_sizes.h" contains definitions for size calculation
+ * macros whose definitions are implementation-specific. */
+#include "crypto_sizes.h"
+
+/* The file "crypto_struct.h" contains definitions for
+ * implementation-specific structs that are declared above. */
+#include "crypto_struct.h"
+
+/* The file "crypto_extra.h" contains vendor-specific definitions. This
+ * can include vendor-defined algorithms, extra functions, etc. */
+#include "crypto_extra.h"
+
+#endif /* PSA_CRYPTO_H */
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
new file mode 100644
index 0000000..c587eb2
--- /dev/null
+++ b/include/psa/crypto_extra.h
@@ -0,0 +1,51 @@
+/**
+ * \file psa/crypto_extra.h
+ *
+ * \brief PSA cryptography module: Mbed Crypto vendor extensions
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * This file is reserved for vendor-specific definitions.
+ */
+/*
+ * Copyright (C) 2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_EXTRA_H
+#define PSA_CRYPTO_EXTRA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Library deinitialization.
+ *
+ * This function clears all data associated with the PSA layer,
+ * including the whole key store.
+ *
+ * This is an Mbed Crypto extension.
+ */
+void mbedcrypto_psa_crypto_free( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PSA_CRYPTO_EXTRA_H */
diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h
new file mode 100644
index 0000000..69ccd56
--- /dev/null
+++ b/include/psa/crypto_platform.h
@@ -0,0 +1,52 @@
+/**
+ * \file psa/crypto_platform.h
+ *
+ * \brief PSA cryptography module: Mbed Crypto platfom definitions
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * This file contains platform-dependent type definitions.
+ *
+ * In implementations with isolation between the application and the
+ * cryptography module, implementers should take care to ensure that
+ * the definitions that are exposed to applications match what the
+ * module implements.
+ */
+/*
+ * Copyright (C) 2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_PLATFORM_H
+#define PSA_CRYPTO_PLATFORM_H
+
+/* Include the Mbed Crypto configuration file, the way Mbed Crypto does it
+ * in each of its header files. */
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "../mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+/* PSA requires several types which C99 provides in stdint.h. */
+#include <stdint.h>
+
+/* Integral type representing a key slot number. */
+typedef uint16_t psa_key_slot_t;
+
+#endif /* PSA_CRYPTO_PLATFORM_H */
diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h
new file mode 100644
index 0000000..9a0ae59
--- /dev/null
+++ b/include/psa/crypto_sizes.h
@@ -0,0 +1,308 @@
+/**
+ * \file psa/crypto_sizes.h
+ *
+ * \brief PSA cryptography module: Mbed Crypto buffer size macros
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * This file contains the definitions of macros that are useful to
+ * compute buffer sizes. The signatures and semantics of these macros
+ * are standardized, but the definitions are not, because they depend on
+ * the available algorithms and, in some cases, on permitted tolerances
+ * on buffer sizes.
+ *
+ * In implementations with isolation between the application and the
+ * cryptography module, implementers should take care to ensure that
+ * the definitions that are exposed to applications match what the
+ * module implements.
+ *
+ * Macros that compute sizes whose values do not depend on the
+ * implementation are in crypto.h.
+ */
+/*
+ * Copyright (C) 2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_SIZES_H
+#define PSA_CRYPTO_SIZES_H
+
+/* Include the Mbed Crypto configuration file, the way Mbed Crypto does it
+ * in each of its header files. */
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "../mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+/** \def PSA_HASH_MAX_SIZE
+ *
+ * Maximum size of a hash.
+ *
+ * This macro must expand to a compile-time constant integer. This value
+ * should be the maximum size of a hash supported by the implementation,
+ * in bytes, and must be no smaller than this maximum.
+ */
+#if defined(MBEDCRYPTO_SHA512_C)
+#define PSA_HASH_MAX_SIZE 64
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128
+#else
+#define PSA_HASH_MAX_SIZE 32
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64
+#endif
+
+/** \def PSA_MAC_MAX_SIZE
+ *
+ * Maximum size of a MAC.
+ *
+ * This macro must expand to a compile-time constant integer. This value
+ * should be the maximum size of a MAC supported by the implementation,
+ * in bytes, and must be no smaller than this maximum.
+ */
+/* All non-HMAC MACs have a maximum size that's smaller than the
+ * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */
+#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE
+
+/* The maximum size of an RSA key on this implementation, in bits.
+ * This is a vendor-specific macro.
+ *
+ * Mbed Crypto does not set a hard limit on the size of RSA keys: any key
+ * whose parameters fit in a bignum is accepted. However large keys can
+ * induce a large memory usage and long computation times. Unlike other
+ * auxiliary macros in this file and in crypto.h, which reflect how the
+ * library is configured, this macro defines how the library is
+ * configured. This implementation refuses to import or generate an
+ * RSA key whose size is larger than the value defined here.
+ *
+ * Note that an implementation may set different size limits for different
+ * operations, and does not need to accept all key sizes up to the limit. */
+#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096
+
+/* The maximum size of an ECC key on this implementation, in bits.
+ * This is a vendor-specific macro. */
+#if defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521
+#elif defined(MBEDCRYPTO_ECP_DP_BP512R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512
+#elif defined(MBEDCRYPTO_ECP_DP_CURVE448_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448
+#elif defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384
+#elif defined(MBEDCRYPTO_ECP_DP_BP384R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384
+#elif defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
+#elif defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
+#elif defined(MBEDCRYPTO_ECP_DP_BP256R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
+#elif defined(MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255
+#elif defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224
+#elif defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224
+#elif defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192
+#elif defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192
+#else
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0
+#endif
+
+/** \def PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE
+ *
+ * Maximum size of an asymmetric signature.
+ *
+ * This macro must expand to a compile-time constant integer. This value
+ * should be the maximum size of a MAC supported by the implementation,
+ * in bytes, and must be no smaller than this maximum.
+ */
+#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \
+ PSA_BITS_TO_BYTES( \
+ PSA_VENDOR_RSA_MAX_KEY_BITS > PSA_VENDOR_ECC_MAX_CURVE_BITS ? \
+ PSA_VENDOR_RSA_MAX_KEY_BITS : \
+ PSA_VENDOR_ECC_MAX_CURVE_BITS \
+ )
+
+
+
+/** The size of the output of psa_mac_sign_finish(), in bytes.
+ *
+ * This is also the MAC size that psa_mac_verify_finish() expects.
+ *
+ * \param key_type The type of the MAC key.
+ * \param key_bits The size of the MAC key in bits.
+ * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_MAC(alg) is true).
+ *
+ * \return The MAC size for the specified algorithm with
+ * the specified key parameters.
+ * \return 0 if the MAC algorithm is not recognized.
+ * \return Either 0 or the correct size for a MAC algorithm that
+ * the implementation recognizes, but does not support.
+ * \return Unspecified if the key parameters are not consistent
+ * with the algorithm.
+ */
+#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \
+ (PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_HASH(alg)) : \
+ PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \
+ 0)
+
+/** The maximum size of the output of psa_aead_encrypt(), in bytes.
+ *
+ * If the size of the ciphertext buffer is at least this large, it is
+ * guaranteed that psa_aead_encrypt() will not fail due to an
+ * insufficient buffer size. Depending on the algorithm, the actual size of
+ * the ciphertext may be smaller.
+ *
+ * \param alg An AEAD algorithm
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_AEAD(alg) is true).
+ * \param plaintext_length Size of the plaintext in bytes.
+ *
+ * \return The AEAD ciphertext size for the specified
+ * algorithm.
+ * If the AEAD algorithm is not recognized, return 0.
+ * An implementation may return either 0 or a
+ * correct size for an AEAD algorithm that it
+ * recognizes, but does not support.
+ */
+#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \
+ (PSA_AEAD_TAG_SIZE(alg) != 0 ? \
+ (plaintext_length) + PSA_AEAD_TAG_SIZE(alg) : \
+ 0)
+
+/** The maximum size of the output of psa_aead_decrypt(), in bytes.
+ *
+ * If the size of the plaintext buffer is at least this large, it is
+ * guaranteed that psa_aead_decrypt() will not fail due to an
+ * insufficient buffer size. Depending on the algorithm, the actual size of
+ * the plaintext may be smaller.
+ *
+ * \param alg An AEAD algorithm
+ * (\c PSA_ALG_XXX value such that
+ * #PSA_ALG_IS_AEAD(alg) is true).
+ * \param ciphertext_length Size of the plaintext in bytes.
+ *
+ * \return The AEAD ciphertext size for the specified
+ * algorithm.
+ * If the AEAD algorithm is not recognized, return 0.
+ * An implementation may return either 0 or a
+ * correct size for an AEAD algorithm that it
+ * recognizes, but does not support.
+ */
+#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \
+ (PSA_AEAD_TAG_SIZE(alg) != 0 ? \
+ (plaintext_length) - PSA_AEAD_TAG_SIZE(alg) : \
+ 0)
+
+/** Safe signature buffer size for psa_asymmetric_sign().
+ *
+ * This macro returns a safe buffer size for a signature using a key
+ * of the specified type and size, with the specified algorithm.
+ * Note that the actual size of the signature may be smaller
+ * (some algorithms produce a variable-size signature).
+ *
+ * \warning This function may call its arguments multiple times or
+ * zero times, so you should not pass arguments that contain
+ * side effects.
+ *
+ * \param key_type An asymmetric key type (this may indifferently be a
+ * key pair type or a public key type).
+ * \param key_bits The size of the key in bits.
+ * \param alg The signature algorithm.
+ *
+ * \return If the parameters are valid and supported, return
+ * a buffer size in bytes that guarantees that
+ * psa_asymmetric_sign() will not fail with
+ * #PSA_ERROR_BUFFER_TOO_SMALL.
+ * If the parameters are a valid combination that is not supported
+ * by the implementation, this macro either shall return either a
+ * sensible size or 0.
+ * If the parameters are not valid, the
+ * return value is unspecified.
+ */
+#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \
+ (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \
+ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \
+ ((void)alg, 0))
+
+/** Safe output buffer size for psa_asymmetric_encrypt().
+ *
+ * This macro returns a safe buffer size for a ciphertext produced using
+ * a key of the specified type and size, with the specified algorithm.
+ * Note that the actual size of the ciphertext may be smaller, depending
+ * on the algorithm.
+ *
+ * \warning This function may call its arguments multiple times or
+ * zero times, so you should not pass arguments that contain
+ * side effects.
+ *
+ * \param key_type An asymmetric key type (this may indifferently be a
+ * key pair type or a public key type).
+ * \param key_bits The size of the key in bits.
+ * \param alg The signature algorithm.
+ *
+ * \return If the parameters are valid and supported, return
+ * a buffer size in bytes that guarantees that
+ * psa_asymmetric_encrypt() will not fail with
+ * #PSA_ERROR_BUFFER_TOO_SMALL.
+ * If the parameters are a valid combination that is not supported
+ * by the implementation, this macro either shall return either a
+ * sensible size or 0.
+ * If the parameters are not valid, the
+ * return value is unspecified.
+ */
+#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \
+ (PSA_KEY_TYPE_IS_RSA(key_type) ? \
+ ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \
+ 0)
+
+/** Safe output buffer size for psa_asymmetric_decrypt().
+ *
+ * This macro returns a safe buffer size for a ciphertext produced using
+ * a key of the specified type and size, with the specified algorithm.
+ * Note that the actual size of the ciphertext may be smaller, depending
+ * on the algorithm.
+ *
+ * \warning This function may call its arguments multiple times or
+ * zero times, so you should not pass arguments that contain
+ * side effects.
+ *
+ * \param key_type An asymmetric key type (this may indifferently be a
+ * key pair type or a public key type).
+ * \param key_bits The size of the key in bits.
+ * \param alg The signature algorithm.
+ *
+ * \return If the parameters are valid and supported, return
+ * a buffer size in bytes that guarantees that
+ * psa_asymmetric_decrypt() will not fail with
+ * #PSA_ERROR_BUFFER_TOO_SMALL.
+ * If the parameters are a valid combination that is not supported
+ * by the implementation, this macro either shall return either a
+ * sensible size or 0.
+ * If the parameters are not valid, the
+ * return value is unspecified.
+ */
+#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \
+ (PSA_KEY_TYPE_IS_RSA(key_type) ? \
+ PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \
+ 0)
+
+#endif /* PSA_CRYPTO_SIZES_H */
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
new file mode 100644
index 0000000..5769a0c
--- /dev/null
+++ b/include/psa/crypto_struct.h
@@ -0,0 +1,177 @@
+/**
+ * \file psa/crypto_struct.h
+ *
+ * \brief PSA cryptography module: Mbed Crypto structured type implementations
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * This file contains the definitions of some data structures with
+ * implementation-specific definitions.
+ *
+ * In implementations with isolation between the application and the
+ * cryptography module, it is expected that the front-end and the back-end
+ * would have different versions of this file.
+ */
+/*
+ * Copyright (C) 2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_STRUCT_H
+#define PSA_CRYPTO_STRUCT_H
+
+/* Include the Mbed Crypto configuration file, the way Mbed Crypto does it
+ * in each of its header files. */
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "../mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "mbedcrypto/cipher.h"
+#include "mbedcrypto/cmac.h"
+#include "mbedcrypto/gcm.h"
+#include "mbedcrypto/md.h"
+#include "mbedcrypto/md2.h"
+#include "mbedcrypto/md4.h"
+#include "mbedcrypto/md5.h"
+#include "mbedcrypto/ripemd160.h"
+#include "mbedcrypto/sha1.h"
+#include "mbedcrypto/sha256.h"
+#include "mbedcrypto/sha512.h"
+
+struct psa_hash_operation_s
+{
+ psa_algorithm_t alg;
+ union
+ {
+ unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+#if defined(MBEDCRYPTO_MD2_C)
+ mbedcrypto_md2_context md2;
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+ mbedcrypto_md4_context md4;
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+ mbedcrypto_md5_context md5;
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+ mbedcrypto_ripemd160_context ripemd160;
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+ mbedcrypto_sha1_context sha1;
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+ mbedcrypto_sha256_context sha256;
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+ mbedcrypto_sha512_context sha512;
+#endif
+ } ctx;
+};
+
+
+typedef struct
+{
+ /** The hash context. */
+ struct psa_hash_operation_s hash_ctx;
+ /** The HMAC part of the context. */
+ uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+} psa_hmac_internal_data;
+
+
+struct psa_mac_operation_s
+{
+ psa_algorithm_t alg;
+ unsigned int key_set : 1;
+ unsigned int iv_required : 1;
+ unsigned int iv_set : 1;
+ unsigned int has_input : 1;
+ unsigned int is_sign : 1;
+ uint8_t mac_size;
+ union
+ {
+ unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+#if defined(MBEDCRYPTO_MD_C)
+ psa_hmac_internal_data hmac;
+#endif
+#if defined(MBEDCRYPTO_CMAC_C)
+ mbedcrypto_cipher_context_t cmac;
+#endif
+ } ctx;
+};
+
+struct psa_cipher_operation_s
+{
+ psa_algorithm_t alg;
+ unsigned int key_set : 1;
+ unsigned int iv_required : 1;
+ unsigned int iv_set : 1;
+ uint8_t iv_size;
+ uint8_t block_size;
+ union
+ {
+ mbedcrypto_cipher_context_t cipher;
+ } ctx;
+};
+
+typedef struct
+{
+ uint8_t *info;
+ size_t info_length;
+ psa_hmac_internal_data hmac;
+ uint8_t prk[PSA_HASH_MAX_SIZE];
+ uint8_t output_block[PSA_HASH_MAX_SIZE];
+#if PSA_HASH_MAX_SIZE > 0xff
+#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
+#endif
+ uint8_t offset_in_block;
+ uint8_t block_number;
+} psa_hkdf_generator_t;
+
+struct psa_crypto_generator_s
+{
+ psa_algorithm_t alg;
+ size_t capacity;
+ union
+ {
+ struct
+ {
+ uint8_t *data;
+ size_t size;
+ } buffer;
+#if defined(MBEDCRYPTO_MD_C)
+ psa_hkdf_generator_t hkdf;
+#endif
+ } ctx;
+};
+
+#define PSA_CRYPTO_GENERATOR_INIT {0, 0, {{0, 0}}}
+static inline struct psa_crypto_generator_s psa_crypto_generator_init( void )
+{
+ const struct psa_crypto_generator_s v = PSA_CRYPTO_GENERATOR_INIT;
+ return( v );
+}
+
+struct psa_key_policy_s
+{
+ psa_key_usage_t usage;
+ psa_algorithm_t alg;
+};
+
+#endif /* PSA_CRYPTO_STRUCT_H */
diff --git a/library/Makefile b/library/Makefile
new file mode 100644
index 0000000..9151662
--- /dev/null
+++ b/library/Makefile
@@ -0,0 +1,76 @@
+CFLAGS ?= -O2 -I../include
+WARNING_CFLAGS ?= \
+ -Werror -Wall -Wextra \
+ -Wno-unused-function \
+ -Wno-overlength-strings \
+ -Wdeclaration-after-statement \
+# Don't delete this line.
+
+OBJS_CRYPTO := \
+ aes.o \
+ aesni.o \
+ arc4.o \
+ asn1parse.o \
+ asn1write.o \
+ base64.o \
+ bignum.o \
+ blowfish.o \
+ camellia.o \
+ ccm.o \
+ cipher.o \
+ cipher_wrap.o \
+ cmac.o \
+ ctr_drbg.o \
+ des.o \
+ ecdsa.o \
+ ecp.o \
+ ecp_curves.o \
+ entropy.o \
+ entropy_poll.o \
+ gcm.o \
+ hmac_drbg.o \
+ md.o \
+ md2.o \
+ md4.o \
+ md5.o \
+ md_wrap.o \
+ oid.o \
+ pem.o \
+ pk.o \
+ pk_wrap.o \
+ pkcs12.o \
+ pkcs5.o \
+ pkparse.o \
+ pkwrite.o \
+ platform.o \
+ platform_util.o \
+ psa_crypto.o \
+ ripemd160.o \
+ rsa_internal.o \
+ rsa.o \
+ sha1.o \
+ sha256.o \
+ sha512.o \
+ xtea.o \
+# Don't delete this line.
+
+.SILENT:
+
+.PHONY: all static clean
+
+all: static
+
+static: libmbedcrypto.a
+
+libmbedcrypto.a: $(OBJS_CRYPTO)
+ echo " AR $@"
+ $(AR) -rc $@ $(OBJS_CRYPTO)
+ echo " RL $@"
+ $(AR) -s $@
+
+.c.o:
+ echo " CC $<"
+ $(CC) $(CFLAGS) $(WARNING_CFLAGS) -c $<
+
+clean:
+ rm -f *.o libmbedcrypto.a
diff --git a/library/aes.c b/library/aes.c
new file mode 100644
index 0000000..4841243
--- /dev/null
+++ b/library/aes.c
@@ -0,0 +1,1574 @@
+/*
+ * FIPS-197 compliant AES implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_AES_C)
+
+#include <string.h>
+
+#include "mbedcrypto/aes.h"
+#include "mbedcrypto/platform_util.h"
+#if defined(MBEDCRYPTO_PADLOCK_C)
+#include "mbedcrypto/padlock.h"
+#endif
+#if defined(MBEDCRYPTO_AESNI_C)
+#include "mbedcrypto/aesni.h"
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_AES_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
+ (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
+ (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
+ (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
+}
+#endif
+
+#if defined(MBEDCRYPTO_PADLOCK_C) && \
+ ( defined(MBEDCRYPTO_HAVE_X86) || defined(MBEDCRYPTO_PADLOCK_ALIGN16) )
+static int aes_padlock_ace = -1;
+#endif
+
+#if defined(MBEDCRYPTO_AES_ROM_TABLES)
+/*
+ * Forward S-box
+ */
+static const unsigned char FSb[256] =
+{
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
+ 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
+ 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
+ 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
+ 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
+ 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
+ 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
+ 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
+ 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
+ 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
+ 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
+ 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+};
+
+/*
+ * Forward tables
+ */
+#define FT \
+\
+ V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
+ V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
+ V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
+ V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
+ V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
+ V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
+ V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
+ V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
+ V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
+ V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
+ V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
+ V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
+ V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
+ V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
+ V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
+ V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
+ V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
+ V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
+ V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
+ V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
+ V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
+ V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
+ V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
+ V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
+ V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
+ V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
+ V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
+ V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
+ V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
+ V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
+ V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
+ V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
+ V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
+ V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
+ V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
+ V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
+ V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
+ V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
+ V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
+ V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
+ V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
+ V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
+ V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
+ V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
+ V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
+ V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
+ V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
+ V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
+ V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
+ V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
+ V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
+ V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
+ V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
+ V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
+ V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
+ V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
+ V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
+ V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
+ V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
+ V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
+ V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
+ V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
+ V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
+ V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const uint32_t FT0[256] = { FT };
+#undef V
+
+#if !defined(MBEDCRYPTO_AES_FEWER_TABLES)
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const uint32_t FT1[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const uint32_t FT2[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const uint32_t FT3[256] = { FT };
+#undef V
+
+#endif /* !MBEDCRYPTO_AES_FEWER_TABLES */
+
+#undef FT
+
+/*
+ * Reverse S-box
+ */
+static const unsigned char RSb[256] =
+{
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
+ 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
+ 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
+ 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
+ 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
+ 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
+ 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
+ 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
+ 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
+ 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
+ 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
+ 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+};
+
+/*
+ * Reverse tables
+ */
+#define RT \
+\
+ V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
+ V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
+ V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
+ V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
+ V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
+ V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
+ V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
+ V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
+ V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
+ V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
+ V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
+ V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
+ V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
+ V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
+ V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
+ V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
+ V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
+ V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
+ V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
+ V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
+ V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
+ V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
+ V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
+ V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
+ V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
+ V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
+ V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
+ V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
+ V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
+ V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
+ V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
+ V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
+ V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
+ V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
+ V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
+ V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
+ V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
+ V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
+ V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
+ V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
+ V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
+ V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
+ V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
+ V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
+ V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
+ V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
+ V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
+ V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
+ V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
+ V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
+ V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
+ V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
+ V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
+ V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
+ V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
+ V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
+ V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
+ V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
+ V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
+ V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
+ V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
+ V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
+ V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
+ V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const uint32_t RT0[256] = { RT };
+#undef V
+
+#if !defined(MBEDCRYPTO_AES_FEWER_TABLES)
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const uint32_t RT1[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const uint32_t RT2[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const uint32_t RT3[256] = { RT };
+#undef V
+
+#endif /* !MBEDCRYPTO_AES_FEWER_TABLES */
+
+#undef RT
+
+/*
+ * Round constants
+ */
+static const uint32_t RCON[10] =
+{
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008,
+ 0x00000010, 0x00000020, 0x00000040, 0x00000080,
+ 0x0000001B, 0x00000036
+};
+
+#else /* MBEDCRYPTO_AES_ROM_TABLES */
+
+/*
+ * Forward S-box & tables
+ */
+static unsigned char FSb[256];
+static uint32_t FT0[256];
+#if !defined(MBEDCRYPTO_AES_FEWER_TABLES)
+static uint32_t FT1[256];
+static uint32_t FT2[256];
+static uint32_t FT3[256];
+#endif /* !MBEDCRYPTO_AES_FEWER_TABLES */
+
+/*
+ * Reverse S-box & tables
+ */
+static unsigned char RSb[256];
+static uint32_t RT0[256];
+#if !defined(MBEDCRYPTO_AES_FEWER_TABLES)
+static uint32_t RT1[256];
+static uint32_t RT2[256];
+static uint32_t RT3[256];
+#endif /* !MBEDCRYPTO_AES_FEWER_TABLES */
+
+/*
+ * Round constants
+ */
+static uint32_t RCON[10];
+
+/*
+ * Tables generation code
+ */
+#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
+#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
+#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
+
+static int aes_init_done = 0;
+
+static void aes_gen_tables( void )
+{
+ int i, x, y, z;
+ int pow[256];
+ int log[256];
+
+ /*
+ * compute pow and log tables over GF(2^8)
+ */
+ for( i = 0, x = 1; i < 256; i++ )
+ {
+ pow[i] = x;
+ log[x] = i;
+ x = ( x ^ XTIME( x ) ) & 0xFF;
+ }
+
+ /*
+ * calculate the round constants
+ */
+ for( i = 0, x = 1; i < 10; i++ )
+ {
+ RCON[i] = (uint32_t) x;
+ x = XTIME( x ) & 0xFF;
+ }
+
+ /*
+ * generate the forward and reverse S-boxes
+ */
+ FSb[0x00] = 0x63;
+ RSb[0x63] = 0x00;
+
+ for( i = 1; i < 256; i++ )
+ {
+ x = pow[255 - log[i]];
+
+ y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+ x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+ x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+ x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+ x ^= y ^ 0x63;
+
+ FSb[i] = (unsigned char) x;
+ RSb[x] = (unsigned char) i;
+ }
+
+ /*
+ * generate the forward and reverse tables
+ */
+ for( i = 0; i < 256; i++ )
+ {
+ x = FSb[i];
+ y = XTIME( x ) & 0xFF;
+ z = ( y ^ x ) & 0xFF;
+
+ FT0[i] = ( (uint32_t) y ) ^
+ ( (uint32_t) x << 8 ) ^
+ ( (uint32_t) x << 16 ) ^
+ ( (uint32_t) z << 24 );
+
+#if !defined(MBEDCRYPTO_AES_FEWER_TABLES)
+ FT1[i] = ROTL8( FT0[i] );
+ FT2[i] = ROTL8( FT1[i] );
+ FT3[i] = ROTL8( FT2[i] );
+#endif /* !MBEDCRYPTO_AES_FEWER_TABLES */
+
+ x = RSb[i];
+
+ RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^
+ ( (uint32_t) MUL( 0x09, x ) << 8 ) ^
+ ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
+ ( (uint32_t) MUL( 0x0B, x ) << 24 );
+
+#if !defined(MBEDCRYPTO_AES_FEWER_TABLES)
+ RT1[i] = ROTL8( RT0[i] );
+ RT2[i] = ROTL8( RT1[i] );
+ RT3[i] = ROTL8( RT2[i] );
+#endif /* !MBEDCRYPTO_AES_FEWER_TABLES */
+ }
+}
+
+#undef ROTL8
+
+#endif /* MBEDCRYPTO_AES_ROM_TABLES */
+
+#if defined(MBEDCRYPTO_AES_FEWER_TABLES)
+
+#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) )
+#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) )
+#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) )
+
+#define AES_RT0(idx) RT0[idx]
+#define AES_RT1(idx) ROTL8( RT0[idx] )
+#define AES_RT2(idx) ROTL16( RT0[idx] )
+#define AES_RT3(idx) ROTL24( RT0[idx] )
+
+#define AES_FT0(idx) FT0[idx]
+#define AES_FT1(idx) ROTL8( FT0[idx] )
+#define AES_FT2(idx) ROTL16( FT0[idx] )
+#define AES_FT3(idx) ROTL24( FT0[idx] )
+
+#else /* MBEDCRYPTO_AES_FEWER_TABLES */
+
+#define AES_RT0(idx) RT0[idx]
+#define AES_RT1(idx) RT1[idx]
+#define AES_RT2(idx) RT2[idx]
+#define AES_RT3(idx) RT3[idx]
+
+#define AES_FT0(idx) FT0[idx]
+#define AES_FT1(idx) FT1[idx]
+#define AES_FT2(idx) FT2[idx]
+#define AES_FT3(idx) FT3[idx]
+
+#endif /* MBEDCRYPTO_AES_FEWER_TABLES */
+
+void mbedcrypto_aes_init( mbedcrypto_aes_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_aes_context ) );
+}
+
+void mbedcrypto_aes_free( mbedcrypto_aes_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_aes_context ) );
+}
+
+/*
+ * AES key schedule (encryption)
+ */
+#if !defined(MBEDCRYPTO_AES_SETKEY_ENC_ALT)
+int mbedcrypto_aes_setkey_enc( mbedcrypto_aes_context *ctx, const unsigned char *key,
+ unsigned int keybits )
+{
+ unsigned int i;
+ uint32_t *RK;
+
+#if !defined(MBEDCRYPTO_AES_ROM_TABLES)
+ if( aes_init_done == 0 )
+ {
+ aes_gen_tables();
+ aes_init_done = 1;
+
+ }
+#endif
+
+ switch( keybits )
+ {
+ case 128: ctx->nr = 10; break;
+ case 192: ctx->nr = 12; break;
+ case 256: ctx->nr = 14; break;
+ default : return( MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+#if defined(MBEDCRYPTO_PADLOCK_C) && defined(MBEDCRYPTO_PADLOCK_ALIGN16)
+ if( aes_padlock_ace == -1 )
+ aes_padlock_ace = mbedcrypto_padlock_has_support( MBEDCRYPTO_PADLOCK_ACE );
+
+ if( aes_padlock_ace )
+ ctx->rk = RK = MBEDCRYPTO_PADLOCK_ALIGN16( ctx->buf );
+ else
+#endif
+ ctx->rk = RK = ctx->buf;
+
+#if defined(MBEDCRYPTO_AESNI_C) && defined(MBEDCRYPTO_HAVE_X86_64)
+ if( mbedcrypto_aesni_has_support( MBEDCRYPTO_AESNI_AES ) )
+ return( mbedcrypto_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) );
+#endif
+
+ for( i = 0; i < ( keybits >> 5 ); i++ )
+ {
+ GET_UINT32_LE( RK[i], key, i << 2 );
+ }
+
+ switch( ctx->nr )
+ {
+ case 10:
+
+ for( i = 0; i < 10; i++, RK += 4 )
+ {
+ RK[4] = RK[0] ^ RCON[i] ^
+ ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 );
+
+ RK[5] = RK[1] ^ RK[4];
+ RK[6] = RK[2] ^ RK[5];
+ RK[7] = RK[3] ^ RK[6];
+ }
+ break;
+
+ case 12:
+
+ for( i = 0; i < 8; i++, RK += 6 )
+ {
+ RK[6] = RK[0] ^ RCON[i] ^
+ ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 );
+
+ RK[7] = RK[1] ^ RK[6];
+ RK[8] = RK[2] ^ RK[7];
+ RK[9] = RK[3] ^ RK[8];
+ RK[10] = RK[4] ^ RK[9];
+ RK[11] = RK[5] ^ RK[10];
+ }
+ break;
+
+ case 14:
+
+ for( i = 0; i < 7; i++, RK += 8 )
+ {
+ RK[8] = RK[0] ^ RCON[i] ^
+ ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 );
+
+ RK[9] = RK[1] ^ RK[8];
+ RK[10] = RK[2] ^ RK[9];
+ RK[11] = RK[3] ^ RK[10];
+
+ RK[12] = RK[4] ^
+ ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
+
+ RK[13] = RK[5] ^ RK[12];
+ RK[14] = RK[6] ^ RK[13];
+ RK[15] = RK[7] ^ RK[14];
+ }
+ break;
+ }
+
+ return( 0 );
+}
+#endif /* !MBEDCRYPTO_AES_SETKEY_ENC_ALT */
+
+/*
+ * AES key schedule (decryption)
+ */
+#if !defined(MBEDCRYPTO_AES_SETKEY_DEC_ALT)
+int mbedcrypto_aes_setkey_dec( mbedcrypto_aes_context *ctx, const unsigned char *key,
+ unsigned int keybits )
+{
+ int i, j, ret;
+ mbedcrypto_aes_context cty;
+ uint32_t *RK;
+ uint32_t *SK;
+
+ mbedcrypto_aes_init( &cty );
+
+#if defined(MBEDCRYPTO_PADLOCK_C) && defined(MBEDCRYPTO_PADLOCK_ALIGN16)
+ if( aes_padlock_ace == -1 )
+ aes_padlock_ace = mbedcrypto_padlock_has_support( MBEDCRYPTO_PADLOCK_ACE );
+
+ if( aes_padlock_ace )
+ ctx->rk = RK = MBEDCRYPTO_PADLOCK_ALIGN16( ctx->buf );
+ else
+#endif
+ ctx->rk = RK = ctx->buf;
+
+ /* Also checks keybits */
+ if( ( ret = mbedcrypto_aes_setkey_enc( &cty, key, keybits ) ) != 0 )
+ goto exit;
+
+ ctx->nr = cty.nr;
+
+#if defined(MBEDCRYPTO_AESNI_C) && defined(MBEDCRYPTO_HAVE_X86_64)
+ if( mbedcrypto_aesni_has_support( MBEDCRYPTO_AESNI_AES ) )
+ {
+ mbedcrypto_aesni_inverse_key( (unsigned char *) ctx->rk,
+ (const unsigned char *) cty.rk, ctx->nr );
+ goto exit;
+ }
+#endif
+
+ SK = cty.rk + cty.nr * 4;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
+ {
+ for( j = 0; j < 4; j++, SK++ )
+ {
+ *RK++ = AES_RT0( FSb[ ( *SK ) & 0xFF ] ) ^
+ AES_RT1( FSb[ ( *SK >> 8 ) & 0xFF ] ) ^
+ AES_RT2( FSb[ ( *SK >> 16 ) & 0xFF ] ) ^
+ AES_RT3( FSb[ ( *SK >> 24 ) & 0xFF ] );
+ }
+ }
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+exit:
+ mbedcrypto_aes_free( &cty );
+
+ return( ret );
+}
+#endif /* !MBEDCRYPTO_AES_SETKEY_DEC_ALT */
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ X0 = *RK++ ^ AES_FT0( ( Y0 ) & 0xFF ) ^ \
+ AES_FT1( ( Y1 >> 8 ) & 0xFF ) ^ \
+ AES_FT2( ( Y2 >> 16 ) & 0xFF ) ^ \
+ AES_FT3( ( Y3 >> 24 ) & 0xFF ); \
+ \
+ X1 = *RK++ ^ AES_FT0( ( Y1 ) & 0xFF ) ^ \
+ AES_FT1( ( Y2 >> 8 ) & 0xFF ) ^ \
+ AES_FT2( ( Y3 >> 16 ) & 0xFF ) ^ \
+ AES_FT3( ( Y0 >> 24 ) & 0xFF ); \
+ \
+ X2 = *RK++ ^ AES_FT0( ( Y2 ) & 0xFF ) ^ \
+ AES_FT1( ( Y3 >> 8 ) & 0xFF ) ^ \
+ AES_FT2( ( Y0 >> 16 ) & 0xFF ) ^ \
+ AES_FT3( ( Y1 >> 24 ) & 0xFF ); \
+ \
+ X3 = *RK++ ^ AES_FT0( ( Y3 ) & 0xFF ) ^ \
+ AES_FT1( ( Y0 >> 8 ) & 0xFF ) ^ \
+ AES_FT2( ( Y1 >> 16 ) & 0xFF ) ^ \
+ AES_FT3( ( Y2 >> 24 ) & 0xFF ); \
+}
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ X0 = *RK++ ^ AES_RT0( ( Y0 ) & 0xFF ) ^ \
+ AES_RT1( ( Y3 >> 8 ) & 0xFF ) ^ \
+ AES_RT2( ( Y2 >> 16 ) & 0xFF ) ^ \
+ AES_RT3( ( Y1 >> 24 ) & 0xFF ); \
+ \
+ X1 = *RK++ ^ AES_RT0( ( Y1 ) & 0xFF ) ^ \
+ AES_RT1( ( Y0 >> 8 ) & 0xFF ) ^ \
+ AES_RT2( ( Y3 >> 16 ) & 0xFF ) ^ \
+ AES_RT3( ( Y2 >> 24 ) & 0xFF ); \
+ \
+ X2 = *RK++ ^ AES_RT0( ( Y2 ) & 0xFF ) ^ \
+ AES_RT1( ( Y1 >> 8 ) & 0xFF ) ^ \
+ AES_RT2( ( Y0 >> 16 ) & 0xFF ) ^ \
+ AES_RT3( ( Y3 >> 24 ) & 0xFF ); \
+ \
+ X3 = *RK++ ^ AES_RT0( ( Y3 ) & 0xFF ) ^ \
+ AES_RT1( ( Y2 >> 8 ) & 0xFF ) ^ \
+ AES_RT2( ( Y1 >> 16 ) & 0xFF ) ^ \
+ AES_RT3( ( Y0 >> 24 ) & 0xFF ); \
+}
+
+/*
+ * AES-ECB block encryption
+ */
+#if !defined(MBEDCRYPTO_AES_ENCRYPT_ALT)
+int mbedcrypto_internal_aes_encrypt( mbedcrypto_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int i;
+ uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+ RK = ctx->rk;
+
+ GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++;
+ GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++;
+ GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++;
+ GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+
+ for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
+ {
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+ AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+ }
+
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+ X0 = *RK++ ^ \
+ ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+ X1 = *RK++ ^ \
+ ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+ X2 = *RK++ ^ \
+ ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+ X3 = *RK++ ^ \
+ ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^
+ ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+ PUT_UINT32_LE( X0, output, 0 );
+ PUT_UINT32_LE( X1, output, 4 );
+ PUT_UINT32_LE( X2, output, 8 );
+ PUT_UINT32_LE( X3, output, 12 );
+
+ return( 0 );
+}
+#endif /* !MBEDCRYPTO_AES_ENCRYPT_ALT */
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_aes_encrypt( mbedcrypto_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ mbedcrypto_internal_aes_encrypt( ctx, input, output );
+}
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/*
+ * AES-ECB block decryption
+ */
+#if !defined(MBEDCRYPTO_AES_DECRYPT_ALT)
+int mbedcrypto_internal_aes_decrypt( mbedcrypto_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int i;
+ uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+ RK = ctx->rk;
+
+ GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++;
+ GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++;
+ GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++;
+ GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+
+ for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
+ {
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+ AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+ }
+
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+ X0 = *RK++ ^ \
+ ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^
+ ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+ X1 = *RK++ ^ \
+ ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^
+ ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+ X2 = *RK++ ^ \
+ ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^
+ ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+ X3 = *RK++ ^ \
+ ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^
+ ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
+ ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+ ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+ PUT_UINT32_LE( X0, output, 0 );
+ PUT_UINT32_LE( X1, output, 4 );
+ PUT_UINT32_LE( X2, output, 8 );
+ PUT_UINT32_LE( X3, output, 12 );
+
+ return( 0 );
+}
+#endif /* !MBEDCRYPTO_AES_DECRYPT_ALT */
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_aes_decrypt( mbedcrypto_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ mbedcrypto_internal_aes_decrypt( ctx, input, output );
+}
+#endif /* !MBEDCRYPTO_DEPRECATED_REMOVED */
+
+/*
+ * AES-ECB block encryption/decryption
+ */
+int mbedcrypto_aes_crypt_ecb( mbedcrypto_aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+#if defined(MBEDCRYPTO_AESNI_C) && defined(MBEDCRYPTO_HAVE_X86_64)
+ if( mbedcrypto_aesni_has_support( MBEDCRYPTO_AESNI_AES ) )
+ return( mbedcrypto_aesni_crypt_ecb( ctx, mode, input, output ) );
+#endif
+
+#if defined(MBEDCRYPTO_PADLOCK_C) && defined(MBEDCRYPTO_HAVE_X86)
+ if( aes_padlock_ace )
+ {
+ if( mbedcrypto_padlock_xcryptecb( ctx, mode, input, output ) == 0 )
+ return( 0 );
+
+ // If padlock data misaligned, we just fall back to
+ // unaccelerated mode
+ //
+ }
+#endif
+
+ if( mode == MBEDCRYPTO_AES_ENCRYPT )
+ return( mbedcrypto_internal_aes_encrypt( ctx, input, output ) );
+ else
+ return( mbedcrypto_internal_aes_decrypt( ctx, input, output ) );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/*
+ * AES-CBC buffer encryption/decryption
+ */
+int mbedcrypto_aes_crypt_cbc( mbedcrypto_aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[16];
+
+ if( length % 16 )
+ return( MBEDCRYPTO_ERR_AES_INVALID_INPUT_LENGTH );
+
+#if defined(MBEDCRYPTO_PADLOCK_C) && defined(MBEDCRYPTO_HAVE_X86)
+ if( aes_padlock_ace )
+ {
+ if( mbedcrypto_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
+ return( 0 );
+
+ // If padlock data misaligned, we just fall back to
+ // unaccelerated mode
+ //
+ }
+#endif
+
+ if( mode == MBEDCRYPTO_AES_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 16 );
+ mbedcrypto_aes_crypt_ecb( ctx, mode, input, output );
+
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ mbedcrypto_aes_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 buffer encryption/decryption
+ */
+int mbedcrypto_aes_crypt_cfb128( mbedcrypto_aes_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c;
+ size_t n = *iv_off;
+
+ if( mode == MBEDCRYPTO_AES_DECRYPT )
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ mbedcrypto_aes_crypt_ecb( ctx, MBEDCRYPTO_AES_ENCRYPT, iv, iv );
+
+ c = *input++;
+ *output++ = (unsigned char)( c ^ iv[n] );
+ iv[n] = (unsigned char) c;
+
+ n = ( n + 1 ) & 0x0F;
+ }
+ }
+ else
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ mbedcrypto_aes_crypt_ecb( ctx, MBEDCRYPTO_AES_ENCRYPT, iv, iv );
+
+ iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+ n = ( n + 1 ) & 0x0F;
+ }
+ }
+
+ *iv_off = n;
+
+ return( 0 );
+}
+
+/*
+ * AES-CFB8 buffer encryption/decryption
+ */
+int mbedcrypto_aes_crypt_cfb8( mbedcrypto_aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ unsigned char c;
+ unsigned char ov[17];
+
+ while( length-- )
+ {
+ memcpy( ov, iv, 16 );
+ mbedcrypto_aes_crypt_ecb( ctx, MBEDCRYPTO_AES_ENCRYPT, iv, iv );
+
+ if( mode == MBEDCRYPTO_AES_DECRYPT )
+ ov[16] = *input;
+
+ c = *output++ = (unsigned char)( iv[0] ^ *input++ );
+
+ if( mode == MBEDCRYPTO_AES_ENCRYPT )
+ ov[16] = c;
+
+ memcpy( iv, ov + 1, 16 );
+ }
+
+ return( 0 );
+}
+#endif /*MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/*
+ * AES-CTR buffer encryption/decryption
+ */
+int mbedcrypto_aes_crypt_ctr( mbedcrypto_aes_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c, i;
+ size_t n = *nc_off;
+
+ while( length-- )
+ {
+ if( n == 0 ) {
+ mbedcrypto_aes_crypt_ecb( ctx, MBEDCRYPTO_AES_ENCRYPT, nonce_counter, stream_block );
+
+ for( i = 16; i > 0; i-- )
+ if( ++nonce_counter[i - 1] != 0 )
+ break;
+ }
+ c = *input++;
+ *output++ = (unsigned char)( c ^ stream_block[n] );
+
+ n = ( n + 1 ) & 0x0F;
+ }
+
+ *nc_off = n;
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+#endif /* !MBEDCRYPTO_AES_ALT */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/*
+ * AES test vectors from:
+ *
+ * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip
+ */
+static const unsigned char aes_test_ecb_dec[3][16] =
+{
+ { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
+ 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },
+ { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
+ 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },
+ { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
+ 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }
+};
+
+static const unsigned char aes_test_ecb_enc[3][16] =
+{
+ { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
+ 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },
+ { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
+ 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },
+ { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
+ 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }
+};
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static const unsigned char aes_test_cbc_dec[3][16] =
+{
+ { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,
+ 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },
+ { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,
+ 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },
+ { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,
+ 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }
+};
+
+static const unsigned char aes_test_cbc_enc[3][16] =
+{
+ { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,
+ 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },
+ { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,
+ 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },
+ { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,
+ 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 test vectors from:
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ */
+static const unsigned char aes_test_cfb128_key[3][32] =
+{
+ { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+ { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+ 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+ 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+ { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_cfb128_iv[16] =
+{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_cfb128_pt[64] =
+{
+ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+ 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+ 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+ 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+ 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_cfb128_ct[3][64] =
+{
+ { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+ 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+ 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,
+ 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,
+ 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,
+ 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
+ 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
+ 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },
+ { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+ 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+ 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,
+ 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,
+ 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,
+ 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,
+ 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,
+ 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },
+ { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+ 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+ 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,
+ 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,
+ 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,
+ 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,
+ 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,
+ 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/*
+ * AES-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc3686.html
+ */
+
+static const unsigned char aes_test_ctr_key[3][16] =
+{
+ { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+ 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+ { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+ 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+ { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+ 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char aes_test_ctr_nonce_counter[3][16] =
+{
+ { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+ 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+ 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char aes_test_ctr_pt[3][48] =
+{
+ { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+ 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char aes_test_ctr_ct[3][48] =
+{
+ { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
+ 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },
+ { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,
+ 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
+ 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,
+ 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },
+ { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,
+ 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,
+ 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,
+ 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,
+ 0x25, 0xB2, 0x07, 0x2F }
+};
+
+static const int aes_test_ctr_len[3] =
+ { 16, 32, 36 };
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_aes_self_test( int verbose )
+{
+ int ret = 0, i, j, u, mode;
+ unsigned int keybits;
+ unsigned char key[32];
+ unsigned char buf[64];
+ const unsigned char *aes_tests;
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC) || defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ unsigned char iv[16];
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ unsigned char prv[16];
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR) || defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ size_t offset;
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ int len;
+ unsigned char nonce_counter[16];
+ unsigned char stream_block[16];
+#endif
+ mbedcrypto_aes_context ctx;
+
+ memset( key, 0, 32 );
+ mbedcrypto_aes_init( &ctx );
+
+ /*
+ * ECB mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " AES-ECB-%3d (%s): ", keybits,
+ ( mode == MBEDCRYPTO_AES_DECRYPT ) ? "dec" : "enc" );
+
+ memset( buf, 0, 16 );
+
+ if( mode == MBEDCRYPTO_AES_DECRYPT )
+ {
+ ret = mbedcrypto_aes_setkey_dec( &ctx, key, keybits );
+ aes_tests = aes_test_ecb_dec[u];
+ }
+ else
+ {
+ ret = mbedcrypto_aes_setkey_enc( &ctx, key, keybits );
+ aes_tests = aes_test_ecb_enc[u];
+ }
+
+ /*
+ * AES-192 is an optional feature that may be unavailable when
+ * there is an alternative underlying implementation i.e. when
+ * MBEDCRYPTO_AES_ALT is defined.
+ */
+ if( ret == MBEDCRYPTO_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+ {
+ mbedcrypto_printf( "skipped\n" );
+ continue;
+ }
+ else if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ for( j = 0; j < 10000; j++ )
+ {
+ ret = mbedcrypto_aes_crypt_ecb( &ctx, mode, buf, buf );
+ if( ret != 0 )
+ goto exit;
+ }
+
+ if( memcmp( buf, aes_tests, 16 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ /*
+ * CBC mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " AES-CBC-%3d (%s): ", keybits,
+ ( mode == MBEDCRYPTO_AES_DECRYPT ) ? "dec" : "enc" );
+
+ memset( iv , 0, 16 );
+ memset( prv, 0, 16 );
+ memset( buf, 0, 16 );
+
+ if( mode == MBEDCRYPTO_AES_DECRYPT )
+ {
+ ret = mbedcrypto_aes_setkey_dec( &ctx, key, keybits );
+ aes_tests = aes_test_cbc_dec[u];
+ }
+ else
+ {
+ ret = mbedcrypto_aes_setkey_enc( &ctx, key, keybits );
+ aes_tests = aes_test_cbc_enc[u];
+ }
+
+ /*
+ * AES-192 is an optional feature that may be unavailable when
+ * there is an alternative underlying implementation i.e. when
+ * MBEDCRYPTO_AES_ALT is defined.
+ */
+ if( ret == MBEDCRYPTO_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+ {
+ mbedcrypto_printf( "skipped\n" );
+ continue;
+ }
+ else if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ for( j = 0; j < 10000; j++ )
+ {
+ if( mode == MBEDCRYPTO_AES_ENCRYPT )
+ {
+ unsigned char tmp[16];
+
+ memcpy( tmp, prv, 16 );
+ memcpy( prv, buf, 16 );
+ memcpy( buf, tmp, 16 );
+ }
+
+ ret = mbedcrypto_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf );
+ if( ret != 0 )
+ goto exit;
+
+ }
+
+ if( memcmp( buf, aes_tests, 16 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ /*
+ * CFB128 mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " AES-CFB128-%3d (%s): ", keybits,
+ ( mode == MBEDCRYPTO_AES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( iv, aes_test_cfb128_iv, 16 );
+ memcpy( key, aes_test_cfb128_key[u], keybits / 8 );
+
+ offset = 0;
+ ret = mbedcrypto_aes_setkey_enc( &ctx, key, keybits );
+ /*
+ * AES-192 is an optional feature that may be unavailable when
+ * there is an alternative underlying implementation i.e. when
+ * MBEDCRYPTO_AES_ALT is defined.
+ */
+ if( ret == MBEDCRYPTO_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+ {
+ mbedcrypto_printf( "skipped\n" );
+ continue;
+ }
+ else if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ if( mode == MBEDCRYPTO_AES_DECRYPT )
+ {
+ memcpy( buf, aes_test_cfb128_ct[u], 64 );
+ aes_tests = aes_test_cfb128_pt;
+ }
+ else
+ {
+ memcpy( buf, aes_test_cfb128_pt, 64 );
+ aes_tests = aes_test_cfb128_ct[u];
+ }
+
+ ret = mbedcrypto_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf );
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, aes_tests, 64 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ /*
+ * CTR mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ mode = i & 1;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " AES-CTR-128 (%s): ",
+ ( mode == MBEDCRYPTO_AES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
+ memcpy( key, aes_test_ctr_key[u], 16 );
+
+ offset = 0;
+ if( ( ret = mbedcrypto_aes_setkey_enc( &ctx, key, 128 ) ) != 0 )
+ goto exit;
+
+ len = aes_test_ctr_len[u];
+
+ if( mode == MBEDCRYPTO_AES_DECRYPT )
+ {
+ memcpy( buf, aes_test_ctr_ct[u], len );
+ aes_tests = aes_test_ctr_pt[u];
+ }
+ else
+ {
+ memcpy( buf, aes_test_ctr_pt[u], len );
+ aes_tests = aes_test_ctr_ct[u];
+ }
+
+ ret = mbedcrypto_aes_crypt_ctr( &ctx, len, &offset, nonce_counter,
+ stream_block, buf, buf );
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, aes_tests, len ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+ ret = 0;
+
+exit:
+ if( ret != 0 && verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ mbedcrypto_aes_free( &ctx );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_AES_C */
diff --git a/library/aesni.c b/library/aesni.c
new file mode 100644
index 0000000..5a3ea2d
--- /dev/null
+++ b/library/aesni.c
@@ -0,0 +1,470 @@
+/*
+ * AES-NI support functions
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set
+ * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_AESNI_C)
+
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+#warning "MBEDCRYPTO_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code."
+#endif
+#endif
+
+#include "mbedcrypto/aesni.h"
+
+#include <string.h>
+
+#ifndef asm
+#define asm __asm
+#endif
+
+#if defined(MBEDCRYPTO_HAVE_X86_64)
+
+/*
+ * AES-NI support detection routine
+ */
+int mbedcrypto_aesni_has_support( unsigned int what )
+{
+ static int done = 0;
+ static unsigned int c = 0;
+
+ if( ! done )
+ {
+ asm( "movl $1, %%eax \n\t"
+ "cpuid \n\t"
+ : "=c" (c)
+ :
+ : "eax", "ebx", "edx" );
+ done = 1;
+ }
+
+ return( ( c & what ) != 0 );
+}
+
+/*
+ * Binutils needs to be at least 2.19 to support AES-NI instructions.
+ * Unfortunately, a lot of users have a lower version now (2014-04).
+ * Emit bytecode directly in order to support "old" version of gas.
+ *
+ * Opcodes from the Intel architecture reference manual, vol. 3.
+ * We always use registers, so we don't need prefixes for memory operands.
+ * Operand macros are in gas order (src, dst) as opposed to Intel order
+ * (dst, src) in order to blend better into the surrounding assembly code.
+ */
+#define AESDEC ".byte 0x66,0x0F,0x38,0xDE,"
+#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF,"
+#define AESENC ".byte 0x66,0x0F,0x38,0xDC,"
+#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD,"
+#define AESIMC ".byte 0x66,0x0F,0x38,0xDB,"
+#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF,"
+#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44,"
+
+#define xmm0_xmm0 "0xC0"
+#define xmm0_xmm1 "0xC8"
+#define xmm0_xmm2 "0xD0"
+#define xmm0_xmm3 "0xD8"
+#define xmm0_xmm4 "0xE0"
+#define xmm1_xmm0 "0xC1"
+#define xmm1_xmm2 "0xD1"
+
+/*
+ * AES-NI AES-ECB block en(de)cryption
+ */
+int mbedcrypto_aesni_crypt_ecb( mbedcrypto_aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ asm( "movdqu (%3), %%xmm0 \n\t" // load input
+ "movdqu (%1), %%xmm1 \n\t" // load round key 0
+ "pxor %%xmm1, %%xmm0 \n\t" // round 0
+ "add $16, %1 \n\t" // point to next round key
+ "subl $1, %0 \n\t" // normal rounds = nr - 1
+ "test %2, %2 \n\t" // mode?
+ "jz 2f \n\t" // 0 = decrypt
+
+ "1: \n\t" // encryption loop
+ "movdqu (%1), %%xmm1 \n\t" // load round key
+ AESENC xmm1_xmm0 "\n\t" // do round
+ "add $16, %1 \n\t" // point to next round key
+ "subl $1, %0 \n\t" // loop
+ "jnz 1b \n\t"
+ "movdqu (%1), %%xmm1 \n\t" // load round key
+ AESENCLAST xmm1_xmm0 "\n\t" // last round
+ "jmp 3f \n\t"
+
+ "2: \n\t" // decryption loop
+ "movdqu (%1), %%xmm1 \n\t"
+ AESDEC xmm1_xmm0 "\n\t" // do round
+ "add $16, %1 \n\t"
+ "subl $1, %0 \n\t"
+ "jnz 2b \n\t"
+ "movdqu (%1), %%xmm1 \n\t" // load round key
+ AESDECLAST xmm1_xmm0 "\n\t" // last round
+
+ "3: \n\t"
+ "movdqu %%xmm0, (%4) \n\t" // export output
+ :
+ : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output)
+ : "memory", "cc", "xmm0", "xmm1" );
+
+
+ return( 0 );
+}
+
+/*
+ * GCM multiplication: c = a times b in GF(2^128)
+ * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
+ */
+void mbedcrypto_aesni_gcm_mult( unsigned char c[16],
+ const unsigned char a[16],
+ const unsigned char b[16] )
+{
+ unsigned char aa[16], bb[16], cc[16];
+ size_t i;
+
+ /* The inputs are in big-endian order, so byte-reverse them */
+ for( i = 0; i < 16; i++ )
+ {
+ aa[i] = a[15 - i];
+ bb[i] = b[15 - i];
+ }
+
+ asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0
+ "movdqu (%1), %%xmm1 \n\t" // b1:b0
+
+ /*
+ * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1
+ * using [CLMUL-WP] algorithm 1 (p. 13).
+ */
+ "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0
+ "movdqa %%xmm1, %%xmm3 \n\t" // same
+ "movdqa %%xmm1, %%xmm4 \n\t" // same
+ PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0
+ PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0
+ PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0
+ PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0
+ "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0
+ "movdqa %%xmm4, %%xmm3 \n\t" // same
+ "psrldq $8, %%xmm4 \n\t" // 0:e1+f1
+ "pslldq $8, %%xmm3 \n\t" // e0+f0:0
+ "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1
+ "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0
+
+ /*
+ * Now shift the result one bit to the left,
+ * taking advantage of [CLMUL-WP] eq 27 (p. 20)
+ */
+ "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0
+ "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2
+ "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1
+ "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1
+ "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63
+ "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63
+ "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63
+ "pslldq $8, %%xmm3 \n\t" // r0>>63:0
+ "pslldq $8, %%xmm4 \n\t" // r2>>63:0
+ "psrldq $8, %%xmm5 \n\t" // 0:r1>>63
+ "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1
+ "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1
+ "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63
+
+ /*
+ * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
+ * using [CLMUL-WP] algorithm 5 (p. 20).
+ * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
+ */
+ /* Step 2 (1) */
+ "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0
+ "movdqa %%xmm1, %%xmm4 \n\t" // same
+ "movdqa %%xmm1, %%xmm5 \n\t" // same
+ "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a
+ "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b
+ "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c
+
+ /* Step 2 (2) */
+ "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b
+ "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c
+ "pslldq $8, %%xmm3 \n\t" // a+b+c:0
+ "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0
+
+ /* Steps 3 and 4 */
+ "movdqa %%xmm1,%%xmm0 \n\t" // d:x0
+ "movdqa %%xmm1,%%xmm4 \n\t" // same
+ "movdqa %%xmm1,%%xmm5 \n\t" // same
+ "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0'
+ "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0'
+ "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0'
+ "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0'
+ "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0'
+ // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing
+ // bits carried from d. Now get those\t bits back in.
+ "movdqa %%xmm1,%%xmm3 \n\t" // d:x0
+ "movdqa %%xmm1,%%xmm4 \n\t" // same
+ "movdqa %%xmm1,%%xmm5 \n\t" // same
+ "psllq $63, %%xmm3 \n\t" // d<<63:stuff
+ "psllq $62, %%xmm4 \n\t" // d<<62:stuff
+ "psllq $57, %%xmm5 \n\t" // d<<57:stuff
+ "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff
+ "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff
+ "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d
+ "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0
+ "pxor %%xmm1, %%xmm0 \n\t" // h1:h0
+ "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0
+
+ "movdqu %%xmm0, (%2) \n\t" // done
+ :
+ : "r" (aa), "r" (bb), "r" (cc)
+ : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" );
+
+ /* Now byte-reverse the outputs */
+ for( i = 0; i < 16; i++ )
+ c[i] = cc[15 - i];
+
+ return;
+}
+
+/*
+ * Compute decryption round keys from encryption round keys
+ */
+void mbedcrypto_aesni_inverse_key( unsigned char *invkey,
+ const unsigned char *fwdkey, int nr )
+{
+ unsigned char *ik = invkey;
+ const unsigned char *fk = fwdkey + 16 * nr;
+
+ memcpy( ik, fk, 16 );
+
+ for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 )
+ asm( "movdqu (%0), %%xmm0 \n\t"
+ AESIMC xmm0_xmm0 "\n\t"
+ "movdqu %%xmm0, (%1) \n\t"
+ :
+ : "r" (fk), "r" (ik)
+ : "memory", "xmm0" );
+
+ memcpy( ik, fk, 16 );
+}
+
+/*
+ * Key expansion, 128-bit case
+ */
+static void aesni_setkey_enc_128( unsigned char *rk,
+ const unsigned char *key )
+{
+ asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key
+ "movdqu %%xmm0, (%0) \n\t" // as round key 0
+ "jmp 2f \n\t" // skip auxiliary routine
+
+ /*
+ * Finish generating the next round key.
+ *
+ * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff
+ * with X = rot( sub( r3 ) ) ^ RCON.
+ *
+ * On exit, xmm0 is r7:r6:r5:r4
+ * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
+ * and those are written to the round key buffer.
+ */
+ "1: \n\t"
+ "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X
+ "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4
+ "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0
+ "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4
+ "pslldq $4, %%xmm0 \n\t" // etc
+ "pxor %%xmm0, %%xmm1 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time!
+ "add $16, %0 \n\t" // point to next round key
+ "movdqu %%xmm0, (%0) \n\t" // write it
+ "ret \n\t"
+
+ /* Main "loop" */
+ "2: \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t"
+ AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t"
+ :
+ : "r" (rk), "r" (key)
+ : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 192-bit case
+ */
+static void aesni_setkey_enc_192( unsigned char *rk,
+ const unsigned char *key )
+{
+ asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key
+ "movdqu %%xmm0, (%0) \n\t"
+ "add $16, %0 \n\t"
+ "movq 16(%1), %%xmm1 \n\t"
+ "movq %%xmm1, (%0) \n\t"
+ "add $8, %0 \n\t"
+ "jmp 2f \n\t" // skip auxiliary routine
+
+ /*
+ * Finish generating the next 6 quarter-keys.
+ *
+ * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4
+ * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.
+ *
+ * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10
+ * and those are written to the round key buffer.
+ */
+ "1: \n\t"
+ "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X
+ "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4
+ "pslldq $4, %%xmm0 \n\t" // etc
+ "pxor %%xmm0, %%xmm2 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm0, %%xmm2 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6
+ "movdqu %%xmm0, (%0) \n\t"
+ "add $16, %0 \n\t"
+ "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9
+ "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10
+ "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0
+ "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10
+ "movq %%xmm1, (%0) \n\t"
+ "add $8, %0 \n\t"
+ "ret \n\t"
+
+ "2: \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t"
+
+ :
+ : "r" (rk), "r" (key)
+ : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 256-bit case
+ */
+static void aesni_setkey_enc_256( unsigned char *rk,
+ const unsigned char *key )
+{
+ asm( "movdqu (%1), %%xmm0 \n\t"
+ "movdqu %%xmm0, (%0) \n\t"
+ "add $16, %0 \n\t"
+ "movdqu 16(%1), %%xmm1 \n\t"
+ "movdqu %%xmm1, (%0) \n\t"
+ "jmp 2f \n\t" // skip auxiliary routine
+
+ /*
+ * Finish generating the next two round keys.
+ *
+ * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and
+ * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
+ *
+ * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12
+ * and those have been written to the output buffer.
+ */
+ "1: \n\t"
+ "pshufd $0xff, %%xmm2, %%xmm2 \n\t"
+ "pxor %%xmm0, %%xmm2 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm0, %%xmm2 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm0, %%xmm2 \n\t"
+ "pslldq $4, %%xmm0 \n\t"
+ "pxor %%xmm2, %%xmm0 \n\t"
+ "add $16, %0 \n\t"
+ "movdqu %%xmm0, (%0) \n\t"
+
+ /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
+ * and proceed to generate next round key from there */
+ AESKEYGENA xmm0_xmm2 ",0x00 \n\t"
+ "pshufd $0xaa, %%xmm2, %%xmm2 \n\t"
+ "pxor %%xmm1, %%xmm2 \n\t"
+ "pslldq $4, %%xmm1 \n\t"
+ "pxor %%xmm1, %%xmm2 \n\t"
+ "pslldq $4, %%xmm1 \n\t"
+ "pxor %%xmm1, %%xmm2 \n\t"
+ "pslldq $4, %%xmm1 \n\t"
+ "pxor %%xmm2, %%xmm1 \n\t"
+ "add $16, %0 \n\t"
+ "movdqu %%xmm1, (%0) \n\t"
+ "ret \n\t"
+
+ /*
+ * Main "loop" - Generating one more key than necessary,
+ * see definition of mbedcrypto_aes_context.buf
+ */
+ "2: \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t"
+ AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t"
+ :
+ : "r" (rk), "r" (key)
+ : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, wrapper
+ */
+int mbedcrypto_aesni_setkey_enc( unsigned char *rk,
+ const unsigned char *key,
+ size_t bits )
+{
+ switch( bits )
+ {
+ case 128: aesni_setkey_enc_128( rk, key ); break;
+ case 192: aesni_setkey_enc_192( rk, key ); break;
+ case 256: aesni_setkey_enc_256( rk, key ); break;
+ default : return( MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+ return( 0 );
+}
+
+#endif /* MBEDCRYPTO_HAVE_X86_64 */
+
+#endif /* MBEDCRYPTO_AESNI_C */
diff --git a/library/arc4.c b/library/arc4.c
new file mode 100644
index 0000000..9ee6dc1
--- /dev/null
+++ b/library/arc4.c
@@ -0,0 +1,201 @@
+/*
+ * An implementation of the ARCFOUR algorithm
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The ARCFOUR algorithm was publicly disclosed on 94/09.
+ *
+ * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_ARC4_C)
+
+#include "mbedcrypto/arc4.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_ARC4_ALT)
+
+void mbedcrypto_arc4_init( mbedcrypto_arc4_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_arc4_context ) );
+}
+
+void mbedcrypto_arc4_free( mbedcrypto_arc4_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_arc4_context ) );
+}
+
+/*
+ * ARC4 key schedule
+ */
+void mbedcrypto_arc4_setup( mbedcrypto_arc4_context *ctx, const unsigned char *key,
+ unsigned int keylen )
+{
+ int i, j, a;
+ unsigned int k;
+ unsigned char *m;
+
+ ctx->x = 0;
+ ctx->y = 0;
+ m = ctx->m;
+
+ for( i = 0; i < 256; i++ )
+ m[i] = (unsigned char) i;
+
+ j = k = 0;
+
+ for( i = 0; i < 256; i++, k++ )
+ {
+ if( k >= keylen ) k = 0;
+
+ a = m[i];
+ j = ( j + a + key[k] ) & 0xFF;
+ m[i] = m[j];
+ m[j] = (unsigned char) a;
+ }
+}
+
+/*
+ * ARC4 cipher function
+ */
+int mbedcrypto_arc4_crypt( mbedcrypto_arc4_context *ctx, size_t length, const unsigned char *input,
+ unsigned char *output )
+{
+ int x, y, a, b;
+ size_t i;
+ unsigned char *m;
+
+ x = ctx->x;
+ y = ctx->y;
+ m = ctx->m;
+
+ for( i = 0; i < length; i++ )
+ {
+ x = ( x + 1 ) & 0xFF; a = m[x];
+ y = ( y + a ) & 0xFF; b = m[y];
+
+ m[x] = (unsigned char) b;
+ m[y] = (unsigned char) a;
+
+ output[i] = (unsigned char)
+ ( input[i] ^ m[(unsigned char)( a + b )] );
+ }
+
+ ctx->x = x;
+ ctx->y = y;
+
+ return( 0 );
+}
+
+#endif /* !MBEDCRYPTO_ARC4_ALT */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/*
+ * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
+ *
+ * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
+ */
+static const unsigned char arc4_test_key[3][8] =
+{
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_pt[3][8] =
+{
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char arc4_test_ct[3][8] =
+{
+ { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
+ { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
+ { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_arc4_self_test( int verbose )
+{
+ int i, ret = 0;
+ unsigned char ibuf[8];
+ unsigned char obuf[8];
+ mbedcrypto_arc4_context ctx;
+
+ mbedcrypto_arc4_init( &ctx );
+
+ for( i = 0; i < 3; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " ARC4 test #%d: ", i + 1 );
+
+ memcpy( ibuf, arc4_test_pt[i], 8 );
+
+ mbedcrypto_arc4_setup( &ctx, arc4_test_key[i], 8 );
+ mbedcrypto_arc4_crypt( &ctx, 8, ibuf, obuf );
+
+ if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+exit:
+ mbedcrypto_arc4_free( &ctx );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_ARC4_C */
diff --git a/library/asn1parse.c b/library/asn1parse.c
new file mode 100644
index 0000000..1375614
--- /dev/null
+++ b/library/asn1parse.c
@@ -0,0 +1,389 @@
+/*
+ * Generic ASN.1 parsing
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_ASN1_PARSE_C)
+
+#include "mbedcrypto/asn1.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_BIGNUM_C)
+#include "mbedcrypto/bignum.h"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+/*
+ * ASN.1 DER decoding routines
+ */
+int mbedcrypto_asn1_get_len( unsigned char **p,
+ const unsigned char *end,
+ size_t *len )
+{
+ if( ( end - *p ) < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+
+ if( ( **p & 0x80 ) == 0 )
+ *len = *(*p)++;
+ else
+ {
+ switch( **p & 0x7F )
+ {
+ case 1:
+ if( ( end - *p ) < 2 )
+ return( MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+
+ *len = (*p)[1];
+ (*p) += 2;
+ break;
+
+ case 2:
+ if( ( end - *p ) < 3 )
+ return( MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+
+ *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2];
+ (*p) += 3;
+ break;
+
+ case 3:
+ if( ( end - *p ) < 4 )
+ return( MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+
+ *len = ( (size_t)(*p)[1] << 16 ) |
+ ( (size_t)(*p)[2] << 8 ) | (*p)[3];
+ (*p) += 4;
+ break;
+
+ case 4:
+ if( ( end - *p ) < 5 )
+ return( MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+
+ *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) |
+ ( (size_t)(*p)[3] << 8 ) | (*p)[4];
+ (*p) += 5;
+ break;
+
+ default:
+ return( MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH );
+ }
+ }
+
+ if( *len > (size_t) ( end - *p ) )
+ return( MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+
+ return( 0 );
+}
+
+int mbedcrypto_asn1_get_tag( unsigned char **p,
+ const unsigned char *end,
+ size_t *len, int tag )
+{
+ if( ( end - *p ) < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+
+ if( **p != tag )
+ return( MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG );
+
+ (*p)++;
+
+ return( mbedcrypto_asn1_get_len( p, end, len ) );
+}
+
+int mbedcrypto_asn1_get_bool( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &len, MBEDCRYPTO_ASN1_BOOLEAN ) ) != 0 )
+ return( ret );
+
+ if( len != 1 )
+ return( MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH );
+
+ *val = ( **p != 0 ) ? 1 : 0;
+ (*p)++;
+
+ return( 0 );
+}
+
+int mbedcrypto_asn1_get_int( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &len, MBEDCRYPTO_ASN1_INTEGER ) ) != 0 )
+ return( ret );
+
+ if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 )
+ return( MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH );
+
+ *val = 0;
+
+ while( len-- > 0 )
+ {
+ *val = ( *val << 8 ) | **p;
+ (*p)++;
+ }
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_BIGNUM_C)
+int mbedcrypto_asn1_get_mpi( unsigned char **p,
+ const unsigned char *end,
+ mbedcrypto_mpi *X )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &len, MBEDCRYPTO_ASN1_INTEGER ) ) != 0 )
+ return( ret );
+
+ ret = mbedcrypto_mpi_read_binary( X, *p, len );
+
+ *p += len;
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_BIGNUM_C */
+
+int mbedcrypto_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
+ mbedcrypto_asn1_bitstring *bs)
+{
+ int ret;
+
+ /* Certificate type is a single byte bitstring */
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &bs->len, MBEDCRYPTO_ASN1_BIT_STRING ) ) != 0 )
+ return( ret );
+
+ /* Check length, subtract one for actual bit string length */
+ if( bs->len < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+ bs->len -= 1;
+
+ /* Get number of unused bits, ensure unused bits <= 7 */
+ bs->unused_bits = **p;
+ if( bs->unused_bits > 7 )
+ return( MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH );
+ (*p)++;
+
+ /* Get actual bitstring */
+ bs->p = *p;
+ *p += bs->len;
+
+ if( *p != end )
+ return( MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+/*
+ * Get a bit string without unused bits
+ */
+int mbedcrypto_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
+ size_t *len )
+{
+ int ret;
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, len, MBEDCRYPTO_ASN1_BIT_STRING ) ) != 0 )
+ return( ret );
+
+ if( (*len)-- < 2 || *(*p)++ != 0 )
+ return( MBEDCRYPTO_ERR_ASN1_INVALID_DATA );
+
+ return( 0 );
+}
+
+
+
+/*
+ * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
+ */
+int mbedcrypto_asn1_get_sequence_of( unsigned char **p,
+ const unsigned char *end,
+ mbedcrypto_asn1_sequence *cur,
+ int tag)
+{
+ int ret;
+ size_t len;
+ mbedcrypto_asn1_buf *buf;
+
+ /* Get main sequence tag */
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ return( ret );
+
+ if( *p + len != end )
+ return( MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ while( *p < end )
+ {
+ buf = &(cur->buf);
+ buf->tag = **p;
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
+ return( ret );
+
+ buf->p = *p;
+ *p += buf->len;
+
+ /* Allocate and assign next pointer */
+ if( *p < end )
+ {
+ cur->next = (mbedcrypto_asn1_sequence*)mbedcrypto_calloc( 1,
+ sizeof( mbedcrypto_asn1_sequence ) );
+
+ if( cur->next == NULL )
+ return( MBEDCRYPTO_ERR_ASN1_ALLOC_FAILED );
+
+ cur = cur->next;
+ }
+ }
+
+ /* Set final sequence entry's next pointer to NULL */
+ cur->next = NULL;
+
+ if( *p != end )
+ return( MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+int mbedcrypto_asn1_get_alg( unsigned char **p,
+ const unsigned char *end,
+ mbedcrypto_asn1_buf *alg, mbedcrypto_asn1_buf *params )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ return( ret );
+
+ if( ( end - *p ) < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+
+ alg->tag = **p;
+ end = *p + len;
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &alg->len, MBEDCRYPTO_ASN1_OID ) ) != 0 )
+ return( ret );
+
+ alg->p = *p;
+ *p += alg->len;
+
+ if( *p == end )
+ {
+ mbedcrypto_platform_zeroize( params, sizeof(mbedcrypto_asn1_buf) );
+ return( 0 );
+ }
+
+ params->tag = **p;
+ (*p)++;
+
+ if( ( ret = mbedcrypto_asn1_get_len( p, end, ¶ms->len ) ) != 0 )
+ return( ret );
+
+ params->p = *p;
+ *p += params->len;
+
+ if( *p != end )
+ return( MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+int mbedcrypto_asn1_get_alg_null( unsigned char **p,
+ const unsigned char *end,
+ mbedcrypto_asn1_buf *alg )
+{
+ int ret;
+ mbedcrypto_asn1_buf params;
+
+ memset( ¶ms, 0, sizeof(mbedcrypto_asn1_buf) );
+
+ if( ( ret = mbedcrypto_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 )
+ return( ret );
+
+ if( ( params.tag != MBEDCRYPTO_ASN1_NULL && params.tag != 0 ) || params.len != 0 )
+ return( MBEDCRYPTO_ERR_ASN1_INVALID_DATA );
+
+ return( 0 );
+}
+
+void mbedcrypto_asn1_free_named_data( mbedcrypto_asn1_named_data *cur )
+{
+ if( cur == NULL )
+ return;
+
+ mbedcrypto_free( cur->oid.p );
+ mbedcrypto_free( cur->val.p );
+
+ mbedcrypto_platform_zeroize( cur, sizeof( mbedcrypto_asn1_named_data ) );
+}
+
+void mbedcrypto_asn1_free_named_data_list( mbedcrypto_asn1_named_data **head )
+{
+ mbedcrypto_asn1_named_data *cur;
+
+ while( ( cur = *head ) != NULL )
+ {
+ *head = cur->next;
+ mbedcrypto_asn1_free_named_data( cur );
+ mbedcrypto_free( cur );
+ }
+}
+
+mbedcrypto_asn1_named_data *mbedcrypto_asn1_find_named_data( mbedcrypto_asn1_named_data *list,
+ const char *oid, size_t len )
+{
+ while( list != NULL )
+ {
+ if( list->oid.len == len &&
+ memcmp( list->oid.p, oid, len ) == 0 )
+ {
+ break;
+ }
+
+ list = list->next;
+ }
+
+ return( list );
+}
+
+#endif /* MBEDCRYPTO_ASN1_PARSE_C */
diff --git a/library/asn1write.c b/library/asn1write.c
new file mode 100644
index 0000000..87c5ef6
--- /dev/null
+++ b/library/asn1write.c
@@ -0,0 +1,386 @@
+/*
+ * ASN.1 buffer writing functionality
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_ASN1_WRITE_C)
+
+#include "mbedcrypto/asn1write.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+int mbedcrypto_asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
+{
+ if( len < 0x80 )
+ {
+ if( *p - start < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = (unsigned char) len;
+ return( 1 );
+ }
+
+ if( len <= 0xFF )
+ {
+ if( *p - start < 2 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = (unsigned char) len;
+ *--(*p) = 0x81;
+ return( 2 );
+ }
+
+ if( len <= 0xFFFF )
+ {
+ if( *p - start < 3 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = ( len ) & 0xFF;
+ *--(*p) = ( len >> 8 ) & 0xFF;
+ *--(*p) = 0x82;
+ return( 3 );
+ }
+
+ if( len <= 0xFFFFFF )
+ {
+ if( *p - start < 4 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = ( len ) & 0xFF;
+ *--(*p) = ( len >> 8 ) & 0xFF;
+ *--(*p) = ( len >> 16 ) & 0xFF;
+ *--(*p) = 0x83;
+ return( 4 );
+ }
+
+ if( len <= 0xFFFFFFFF )
+ {
+ if( *p - start < 5 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = ( len ) & 0xFF;
+ *--(*p) = ( len >> 8 ) & 0xFF;
+ *--(*p) = ( len >> 16 ) & 0xFF;
+ *--(*p) = ( len >> 24 ) & 0xFF;
+ *--(*p) = 0x84;
+ return( 5 );
+ }
+
+ return( MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH );
+}
+
+int mbedcrypto_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
+{
+ if( *p - start < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = tag;
+
+ return( 1 );
+}
+
+int mbedcrypto_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
+ const unsigned char *buf, size_t size )
+{
+ size_t len = 0;
+
+ if( *p < start || (size_t)( *p - start ) < size )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ len = size;
+ (*p) -= len;
+ memcpy( *p, buf, len );
+
+ return( (int) len );
+}
+
+#if defined(MBEDCRYPTO_BIGNUM_C)
+int mbedcrypto_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedcrypto_mpi *X )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write the MPI
+ //
+ len = mbedcrypto_mpi_size( X );
+
+ if( *p < start || (size_t)( *p - start ) < len )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ (*p) -= len;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( X, *p, len ) );
+
+ // DER format assumes 2s complement for numbers, so the leftmost bit
+ // should be 0 for positive numbers and 1 for negative numbers.
+ //
+ if( X->s ==1 && **p & 0x80 )
+ {
+ if( *p - start < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = 0x00;
+ len += 1;
+ }
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_INTEGER ) );
+
+ ret = (int) len;
+
+cleanup:
+ return( ret );
+}
+#endif /* MBEDCRYPTO_BIGNUM_C */
+
+int mbedcrypto_asn1_write_null( unsigned char **p, unsigned char *start )
+{
+ int ret;
+ size_t len = 0;
+
+ // Write NULL
+ //
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, 0) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_NULL ) );
+
+ return( (int) len );
+}
+
+int mbedcrypto_asn1_write_oid( unsigned char **p, unsigned char *start,
+ const char *oid, size_t oid_len )
+{
+ int ret;
+ size_t len = 0;
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_raw_buffer( p, start,
+ (const unsigned char *) oid, oid_len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len , mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len , mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_OID ) );
+
+ return( (int) len );
+}
+
+int mbedcrypto_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
+ const char *oid, size_t oid_len,
+ size_t par_len )
+{
+ int ret;
+ size_t len = 0;
+
+ if( par_len == 0 )
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_null( p, start ) );
+ else
+ len += par_len;
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_oid( p, start, oid, oid_len ) );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) );
+
+ return( (int) len );
+}
+
+int mbedcrypto_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
+{
+ int ret;
+ size_t len = 0;
+
+ if( *p - start < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = (boolean) ? 255 : 0;
+ len++;
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_BOOLEAN ) );
+
+ return( (int) len );
+}
+
+int mbedcrypto_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+{
+ int ret;
+ size_t len = 0;
+
+ if( *p - start < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ len += 1;
+ *--(*p) = val;
+
+ if( val > 0 && **p & 0x80 )
+ {
+ if( *p - start < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = 0x00;
+ len += 1;
+ }
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_INTEGER ) );
+
+ return( (int) len );
+}
+
+int mbedcrypto_asn1_write_printable_string( unsigned char **p, unsigned char *start,
+ const char *text, size_t text_len )
+{
+ int ret;
+ size_t len = 0;
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_raw_buffer( p, start,
+ (const unsigned char *) text, text_len ) );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_PRINTABLE_STRING ) );
+
+ return( (int) len );
+}
+
+int mbedcrypto_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
+ const char *text, size_t text_len )
+{
+ int ret;
+ size_t len = 0;
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_raw_buffer( p, start,
+ (const unsigned char *) text, text_len ) );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_IA5_STRING ) );
+
+ return( (int) len );
+}
+
+int mbedcrypto_asn1_write_bitstring( unsigned char **p, unsigned char *start,
+ const unsigned char *buf, size_t bits )
+{
+ int ret;
+ size_t len = 0, size;
+
+ size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 );
+
+ // Calculate byte length
+ //
+ if( *p < start || (size_t)( *p - start ) < size + 1 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ len = size + 1;
+ (*p) -= size;
+ memcpy( *p, buf, size );
+
+ // Write unused bits
+ //
+ *--(*p) = (unsigned char) (size * 8 - bits);
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_BIT_STRING ) );
+
+ return( (int) len );
+}
+
+int mbedcrypto_asn1_write_octet_string( unsigned char **p, unsigned char *start,
+ const unsigned char *buf, size_t size )
+{
+ int ret;
+ size_t len = 0;
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_raw_buffer( p, start, buf, size ) );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_OCTET_STRING ) );
+
+ return( (int) len );
+}
+
+mbedcrypto_asn1_named_data *mbedcrypto_asn1_store_named_data( mbedcrypto_asn1_named_data **head,
+ const char *oid, size_t oid_len,
+ const unsigned char *val,
+ size_t val_len )
+{
+ mbedcrypto_asn1_named_data *cur;
+
+ if( ( cur = mbedcrypto_asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
+ {
+ // Add new entry if not present yet based on OID
+ //
+ cur = (mbedcrypto_asn1_named_data*)mbedcrypto_calloc( 1,
+ sizeof(mbedcrypto_asn1_named_data) );
+ if( cur == NULL )
+ return( NULL );
+
+ cur->oid.len = oid_len;
+ cur->oid.p = mbedcrypto_calloc( 1, oid_len );
+ if( cur->oid.p == NULL )
+ {
+ mbedcrypto_free( cur );
+ return( NULL );
+ }
+
+ memcpy( cur->oid.p, oid, oid_len );
+
+ cur->val.len = val_len;
+ cur->val.p = mbedcrypto_calloc( 1, val_len );
+ if( cur->val.p == NULL )
+ {
+ mbedcrypto_free( cur->oid.p );
+ mbedcrypto_free( cur );
+ return( NULL );
+ }
+
+ cur->next = *head;
+ *head = cur;
+ }
+ else if( cur->val.len < val_len )
+ {
+ /*
+ * Enlarge existing value buffer if needed
+ * Preserve old data until the allocation succeeded, to leave list in
+ * a consistent state in case allocation fails.
+ */
+ void *p = mbedcrypto_calloc( 1, val_len );
+ if( p == NULL )
+ return( NULL );
+
+ mbedcrypto_free( cur->val.p );
+ cur->val.p = p;
+ cur->val.len = val_len;
+ }
+
+ if( val != NULL )
+ memcpy( cur->val.p, val, val_len );
+
+ return( cur );
+}
+#endif /* MBEDCRYPTO_ASN1_WRITE_C */
diff --git a/library/base64.c b/library/base64.c
new file mode 100644
index 0000000..637f30b
--- /dev/null
+++ b/library/base64.c
@@ -0,0 +1,293 @@
+/*
+ * RFC 1521 base64 encoding/decoding
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_BASE64_C)
+
+#include "mbedcrypto/base64.h"
+
+#include <stdint.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#include <string.h>
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+static const unsigned char base64_enc_map[64] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', '+', '/'
+};
+
+static const unsigned char base64_dec_map[128] =
+{
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
+ 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 127, 127, 127, 127, 127
+};
+
+#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
+
+/*
+ * Encode a buffer into base64 format
+ */
+int mbedcrypto_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
+ const unsigned char *src, size_t slen )
+{
+ size_t i, n;
+ int C1, C2, C3;
+ unsigned char *p;
+
+ if( slen == 0 )
+ {
+ *olen = 0;
+ return( 0 );
+ }
+
+ n = slen / 3 + ( slen % 3 != 0 );
+
+ if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
+ {
+ *olen = BASE64_SIZE_T_MAX;
+ return( MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ n *= 4;
+
+ if( ( dlen < n + 1 ) || ( NULL == dst ) )
+ {
+ *olen = n + 1;
+ return( MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ n = ( slen / 3 ) * 3;
+
+ for( i = 0, p = dst; i < n; i += 3 )
+ {
+ C1 = *src++;
+ C2 = *src++;
+ C3 = *src++;
+
+ *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+ *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+ *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
+ *p++ = base64_enc_map[C3 & 0x3F];
+ }
+
+ if( i < slen )
+ {
+ C1 = *src++;
+ C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
+
+ *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
+ *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+
+ if( ( i + 1 ) < slen )
+ *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+ else *p++ = '=';
+
+ *p++ = '=';
+ }
+
+ *olen = p - dst;
+ *p = 0;
+
+ return( 0 );
+}
+
+/*
+ * Decode a base64-formatted buffer
+ */
+int mbedcrypto_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
+ const unsigned char *src, size_t slen )
+{
+ size_t i, n;
+ uint32_t j, x;
+ unsigned char *p;
+
+ /* First pass: check for validity and get output length */
+ for( i = n = j = 0; i < slen; i++ )
+ {
+ /* Skip spaces before checking for EOL */
+ x = 0;
+ while( i < slen && src[i] == ' ' )
+ {
+ ++i;
+ ++x;
+ }
+
+ /* Spaces at end of buffer are OK */
+ if( i == slen )
+ break;
+
+ if( ( slen - i ) >= 2 &&
+ src[i] == '\r' && src[i + 1] == '\n' )
+ continue;
+
+ if( src[i] == '\n' )
+ continue;
+
+ /* Space inside a line is an error */
+ if( x != 0 )
+ return( MBEDCRYPTO_ERR_BASE64_INVALID_CHARACTER );
+
+ if( src[i] == '=' && ++j > 2 )
+ return( MBEDCRYPTO_ERR_BASE64_INVALID_CHARACTER );
+
+ if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
+ return( MBEDCRYPTO_ERR_BASE64_INVALID_CHARACTER );
+
+ if( base64_dec_map[src[i]] < 64 && j != 0 )
+ return( MBEDCRYPTO_ERR_BASE64_INVALID_CHARACTER );
+
+ n++;
+ }
+
+ if( n == 0 )
+ {
+ *olen = 0;
+ return( 0 );
+ }
+
+ /* The following expression is to calculate the following formula without
+ * risk of integer overflow in n:
+ * n = ( ( n * 6 ) + 7 ) >> 3;
+ */
+ n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
+ n -= j;
+
+ if( dst == NULL || dlen < n )
+ {
+ *olen = n;
+ return( MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
+ {
+ if( *src == '\r' || *src == '\n' || *src == ' ' )
+ continue;
+
+ j -= ( base64_dec_map[*src] == 64 );
+ x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
+
+ if( ++n == 4 )
+ {
+ n = 0;
+ if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
+ if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
+ if( j > 2 ) *p++ = (unsigned char)( x );
+ }
+ }
+
+ *olen = p - dst;
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+static const unsigned char base64_test_dec[64] =
+{
+ 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
+ 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
+ 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
+ 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
+ 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
+ 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
+ 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
+ 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
+};
+
+static const unsigned char base64_test_enc[] =
+ "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
+ "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_base64_self_test( int verbose )
+{
+ size_t len;
+ const unsigned char *src;
+ unsigned char buffer[128];
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " Base64 encoding test: " );
+
+ src = base64_test_dec;
+
+ if( mbedcrypto_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 ||
+ memcmp( base64_test_enc, buffer, 88 ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n Base64 decoding test: " );
+
+ src = base64_test_enc;
+
+ if( mbedcrypto_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 ||
+ memcmp( base64_test_dec, buffer, 64 ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n\n" );
+
+ return( 0 );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_BASE64_C */
diff --git a/library/bignum.c b/library/bignum.c
new file mode 100644
index 0000000..2b57f9e
--- /dev/null
+++ b/library/bignum.c
@@ -0,0 +1,2468 @@
+/*
+ * Multi-precision integer library
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * The following sources were referenced in the design of this Multi-precision
+ * Integer library:
+ *
+ * [1] Handbook of Applied Cryptography - 1997
+ * Menezes, van Oorschot and Vanstone
+ *
+ * [2] Multi-Precision Math
+ * Tom St Denis
+ * https://github.com/libtom/libtommath/blob/develop/tommath.pdf
+ *
+ * [3] GNU Multi-Precision Arithmetic Library
+ * https://gmplib.org/manual/index.html
+ *
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_BIGNUM_C)
+
+#include "mbedcrypto/bignum.h"
+#include "mbedcrypto/bn_mul.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedcrypto_printf printf
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#define ciL (sizeof(mbedcrypto_mpi_uint)) /* chars in limb */
+#define biL (ciL << 3) /* bits in limb */
+#define biH (ciL << 2) /* half limb size */
+
+#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
+
+/*
+ * Convert between bits/chars and number of limbs
+ * Divide first in order to avoid potential overflows
+ */
+#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
+#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedcrypto_mpi_zeroize( mbedcrypto_mpi_uint *v, size_t n )
+{
+ mbedcrypto_platform_zeroize( v, ciL * n );
+}
+
+/*
+ * Initialize one MPI
+ */
+void mbedcrypto_mpi_init( mbedcrypto_mpi *X )
+{
+ if( X == NULL )
+ return;
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+}
+
+/*
+ * Unallocate one MPI
+ */
+void mbedcrypto_mpi_free( mbedcrypto_mpi *X )
+{
+ if( X == NULL )
+ return;
+
+ if( X->p != NULL )
+ {
+ mbedcrypto_mpi_zeroize( X->p, X->n );
+ mbedcrypto_free( X->p );
+ }
+
+ X->s = 1;
+ X->n = 0;
+ X->p = NULL;
+}
+
+/*
+ * Enlarge to the specified number of limbs
+ */
+int mbedcrypto_mpi_grow( mbedcrypto_mpi *X, size_t nblimbs )
+{
+ mbedcrypto_mpi_uint *p;
+
+ if( nblimbs > MBEDCRYPTO_MPI_MAX_LIMBS )
+ return( MBEDCRYPTO_ERR_MPI_ALLOC_FAILED );
+
+ if( X->n < nblimbs )
+ {
+ if( ( p = (mbedcrypto_mpi_uint*)mbedcrypto_calloc( nblimbs, ciL ) ) == NULL )
+ return( MBEDCRYPTO_ERR_MPI_ALLOC_FAILED );
+
+ if( X->p != NULL )
+ {
+ memcpy( p, X->p, X->n * ciL );
+ mbedcrypto_mpi_zeroize( X->p, X->n );
+ mbedcrypto_free( X->p );
+ }
+
+ X->n = nblimbs;
+ X->p = p;
+ }
+
+ return( 0 );
+}
+
+/*
+ * Resize down as much as possible,
+ * while keeping at least the specified number of limbs
+ */
+int mbedcrypto_mpi_shrink( mbedcrypto_mpi *X, size_t nblimbs )
+{
+ mbedcrypto_mpi_uint *p;
+ size_t i;
+
+ /* Actually resize up in this case */
+ if( X->n <= nblimbs )
+ return( mbedcrypto_mpi_grow( X, nblimbs ) );
+
+ for( i = X->n - 1; i > 0; i-- )
+ if( X->p[i] != 0 )
+ break;
+ i++;
+
+ if( i < nblimbs )
+ i = nblimbs;
+
+ if( ( p = (mbedcrypto_mpi_uint*)mbedcrypto_calloc( i, ciL ) ) == NULL )
+ return( MBEDCRYPTO_ERR_MPI_ALLOC_FAILED );
+
+ if( X->p != NULL )
+ {
+ memcpy( p, X->p, i * ciL );
+ mbedcrypto_mpi_zeroize( X->p, X->n );
+ mbedcrypto_free( X->p );
+ }
+
+ X->n = i;
+ X->p = p;
+
+ return( 0 );
+}
+
+/*
+ * Copy the contents of Y into X
+ */
+int mbedcrypto_mpi_copy( mbedcrypto_mpi *X, const mbedcrypto_mpi *Y )
+{
+ int ret = 0;
+ size_t i;
+
+ if( X == Y )
+ return( 0 );
+
+ if( Y->p == NULL )
+ {
+ mbedcrypto_mpi_free( X );
+ return( 0 );
+ }
+
+ for( i = Y->n - 1; i > 0; i-- )
+ if( Y->p[i] != 0 )
+ break;
+ i++;
+
+ X->s = Y->s;
+
+ if( X->n < i )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, i ) );
+ }
+ else
+ {
+ memset( X->p + i, 0, ( X->n - i ) * ciL );
+ }
+
+ memcpy( X->p, Y->p, i * ciL );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Swap the contents of X and Y
+ */
+void mbedcrypto_mpi_swap( mbedcrypto_mpi *X, mbedcrypto_mpi *Y )
+{
+ mbedcrypto_mpi T;
+
+ memcpy( &T, X, sizeof( mbedcrypto_mpi ) );
+ memcpy( X, Y, sizeof( mbedcrypto_mpi ) );
+ memcpy( Y, &T, sizeof( mbedcrypto_mpi ) );
+}
+
+/*
+ * Conditionally assign X = Y, without leaking information
+ * about whether the assignment was made or not.
+ * (Leaking information about the respective sizes of X and Y is ok however.)
+ */
+int mbedcrypto_mpi_safe_cond_assign( mbedcrypto_mpi *X, const mbedcrypto_mpi *Y, unsigned char assign )
+{
+ int ret = 0;
+ size_t i;
+
+ /* make sure assign is 0 or 1 in a time-constant manner */
+ assign = (assign | (unsigned char)-assign) >> 7;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, Y->n ) );
+
+ X->s = X->s * ( 1 - assign ) + Y->s * assign;
+
+ for( i = 0; i < Y->n; i++ )
+ X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign;
+
+ for( ; i < X->n; i++ )
+ X->p[i] *= ( 1 - assign );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Conditionally swap X and Y, without leaking information
+ * about whether the swap was made or not.
+ * Here it is not ok to simply swap the pointers, which whould lead to
+ * different memory access patterns when X and Y are used afterwards.
+ */
+int mbedcrypto_mpi_safe_cond_swap( mbedcrypto_mpi *X, mbedcrypto_mpi *Y, unsigned char swap )
+{
+ int ret, s;
+ size_t i;
+ mbedcrypto_mpi_uint tmp;
+
+ if( X == Y )
+ return( 0 );
+
+ /* make sure swap is 0 or 1 in a time-constant manner */
+ swap = (swap | (unsigned char)-swap) >> 7;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, Y->n ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( Y, X->n ) );
+
+ s = X->s;
+ X->s = X->s * ( 1 - swap ) + Y->s * swap;
+ Y->s = Y->s * ( 1 - swap ) + s * swap;
+
+
+ for( i = 0; i < X->n; i++ )
+ {
+ tmp = X->p[i];
+ X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
+ Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap;
+ }
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Set value from integer
+ */
+int mbedcrypto_mpi_lset( mbedcrypto_mpi *X, mbedcrypto_mpi_sint z )
+{
+ int ret;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, 1 ) );
+ memset( X->p, 0, X->n * ciL );
+
+ X->p[0] = ( z < 0 ) ? -z : z;
+ X->s = ( z < 0 ) ? -1 : 1;
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Get a specific bit
+ */
+int mbedcrypto_mpi_get_bit( const mbedcrypto_mpi *X, size_t pos )
+{
+ if( X->n * biL <= pos )
+ return( 0 );
+
+ return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
+}
+
+/*
+ * Set a bit to a specific value of 0 or 1
+ */
+int mbedcrypto_mpi_set_bit( mbedcrypto_mpi *X, size_t pos, unsigned char val )
+{
+ int ret = 0;
+ size_t off = pos / biL;
+ size_t idx = pos % biL;
+
+ if( val != 0 && val != 1 )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ if( X->n * biL <= pos )
+ {
+ if( val == 0 )
+ return( 0 );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, off + 1 ) );
+ }
+
+ X->p[off] &= ~( (mbedcrypto_mpi_uint) 0x01 << idx );
+ X->p[off] |= (mbedcrypto_mpi_uint) val << idx;
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Return the number of less significant zero-bits
+ */
+size_t mbedcrypto_mpi_lsb( const mbedcrypto_mpi *X )
+{
+ size_t i, j, count = 0;
+
+ for( i = 0; i < X->n; i++ )
+ for( j = 0; j < biL; j++, count++ )
+ if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+ return( count );
+
+ return( 0 );
+}
+
+/*
+ * Count leading zero bits in a given integer
+ */
+static size_t mbedcrypto_clz( const mbedcrypto_mpi_uint x )
+{
+ size_t j;
+ mbedcrypto_mpi_uint mask = (mbedcrypto_mpi_uint) 1 << (biL - 1);
+
+ for( j = 0; j < biL; j++ )
+ {
+ if( x & mask ) break;
+
+ mask >>= 1;
+ }
+
+ return j;
+}
+
+/*
+ * Return the number of bits
+ */
+size_t mbedcrypto_mpi_bitlen( const mbedcrypto_mpi *X )
+{
+ size_t i, j;
+
+ if( X->n == 0 )
+ return( 0 );
+
+ for( i = X->n - 1; i > 0; i-- )
+ if( X->p[i] != 0 )
+ break;
+
+ j = biL - mbedcrypto_clz( X->p[i] );
+
+ return( ( i * biL ) + j );
+}
+
+/*
+ * Return the total size in bytes
+ */
+size_t mbedcrypto_mpi_size( const mbedcrypto_mpi *X )
+{
+ return( ( mbedcrypto_mpi_bitlen( X ) + 7 ) >> 3 );
+}
+
+/*
+ * Convert an ASCII character to digit value
+ */
+static int mpi_get_digit( mbedcrypto_mpi_uint *d, int radix, char c )
+{
+ *d = 255;
+
+ if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
+ if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
+ if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
+
+ if( *d >= (mbedcrypto_mpi_uint) radix )
+ return( MBEDCRYPTO_ERR_MPI_INVALID_CHARACTER );
+
+ return( 0 );
+}
+
+/*
+ * Import from an ASCII string
+ */
+int mbedcrypto_mpi_read_string( mbedcrypto_mpi *X, int radix, const char *s )
+{
+ int ret;
+ size_t i, j, slen, n;
+ mbedcrypto_mpi_uint d;
+ mbedcrypto_mpi T;
+
+ if( radix < 2 || radix > 16 )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ mbedcrypto_mpi_init( &T );
+
+ slen = strlen( s );
+
+ if( radix == 16 )
+ {
+ if( slen > MPI_SIZE_T_MAX >> 2 )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ n = BITS_TO_LIMBS( slen << 2 );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, n ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( X, 0 ) );
+
+ for( i = slen, j = 0; i > 0; i--, j++ )
+ {
+ if( i == 1 && s[i - 1] == '-' )
+ {
+ X->s = -1;
+ break;
+ }
+
+ MBEDCRYPTO_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
+ X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
+ }
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( X, 0 ) );
+
+ for( i = 0; i < slen; i++ )
+ {
+ if( i == 0 && s[i] == '-' )
+ {
+ X->s = -1;
+ continue;
+ }
+
+ MBEDCRYPTO_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_int( &T, X, radix ) );
+
+ if( X->s == 1 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_int( X, &T, d ) );
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( X, &T, d ) );
+ }
+ }
+ }
+
+cleanup:
+
+ mbedcrypto_mpi_free( &T );
+
+ return( ret );
+}
+
+/*
+ * Helper to write the digits high-order first
+ */
+static int mpi_write_hlp( mbedcrypto_mpi *X, int radix, char **p )
+{
+ int ret;
+ mbedcrypto_mpi_uint r;
+
+ if( radix < 2 || radix > 16 )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_int( &r, X, radix ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_div_int( X, NULL, X, radix ) );
+
+ if( mbedcrypto_mpi_cmp_int( X, 0 ) != 0 )
+ MBEDCRYPTO_MPI_CHK( mpi_write_hlp( X, radix, p ) );
+
+ if( r < 10 )
+ *(*p)++ = (char)( r + 0x30 );
+ else
+ *(*p)++ = (char)( r + 0x37 );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export into an ASCII string
+ */
+int mbedcrypto_mpi_write_string( const mbedcrypto_mpi *X, int radix,
+ char *buf, size_t buflen, size_t *olen )
+{
+ int ret = 0;
+ size_t n;
+ char *p;
+ mbedcrypto_mpi T;
+
+ if( radix < 2 || radix > 16 )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ n = mbedcrypto_mpi_bitlen( X );
+ if( radix >= 4 ) n >>= 1;
+ if( radix >= 16 ) n >>= 1;
+ /*
+ * Round up the buffer length to an even value to ensure that there is
+ * enough room for hexadecimal values that can be represented in an odd
+ * number of digits.
+ */
+ n += 3 + ( ( n + 1 ) & 1 );
+
+ if( buflen < n )
+ {
+ *olen = n;
+ return( MBEDCRYPTO_ERR_MPI_BUFFER_TOO_SMALL );
+ }
+
+ p = buf;
+ mbedcrypto_mpi_init( &T );
+
+ if( X->s == -1 )
+ *p++ = '-';
+
+ if( radix == 16 )
+ {
+ int c;
+ size_t i, j, k;
+
+ for( i = X->n, k = 0; i > 0; i-- )
+ {
+ for( j = ciL; j > 0; j-- )
+ {
+ c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
+
+ if( c == 0 && k == 0 && ( i + j ) != 2 )
+ continue;
+
+ *(p++) = "0123456789ABCDEF" [c / 16];
+ *(p++) = "0123456789ABCDEF" [c % 16];
+ k = 1;
+ }
+ }
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &T, X ) );
+
+ if( T.s == -1 )
+ T.s = 1;
+
+ MBEDCRYPTO_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
+ }
+
+ *p++ = '\0';
+ *olen = p - buf;
+
+cleanup:
+
+ mbedcrypto_mpi_free( &T );
+
+ return( ret );
+}
+
+#if defined(MBEDCRYPTO_FS_IO)
+/*
+ * Read X from an opened file
+ */
+int mbedcrypto_mpi_read_file( mbedcrypto_mpi *X, int radix, FILE *fin )
+{
+ mbedcrypto_mpi_uint d;
+ size_t slen;
+ char *p;
+ /*
+ * Buffer should have space for (short) label and decimal formatted MPI,
+ * newline characters and '\0'
+ */
+ char s[ MBEDCRYPTO_MPI_RW_BUFFER_SIZE ];
+
+ memset( s, 0, sizeof( s ) );
+ if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
+ return( MBEDCRYPTO_ERR_MPI_FILE_IO_ERROR );
+
+ slen = strlen( s );
+ if( slen == sizeof( s ) - 2 )
+ return( MBEDCRYPTO_ERR_MPI_BUFFER_TOO_SMALL );
+
+ if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
+ if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
+
+ p = s + slen;
+ while( p-- > s )
+ if( mpi_get_digit( &d, radix, *p ) != 0 )
+ break;
+
+ return( mbedcrypto_mpi_read_string( X, radix, p + 1 ) );
+}
+
+/*
+ * Write X into an opened file (or stdout if fout == NULL)
+ */
+int mbedcrypto_mpi_write_file( const char *p, const mbedcrypto_mpi *X, int radix, FILE *fout )
+{
+ int ret;
+ size_t n, slen, plen;
+ /*
+ * Buffer should have space for (short) label and decimal formatted MPI,
+ * newline characters and '\0'
+ */
+ char s[ MBEDCRYPTO_MPI_RW_BUFFER_SIZE ];
+
+ memset( s, 0, sizeof( s ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
+
+ if( p == NULL ) p = "";
+
+ plen = strlen( p );
+ slen = strlen( s );
+ s[slen++] = '\r';
+ s[slen++] = '\n';
+
+ if( fout != NULL )
+ {
+ if( fwrite( p, 1, plen, fout ) != plen ||
+ fwrite( s, 1, slen, fout ) != slen )
+ return( MBEDCRYPTO_ERR_MPI_FILE_IO_ERROR );
+ }
+ else
+ mbedcrypto_printf( "%s%s", p, s );
+
+cleanup:
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_FS_IO */
+
+/*
+ * Import X from unsigned binary data, big endian
+ */
+int mbedcrypto_mpi_read_binary( mbedcrypto_mpi *X, const unsigned char *buf, size_t buflen )
+{
+ int ret;
+ size_t i, j;
+ size_t const limbs = CHARS_TO_LIMBS( buflen );
+
+ /* Ensure that target MPI has exactly the necessary number of limbs */
+ if( X->n != limbs )
+ {
+ mbedcrypto_mpi_free( X );
+ mbedcrypto_mpi_init( X );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, limbs ) );
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( X, 0 ) );
+
+ for( i = buflen, j = 0; i > 0; i--, j++ )
+ X->p[j / ciL] |= ((mbedcrypto_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Export X into unsigned binary data, big endian
+ */
+int mbedcrypto_mpi_write_binary( const mbedcrypto_mpi *X, unsigned char *buf, size_t buflen )
+{
+ size_t i, j, n;
+
+ n = mbedcrypto_mpi_size( X );
+
+ if( buflen < n )
+ return( MBEDCRYPTO_ERR_MPI_BUFFER_TOO_SMALL );
+
+ memset( buf, 0, buflen );
+
+ for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
+ buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+
+ return( 0 );
+}
+
+/*
+ * Left-shift: X <<= count
+ */
+int mbedcrypto_mpi_shift_l( mbedcrypto_mpi *X, size_t count )
+{
+ int ret;
+ size_t i, v0, t1;
+ mbedcrypto_mpi_uint r0 = 0, r1;
+
+ v0 = count / (biL );
+ t1 = count & (biL - 1);
+
+ i = mbedcrypto_mpi_bitlen( X ) + count;
+
+ if( X->n * biL < i )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+
+ ret = 0;
+
+ /*
+ * shift by count / limb_size
+ */
+ if( v0 > 0 )
+ {
+ for( i = X->n; i > v0; i-- )
+ X->p[i - 1] = X->p[i - v0 - 1];
+
+ for( ; i > 0; i-- )
+ X->p[i - 1] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if( t1 > 0 )
+ {
+ for( i = v0; i < X->n; i++ )
+ {
+ r1 = X->p[i] >> (biL - t1);
+ X->p[i] <<= t1;
+ X->p[i] |= r0;
+ r0 = r1;
+ }
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Right-shift: X >>= count
+ */
+int mbedcrypto_mpi_shift_r( mbedcrypto_mpi *X, size_t count )
+{
+ size_t i, v0, v1;
+ mbedcrypto_mpi_uint r0 = 0, r1;
+
+ v0 = count / biL;
+ v1 = count & (biL - 1);
+
+ if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
+ return mbedcrypto_mpi_lset( X, 0 );
+
+ /*
+ * shift by count / limb_size
+ */
+ if( v0 > 0 )
+ {
+ for( i = 0; i < X->n - v0; i++ )
+ X->p[i] = X->p[i + v0];
+
+ for( ; i < X->n; i++ )
+ X->p[i] = 0;
+ }
+
+ /*
+ * shift by count % limb_size
+ */
+ if( v1 > 0 )
+ {
+ for( i = X->n; i > 0; i-- )
+ {
+ r1 = X->p[i - 1] << (biL - v1);
+ X->p[i - 1] >>= v1;
+ X->p[i - 1] |= r0;
+ r0 = r1;
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare unsigned values
+ */
+int mbedcrypto_mpi_cmp_abs( const mbedcrypto_mpi *X, const mbedcrypto_mpi *Y )
+{
+ size_t i, j;
+
+ for( i = X->n; i > 0; i-- )
+ if( X->p[i - 1] != 0 )
+ break;
+
+ for( j = Y->n; j > 0; j-- )
+ if( Y->p[j - 1] != 0 )
+ break;
+
+ if( i == 0 && j == 0 )
+ return( 0 );
+
+ if( i > j ) return( 1 );
+ if( j > i ) return( -1 );
+
+ for( ; i > 0; i-- )
+ {
+ if( X->p[i - 1] > Y->p[i - 1] ) return( 1 );
+ if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mbedcrypto_mpi_cmp_mpi( const mbedcrypto_mpi *X, const mbedcrypto_mpi *Y )
+{
+ size_t i, j;
+
+ for( i = X->n; i > 0; i-- )
+ if( X->p[i - 1] != 0 )
+ break;
+
+ for( j = Y->n; j > 0; j-- )
+ if( Y->p[j - 1] != 0 )
+ break;
+
+ if( i == 0 && j == 0 )
+ return( 0 );
+
+ if( i > j ) return( X->s );
+ if( j > i ) return( -Y->s );
+
+ if( X->s > 0 && Y->s < 0 ) return( 1 );
+ if( Y->s > 0 && X->s < 0 ) return( -1 );
+
+ for( ; i > 0; i-- )
+ {
+ if( X->p[i - 1] > Y->p[i - 1] ) return( X->s );
+ if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mbedcrypto_mpi_cmp_int( const mbedcrypto_mpi *X, mbedcrypto_mpi_sint z )
+{
+ mbedcrypto_mpi Y;
+ mbedcrypto_mpi_uint p[1];
+
+ *p = ( z < 0 ) ? -z : z;
+ Y.s = ( z < 0 ) ? -1 : 1;
+ Y.n = 1;
+ Y.p = p;
+
+ return( mbedcrypto_mpi_cmp_mpi( X, &Y ) );
+}
+
+/*
+ * Unsigned addition: X = |A| + |B| (HAC 14.7)
+ */
+int mbedcrypto_mpi_add_abs( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B )
+{
+ int ret;
+ size_t i, j;
+ mbedcrypto_mpi_uint *o, *p, c, tmp;
+
+ if( X == B )
+ {
+ const mbedcrypto_mpi *T = A; A = X; B = T;
+ }
+
+ if( X != A )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( X, A ) );
+
+ /*
+ * X should always be positive as a result of unsigned additions.
+ */
+ X->s = 1;
+
+ for( j = B->n; j > 0; j-- )
+ if( B->p[j - 1] != 0 )
+ break;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, j ) );
+
+ o = B->p; p = X->p; c = 0;
+
+ /*
+ * tmp is used because it might happen that p == o
+ */
+ for( i = 0; i < j; i++, o++, p++ )
+ {
+ tmp= *o;
+ *p += c; c = ( *p < c );
+ *p += tmp; c += ( *p < tmp );
+ }
+
+ while( c != 0 )
+ {
+ if( i >= X->n )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, i + 1 ) );
+ p = X->p + i;
+ }
+
+ *p += c; c = ( *p < c ); i++; p++;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Helper for mbedcrypto_mpi subtraction
+ */
+static void mpi_sub_hlp( size_t n, mbedcrypto_mpi_uint *s, mbedcrypto_mpi_uint *d )
+{
+ size_t i;
+ mbedcrypto_mpi_uint c, z;
+
+ for( i = c = 0; i < n; i++, s++, d++ )
+ {
+ z = ( *d < c ); *d -= c;
+ c = ( *d < *s ) + z; *d -= *s;
+ }
+
+ while( c != 0 )
+ {
+ z = ( *d < c ); *d -= c;
+ c = z; d++;
+ }
+}
+
+/*
+ * Unsigned subtraction: X = |A| - |B| (HAC 14.9)
+ */
+int mbedcrypto_mpi_sub_abs( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B )
+{
+ mbedcrypto_mpi TB;
+ int ret;
+ size_t n;
+
+ if( mbedcrypto_mpi_cmp_abs( A, B ) < 0 )
+ return( MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE );
+
+ mbedcrypto_mpi_init( &TB );
+
+ if( X == B )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &TB, B ) );
+ B = &TB;
+ }
+
+ if( X != A )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( X, A ) );
+
+ /*
+ * X should always be positive as a result of unsigned subtractions.
+ */
+ X->s = 1;
+
+ ret = 0;
+
+ for( n = B->n; n > 0; n-- )
+ if( B->p[n - 1] != 0 )
+ break;
+
+ mpi_sub_hlp( n, B->p, X->p );
+
+cleanup:
+
+ mbedcrypto_mpi_free( &TB );
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + B
+ */
+int mbedcrypto_mpi_add_mpi( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B )
+{
+ int ret, s = A->s;
+
+ if( A->s * B->s < 0 )
+ {
+ if( mbedcrypto_mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed subtraction: X = A - B
+ */
+int mbedcrypto_mpi_sub_mpi( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B )
+{
+ int ret, s = A->s;
+
+ if( A->s * B->s > 0 )
+ {
+ if( mbedcrypto_mpi_cmp_abs( A, B ) >= 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_abs( X, A, B ) );
+ X->s = s;
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_abs( X, B, A ) );
+ X->s = -s;
+ }
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_abs( X, A, B ) );
+ X->s = s;
+ }
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Signed addition: X = A + b
+ */
+int mbedcrypto_mpi_add_int( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b )
+{
+ mbedcrypto_mpi _B;
+ mbedcrypto_mpi_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mbedcrypto_mpi_add_mpi( X, A, &_B ) );
+}
+
+/*
+ * Signed subtraction: X = A - b
+ */
+int mbedcrypto_mpi_sub_int( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b )
+{
+ mbedcrypto_mpi _B;
+ mbedcrypto_mpi_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mbedcrypto_mpi_sub_mpi( X, A, &_B ) );
+}
+
+/*
+ * Helper for mbedcrypto_mpi multiplication
+ */
+static
+#if defined(__APPLE__) && defined(__arm__)
+/*
+ * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
+ * appears to need this to prevent bad ARM code generation at -O3.
+ */
+__attribute__ ((noinline))
+#endif
+void mpi_mul_hlp( size_t i, mbedcrypto_mpi_uint *s, mbedcrypto_mpi_uint *d, mbedcrypto_mpi_uint b )
+{
+ mbedcrypto_mpi_uint c = 0, t = 0;
+
+#if defined(MULADDC_HUIT)
+ for( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_HUIT
+ MULADDC_STOP
+ }
+
+ for( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#else /* MULADDC_HUIT */
+ for( ; i >= 16; i -= 16 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for( ; i >= 8; i -= 8 )
+ {
+ MULADDC_INIT
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_CORE MULADDC_CORE
+ MULADDC_STOP
+ }
+
+ for( ; i > 0; i-- )
+ {
+ MULADDC_INIT
+ MULADDC_CORE
+ MULADDC_STOP
+ }
+#endif /* MULADDC_HUIT */
+
+ t++;
+
+ do {
+ *d += c; c = ( *d < c ); d++;
+ }
+ while( c != 0 );
+}
+
+/*
+ * Baseline multiplication: X = A * B (HAC 14.12)
+ */
+int mbedcrypto_mpi_mul_mpi( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B )
+{
+ int ret;
+ size_t i, j;
+ mbedcrypto_mpi TA, TB;
+
+ mbedcrypto_mpi_init( &TA ); mbedcrypto_mpi_init( &TB );
+
+ if( X == A ) { MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &TA, A ) ); A = &TA; }
+ if( X == B ) { MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &TB, B ) ); B = &TB; }
+
+ for( i = A->n; i > 0; i-- )
+ if( A->p[i - 1] != 0 )
+ break;
+
+ for( j = B->n; j > 0; j-- )
+ if( B->p[j - 1] != 0 )
+ break;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, i + j ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( X, 0 ) );
+
+ for( ; j > 0; j-- )
+ mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
+
+ X->s = A->s * B->s;
+
+cleanup:
+
+ mbedcrypto_mpi_free( &TB ); mbedcrypto_mpi_free( &TA );
+
+ return( ret );
+}
+
+/*
+ * Baseline multiplication: X = A * b
+ */
+int mbedcrypto_mpi_mul_int( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, mbedcrypto_mpi_uint b )
+{
+ mbedcrypto_mpi _B;
+ mbedcrypto_mpi_uint p[1];
+
+ _B.s = 1;
+ _B.n = 1;
+ _B.p = p;
+ p[0] = b;
+
+ return( mbedcrypto_mpi_mul_mpi( X, A, &_B ) );
+}
+
+/*
+ * Unsigned integer divide - double mbedcrypto_mpi_uint dividend, u1/u0, and
+ * mbedcrypto_mpi_uint divisor, d
+ */
+static mbedcrypto_mpi_uint mbedcrypto_int_div_int( mbedcrypto_mpi_uint u1,
+ mbedcrypto_mpi_uint u0, mbedcrypto_mpi_uint d, mbedcrypto_mpi_uint *r )
+{
+#if defined(MBEDCRYPTO_HAVE_UDBL)
+ mbedcrypto_t_udbl dividend, quotient;
+#else
+ const mbedcrypto_mpi_uint radix = (mbedcrypto_mpi_uint) 1 << biH;
+ const mbedcrypto_mpi_uint uint_halfword_mask = ( (mbedcrypto_mpi_uint) 1 << biH ) - 1;
+ mbedcrypto_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
+ mbedcrypto_mpi_uint u0_msw, u0_lsw;
+ size_t s;
+#endif
+
+ /*
+ * Check for overflow
+ */
+ if( 0 == d || u1 >= d )
+ {
+ if (r != NULL) *r = ~0;
+
+ return ( ~0 );
+ }
+
+#if defined(MBEDCRYPTO_HAVE_UDBL)
+ dividend = (mbedcrypto_t_udbl) u1 << biL;
+ dividend |= (mbedcrypto_t_udbl) u0;
+ quotient = dividend / d;
+ if( quotient > ( (mbedcrypto_t_udbl) 1 << biL ) - 1 )
+ quotient = ( (mbedcrypto_t_udbl) 1 << biL ) - 1;
+
+ if( r != NULL )
+ *r = (mbedcrypto_mpi_uint)( dividend - (quotient * d ) );
+
+ return (mbedcrypto_mpi_uint) quotient;
+#else
+
+ /*
+ * Algorithm D, Section 4.3.1 - The Art of Computer Programming
+ * Vol. 2 - Seminumerical Algorithms, Knuth
+ */
+
+ /*
+ * Normalize the divisor, d, and dividend, u0, u1
+ */
+ s = mbedcrypto_clz( d );
+ d = d << s;
+
+ u1 = u1 << s;
+ u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedcrypto_mpi_sint)s >> ( biL - 1 ) );
+ u0 = u0 << s;
+
+ d1 = d >> biH;
+ d0 = d & uint_halfword_mask;
+
+ u0_msw = u0 >> biH;
+ u0_lsw = u0 & uint_halfword_mask;
+
+ /*
+ * Find the first quotient and remainder
+ */
+ q1 = u1 / d1;
+ r0 = u1 - d1 * q1;
+
+ while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
+ {
+ q1 -= 1;
+ r0 += d1;
+
+ if ( r0 >= radix ) break;
+ }
+
+ rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
+ q0 = rAX / d1;
+ r0 = rAX - q0 * d1;
+
+ while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
+ {
+ q0 -= 1;
+ r0 += d1;
+
+ if ( r0 >= radix ) break;
+ }
+
+ if (r != NULL)
+ *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
+
+ quotient = q1 * radix + q0;
+
+ return quotient;
+#endif
+}
+
+/*
+ * Division by mbedcrypto_mpi: A = Q * B + R (HAC 14.20)
+ */
+int mbedcrypto_mpi_div_mpi( mbedcrypto_mpi *Q, mbedcrypto_mpi *R, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B )
+{
+ int ret;
+ size_t i, n, t, k;
+ mbedcrypto_mpi X, Y, Z, T1, T2;
+
+ if( mbedcrypto_mpi_cmp_int( B, 0 ) == 0 )
+ return( MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO );
+
+ mbedcrypto_mpi_init( &X ); mbedcrypto_mpi_init( &Y ); mbedcrypto_mpi_init( &Z );
+ mbedcrypto_mpi_init( &T1 ); mbedcrypto_mpi_init( &T2 );
+
+ if( mbedcrypto_mpi_cmp_abs( A, B ) < 0 )
+ {
+ if( Q != NULL ) MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( Q, 0 ) );
+ if( R != NULL ) MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( R, A ) );
+ return( 0 );
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &X, A ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &Y, B ) );
+ X.s = Y.s = 1;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( &Z, A->n + 2 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &Z, 0 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( &T1, 2 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( &T2, 3 ) );
+
+ k = mbedcrypto_mpi_bitlen( &Y ) % biL;
+ if( k < biL - 1 )
+ {
+ k = biL - 1 - k;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &X, k ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &Y, k ) );
+ }
+ else k = 0;
+
+ n = X.n - 1;
+ t = Y.n - 1;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &Y, biL * ( n - t ) ) );
+
+ while( mbedcrypto_mpi_cmp_mpi( &X, &Y ) >= 0 )
+ {
+ Z.p[n - t]++;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &X, &X, &Y ) );
+ }
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &Y, biL * ( n - t ) ) );
+
+ for( i = n; i > t ; i-- )
+ {
+ if( X.p[i] >= Y.p[t] )
+ Z.p[i - t - 1] = ~0;
+ else
+ {
+ Z.p[i - t - 1] = mbedcrypto_int_div_int( X.p[i], X.p[i - 1],
+ Y.p[t], NULL);
+ }
+
+ Z.p[i - t - 1]++;
+ do
+ {
+ Z.p[i - t - 1]--;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &T1, 0 ) );
+ T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
+ T1.p[1] = Y.p[t];
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &T2, 0 ) );
+ T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
+ T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
+ T2.p[2] = X.p[i];
+ }
+ while( mbedcrypto_mpi_cmp_mpi( &T1, &T2 ) > 0 );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &X, &X, &T1 ) );
+
+ if( mbedcrypto_mpi_cmp_int( &X, 0 ) < 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &T1, &Y ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &X, &X, &T1 ) );
+ Z.p[i - t - 1]--;
+ }
+ }
+
+ if( Q != NULL )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( Q, &Z ) );
+ Q->s = A->s * B->s;
+ }
+
+ if( R != NULL )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &X, k ) );
+ X.s = A->s;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( R, &X ) );
+
+ if( mbedcrypto_mpi_cmp_int( R, 0 ) == 0 )
+ R->s = 1;
+ }
+
+cleanup:
+
+ mbedcrypto_mpi_free( &X ); mbedcrypto_mpi_free( &Y ); mbedcrypto_mpi_free( &Z );
+ mbedcrypto_mpi_free( &T1 ); mbedcrypto_mpi_free( &T2 );
+
+ return( ret );
+}
+
+/*
+ * Division by int: A = Q * b + R
+ */
+int mbedcrypto_mpi_div_int( mbedcrypto_mpi *Q, mbedcrypto_mpi *R, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b )
+{
+ mbedcrypto_mpi _B;
+ mbedcrypto_mpi_uint p[1];
+
+ p[0] = ( b < 0 ) ? -b : b;
+ _B.s = ( b < 0 ) ? -1 : 1;
+ _B.n = 1;
+ _B.p = p;
+
+ return( mbedcrypto_mpi_div_mpi( Q, R, A, &_B ) );
+}
+
+/*
+ * Modulo: R = A mod B
+ */
+int mbedcrypto_mpi_mod_mpi( mbedcrypto_mpi *R, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B )
+{
+ int ret;
+
+ if( mbedcrypto_mpi_cmp_int( B, 0 ) < 0 )
+ return( MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_div_mpi( NULL, R, A, B ) );
+
+ while( mbedcrypto_mpi_cmp_int( R, 0 ) < 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( R, R, B ) );
+
+ while( mbedcrypto_mpi_cmp_mpi( R, B ) >= 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( R, R, B ) );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Modulo: r = A mod b
+ */
+int mbedcrypto_mpi_mod_int( mbedcrypto_mpi_uint *r, const mbedcrypto_mpi *A, mbedcrypto_mpi_sint b )
+{
+ size_t i;
+ mbedcrypto_mpi_uint x, y, z;
+
+ if( b == 0 )
+ return( MBEDCRYPTO_ERR_MPI_DIVISION_BY_ZERO );
+
+ if( b < 0 )
+ return( MBEDCRYPTO_ERR_MPI_NEGATIVE_VALUE );
+
+ /*
+ * handle trivial cases
+ */
+ if( b == 1 )
+ {
+ *r = 0;
+ return( 0 );
+ }
+
+ if( b == 2 )
+ {
+ *r = A->p[0] & 1;
+ return( 0 );
+ }
+
+ /*
+ * general case
+ */
+ for( i = A->n, y = 0; i > 0; i-- )
+ {
+ x = A->p[i - 1];
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+
+ x <<= biH;
+ y = ( y << biH ) | ( x >> biH );
+ z = y / b;
+ y -= z * b;
+ }
+
+ /*
+ * If A is negative, then the current y represents a negative value.
+ * Flipping it to the positive side.
+ */
+ if( A->s < 0 && y != 0 )
+ y = b - y;
+
+ *r = y;
+
+ return( 0 );
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis)
+ */
+static void mpi_montg_init( mbedcrypto_mpi_uint *mm, const mbedcrypto_mpi *N )
+{
+ mbedcrypto_mpi_uint x, m0 = N->p[0];
+ unsigned int i;
+
+ x = m0;
+ x += ( ( m0 + 2 ) & 4 ) << 1;
+
+ for( i = biL; i >= 8; i /= 2 )
+ x *= ( 2 - ( m0 * x ) );
+
+ *mm = ~x + 1;
+}
+
+/*
+ * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
+ */
+static int mpi_montmul( mbedcrypto_mpi *A, const mbedcrypto_mpi *B, const mbedcrypto_mpi *N, mbedcrypto_mpi_uint mm,
+ const mbedcrypto_mpi *T )
+{
+ size_t i, n, m;
+ mbedcrypto_mpi_uint u0, u1, *d;
+
+ if( T->n < N->n + 1 || T->p == NULL )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ memset( T->p, 0, T->n * ciL );
+
+ d = T->p;
+ n = N->n;
+ m = ( B->n < n ) ? B->n : n;
+
+ for( i = 0; i < n; i++ )
+ {
+ /*
+ * T = (T + u0*B + u1*N) / 2^biL
+ */
+ u0 = A->p[i];
+ u1 = ( d[0] + u0 * B->p[0] ) * mm;
+
+ mpi_mul_hlp( m, B->p, d, u0 );
+ mpi_mul_hlp( n, N->p, d, u1 );
+
+ *d++ = u0; d[n + 1] = 0;
+ }
+
+ memcpy( A->p, d, ( n + 1 ) * ciL );
+
+ if( mbedcrypto_mpi_cmp_abs( A, N ) >= 0 )
+ mpi_sub_hlp( n, N->p, A->p );
+ else
+ /* prevent timing attacks */
+ mpi_sub_hlp( n, A->p, T->p );
+
+ return( 0 );
+}
+
+/*
+ * Montgomery reduction: A = A * R^-1 mod N
+ */
+static int mpi_montred( mbedcrypto_mpi *A, const mbedcrypto_mpi *N, mbedcrypto_mpi_uint mm, const mbedcrypto_mpi *T )
+{
+ mbedcrypto_mpi_uint z = 1;
+ mbedcrypto_mpi U;
+
+ U.n = U.s = (int) z;
+ U.p = &z;
+
+ return( mpi_montmul( A, &U, N, mm, T ) );
+}
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
+ */
+int mbedcrypto_mpi_exp_mod( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *E, const mbedcrypto_mpi *N, mbedcrypto_mpi *_RR )
+{
+ int ret;
+ size_t wbits, wsize, one = 1;
+ size_t i, j, nblimbs;
+ size_t bufsize, nbits;
+ mbedcrypto_mpi_uint ei, mm, state;
+ mbedcrypto_mpi RR, T, W[ 2 << MBEDCRYPTO_MPI_WINDOW_SIZE ], Apos;
+ int neg;
+
+ if( mbedcrypto_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ if( mbedcrypto_mpi_cmp_int( E, 0 ) < 0 )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ /*
+ * Init temps and window size
+ */
+ mpi_montg_init( &mm, N );
+ mbedcrypto_mpi_init( &RR ); mbedcrypto_mpi_init( &T );
+ mbedcrypto_mpi_init( &Apos );
+ memset( W, 0, sizeof( W ) );
+
+ i = mbedcrypto_mpi_bitlen( E );
+
+ wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+ ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
+
+ if( wsize > MBEDCRYPTO_MPI_WINDOW_SIZE )
+ wsize = MBEDCRYPTO_MPI_WINDOW_SIZE;
+
+ j = N->n + 1;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( X, j ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( &W[1], j ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( &T, j * 2 ) );
+
+ /*
+ * Compensate for negative A (and correct at the end)
+ */
+ neg = ( A->s == -1 );
+ if( neg )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &Apos, A ) );
+ Apos.s = 1;
+ A = &Apos;
+ }
+
+ /*
+ * If 1st call, pre-compute R^2 mod N
+ */
+ if( _RR == NULL || _RR->p == NULL )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &RR, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &RR, N->n * 2 * biL ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &RR, &RR, N ) );
+
+ if( _RR != NULL )
+ memcpy( _RR, &RR, sizeof( mbedcrypto_mpi ) );
+ }
+ else
+ memcpy( &RR, _RR, sizeof( mbedcrypto_mpi ) );
+
+ /*
+ * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+ */
+ if( mbedcrypto_mpi_cmp_mpi( A, N ) >= 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &W[1], A, N ) );
+ else
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &W[1], A ) );
+
+ MBEDCRYPTO_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
+
+ /*
+ * X = R^2 * R^-1 mod N = R mod N
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( X, &RR ) );
+ MBEDCRYPTO_MPI_CHK( mpi_montred( X, N, mm, &T ) );
+
+ if( wsize > 1 )
+ {
+ /*
+ * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+ */
+ j = one << ( wsize - 1 );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( &W[j], N->n + 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &W[j], &W[1] ) );
+
+ for( i = 0; i < wsize - 1; i++ )
+ MBEDCRYPTO_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
+
+ /*
+ * W[i] = W[i - 1] * W[1]
+ */
+ for( i = j + 1; i < ( one << wsize ); i++ )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( &W[i], N->n + 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &W[i], &W[i - 1] ) );
+
+ MBEDCRYPTO_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
+ }
+ }
+
+ nblimbs = E->n;
+ bufsize = 0;
+ nbits = 0;
+ wbits = 0;
+ state = 0;
+
+ while( 1 )
+ {
+ if( bufsize == 0 )
+ {
+ if( nblimbs == 0 )
+ break;
+
+ nblimbs--;
+
+ bufsize = sizeof( mbedcrypto_mpi_uint ) << 3;
+ }
+
+ bufsize--;
+
+ ei = (E->p[nblimbs] >> bufsize) & 1;
+
+ /*
+ * skip leading 0s
+ */
+ if( ei == 0 && state == 0 )
+ continue;
+
+ if( ei == 0 && state == 1 )
+ {
+ /*
+ * out of window, square X
+ */
+ MBEDCRYPTO_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
+ continue;
+ }
+
+ /*
+ * add ei to current window
+ */
+ state = 2;
+
+ nbits++;
+ wbits |= ( ei << ( wsize - nbits ) );
+
+ if( nbits == wsize )
+ {
+ /*
+ * X = X^wsize R^-1 mod N
+ */
+ for( i = 0; i < wsize; i++ )
+ MBEDCRYPTO_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
+
+ /*
+ * X = X * W[wbits] R^-1 mod N
+ */
+ MBEDCRYPTO_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
+
+ state--;
+ nbits = 0;
+ wbits = 0;
+ }
+ }
+
+ /*
+ * process the remaining bits
+ */
+ for( i = 0; i < nbits; i++ )
+ {
+ MBEDCRYPTO_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
+
+ wbits <<= 1;
+
+ if( ( wbits & ( one << wsize ) ) != 0 )
+ MBEDCRYPTO_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
+ }
+
+ /*
+ * X = A^E * R * R^-1 mod N = A^E mod N
+ */
+ MBEDCRYPTO_MPI_CHK( mpi_montred( X, N, mm, &T ) );
+
+ if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
+ {
+ X->s = -1;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( X, N, X ) );
+ }
+
+cleanup:
+
+ for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
+ mbedcrypto_mpi_free( &W[i] );
+
+ mbedcrypto_mpi_free( &W[1] ); mbedcrypto_mpi_free( &T ); mbedcrypto_mpi_free( &Apos );
+
+ if( _RR == NULL || _RR->p == NULL )
+ mbedcrypto_mpi_free( &RR );
+
+ return( ret );
+}
+
+/*
+ * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
+ */
+int mbedcrypto_mpi_gcd( mbedcrypto_mpi *G, const mbedcrypto_mpi *A, const mbedcrypto_mpi *B )
+{
+ int ret;
+ size_t lz, lzt;
+ mbedcrypto_mpi TG, TA, TB;
+
+ mbedcrypto_mpi_init( &TG ); mbedcrypto_mpi_init( &TA ); mbedcrypto_mpi_init( &TB );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &TA, A ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &TB, B ) );
+
+ lz = mbedcrypto_mpi_lsb( &TA );
+ lzt = mbedcrypto_mpi_lsb( &TB );
+
+ if( lzt < lz )
+ lz = lzt;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &TA, lz ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &TB, lz ) );
+
+ TA.s = TB.s = 1;
+
+ while( mbedcrypto_mpi_cmp_int( &TA, 0 ) != 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &TA, mbedcrypto_mpi_lsb( &TA ) ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &TB, mbedcrypto_mpi_lsb( &TB ) ) );
+
+ if( mbedcrypto_mpi_cmp_mpi( &TA, &TB ) >= 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_abs( &TA, &TA, &TB ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &TA, 1 ) );
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_abs( &TB, &TB, &TA ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &TB, 1 ) );
+ }
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &TB, lz ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( G, &TB ) );
+
+cleanup:
+
+ mbedcrypto_mpi_free( &TG ); mbedcrypto_mpi_free( &TA ); mbedcrypto_mpi_free( &TB );
+
+ return( ret );
+}
+
+/*
+ * Fill X with size bytes of random.
+ *
+ * Use a temporary bytes representation to make sure the result is the same
+ * regardless of the platform endianness (useful when f_rng is actually
+ * deterministic, eg for tests).
+ */
+int mbedcrypto_mpi_fill_random( mbedcrypto_mpi *X, size_t size,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ unsigned char buf[MBEDCRYPTO_MPI_MAX_SIZE];
+
+ if( size > MBEDCRYPTO_MPI_MAX_SIZE )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ MBEDCRYPTO_MPI_CHK( f_rng( p_rng, buf, size ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( X, buf, size ) );
+
+cleanup:
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+ return( ret );
+}
+
+/*
+ * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
+ */
+int mbedcrypto_mpi_inv_mod( mbedcrypto_mpi *X, const mbedcrypto_mpi *A, const mbedcrypto_mpi *N )
+{
+ int ret;
+ mbedcrypto_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
+
+ if( mbedcrypto_mpi_cmp_int( N, 1 ) <= 0 )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ mbedcrypto_mpi_init( &TA ); mbedcrypto_mpi_init( &TU ); mbedcrypto_mpi_init( &U1 ); mbedcrypto_mpi_init( &U2 );
+ mbedcrypto_mpi_init( &G ); mbedcrypto_mpi_init( &TB ); mbedcrypto_mpi_init( &TV );
+ mbedcrypto_mpi_init( &V1 ); mbedcrypto_mpi_init( &V2 );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_gcd( &G, A, N ) );
+
+ if( mbedcrypto_mpi_cmp_int( &G, 1 ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE;
+ goto cleanup;
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &TA, A, N ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &TU, &TA ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &TB, N ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &TV, N ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &U1, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &U2, 0 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &V1, 0 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &V2, 1 ) );
+
+ do
+ {
+ while( ( TU.p[0] & 1 ) == 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &TU, 1 ) );
+
+ if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &U1, &U1, &TB ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &U2, &U2, &TA ) );
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &U1, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &U2, 1 ) );
+ }
+
+ while( ( TV.p[0] & 1 ) == 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &TV, 1 ) );
+
+ if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &V1, &V1, &TB ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &V2, &V2, &TA ) );
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &V1, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &V2, 1 ) );
+ }
+
+ if( mbedcrypto_mpi_cmp_mpi( &TU, &TV ) >= 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &TU, &TU, &TV ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &U1, &U1, &V1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &U2, &U2, &V2 ) );
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &TV, &TV, &TU ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &V1, &V1, &U1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &V2, &V2, &U2 ) );
+ }
+ }
+ while( mbedcrypto_mpi_cmp_int( &TU, 0 ) != 0 );
+
+ while( mbedcrypto_mpi_cmp_int( &V1, 0 ) < 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &V1, &V1, N ) );
+
+ while( mbedcrypto_mpi_cmp_mpi( &V1, N ) >= 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &V1, &V1, N ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( X, &V1 ) );
+
+cleanup:
+
+ mbedcrypto_mpi_free( &TA ); mbedcrypto_mpi_free( &TU ); mbedcrypto_mpi_free( &U1 ); mbedcrypto_mpi_free( &U2 );
+ mbedcrypto_mpi_free( &G ); mbedcrypto_mpi_free( &TB ); mbedcrypto_mpi_free( &TV );
+ mbedcrypto_mpi_free( &V1 ); mbedcrypto_mpi_free( &V2 );
+
+ return( ret );
+}
+
+#if defined(MBEDCRYPTO_GENPRIME)
+
+static const int small_prime[] =
+{
+ 3, 5, 7, 11, 13, 17, 19, 23,
+ 29, 31, 37, 41, 43, 47, 53, 59,
+ 61, 67, 71, 73, 79, 83, 89, 97,
+ 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179,
+ 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251, 257, 263, 269,
+ 271, 277, 281, 283, 293, 307, 311, 313,
+ 317, 331, 337, 347, 349, 353, 359, 367,
+ 373, 379, 383, 389, 397, 401, 409, 419,
+ 421, 431, 433, 439, 443, 449, 457, 461,
+ 463, 467, 479, 487, 491, 499, 503, 509,
+ 521, 523, 541, 547, 557, 563, 569, 571,
+ 577, 587, 593, 599, 601, 607, 613, 617,
+ 619, 631, 641, 643, 647, 653, 659, 661,
+ 673, 677, 683, 691, 701, 709, 719, 727,
+ 733, 739, 743, 751, 757, 761, 769, 773,
+ 787, 797, 809, 811, 821, 823, 827, 829,
+ 839, 853, 857, 859, 863, 877, 881, 883,
+ 887, 907, 911, 919, 929, 937, 941, 947,
+ 953, 967, 971, 977, 983, 991, 997, -103
+};
+
+/*
+ * Small divisors test (X must be positive)
+ *
+ * Return values:
+ * 0: no small factor (possible prime, more tests needed)
+ * 1: certain prime
+ * MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
+ * other negative: error
+ */
+static int mpi_check_small_factors( const mbedcrypto_mpi *X )
+{
+ int ret = 0;
+ size_t i;
+ mbedcrypto_mpi_uint r;
+
+ if( ( X->p[0] & 1 ) == 0 )
+ return( MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE );
+
+ for( i = 0; small_prime[i] > 0; i++ )
+ {
+ if( mbedcrypto_mpi_cmp_int( X, small_prime[i] ) <= 0 )
+ return( 1 );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_int( &r, X, small_prime[i] ) );
+
+ if( r == 0 )
+ return( MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE );
+ }
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Miller-Rabin pseudo-primality test (HAC 4.24)
+ */
+static int mpi_miller_rabin( const mbedcrypto_mpi *X,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret, count;
+ size_t i, j, k, n, s;
+ mbedcrypto_mpi W, R, T, A, RR;
+
+ mbedcrypto_mpi_init( &W ); mbedcrypto_mpi_init( &R ); mbedcrypto_mpi_init( &T ); mbedcrypto_mpi_init( &A );
+ mbedcrypto_mpi_init( &RR );
+
+ /*
+ * W = |X| - 1
+ * R = W >> lsb( W )
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &W, X, 1 ) );
+ s = mbedcrypto_mpi_lsb( &W );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &R, &W ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &R, s ) );
+
+ i = mbedcrypto_mpi_bitlen( X );
+ /*
+ * HAC, table 4.4
+ */
+ n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
+ ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
+ ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
+
+ for( i = 0; i < n; i++ )
+ {
+ /*
+ * pick a random A, 1 < A < |X| - 1
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
+
+ if( mbedcrypto_mpi_cmp_mpi( &A, &W ) >= 0 )
+ {
+ j = mbedcrypto_mpi_bitlen( &A ) - mbedcrypto_mpi_bitlen( &W );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &A, j + 1 ) );
+ }
+ A.p[0] |= 3;
+
+ count = 0;
+ do {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
+
+ j = mbedcrypto_mpi_bitlen( &A );
+ k = mbedcrypto_mpi_bitlen( &W );
+ if (j > k) {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &A, j - k ) );
+ }
+
+ if (count++ > 30) {
+ return MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE;
+ }
+
+ } while ( mbedcrypto_mpi_cmp_mpi( &A, &W ) >= 0 ||
+ mbedcrypto_mpi_cmp_int( &A, 1 ) <= 0 );
+
+ /*
+ * A = A^R mod |X|
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_exp_mod( &A, &A, &R, X, &RR ) );
+
+ if( mbedcrypto_mpi_cmp_mpi( &A, &W ) == 0 ||
+ mbedcrypto_mpi_cmp_int( &A, 1 ) == 0 )
+ continue;
+
+ j = 1;
+ while( j < s && mbedcrypto_mpi_cmp_mpi( &A, &W ) != 0 )
+ {
+ /*
+ * A = A * A mod |X|
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T, &A, &A ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &A, &T, X ) );
+
+ if( mbedcrypto_mpi_cmp_int( &A, 1 ) == 0 )
+ break;
+
+ j++;
+ }
+
+ /*
+ * not prime if A != |X| - 1 or A == 1
+ */
+ if( mbedcrypto_mpi_cmp_mpi( &A, &W ) != 0 ||
+ mbedcrypto_mpi_cmp_int( &A, 1 ) == 0 )
+ {
+ ret = MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE;
+ break;
+ }
+ }
+
+cleanup:
+ mbedcrypto_mpi_free( &W ); mbedcrypto_mpi_free( &R ); mbedcrypto_mpi_free( &T ); mbedcrypto_mpi_free( &A );
+ mbedcrypto_mpi_free( &RR );
+
+ return( ret );
+}
+
+/*
+ * Pseudo-primality test: small factors, then Miller-Rabin
+ */
+int mbedcrypto_mpi_is_prime( const mbedcrypto_mpi *X,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ mbedcrypto_mpi XX;
+
+ XX.s = 1;
+ XX.n = X->n;
+ XX.p = X->p;
+
+ if( mbedcrypto_mpi_cmp_int( &XX, 0 ) == 0 ||
+ mbedcrypto_mpi_cmp_int( &XX, 1 ) == 0 )
+ return( MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE );
+
+ if( mbedcrypto_mpi_cmp_int( &XX, 2 ) == 0 )
+ return( 0 );
+
+ if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
+ {
+ if( ret == 1 )
+ return( 0 );
+
+ return( ret );
+ }
+
+ return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
+}
+
+/*
+ * Prime number generation
+ *
+ * If dh_flag is 0 and nbits is at least 1024, then the procedure
+ * follows the RSA probably-prime generation method of FIPS 186-4.
+ * NB. FIPS 186-4 only allows the specific bit lengths of 1024 and 1536.
+ */
+int mbedcrypto_mpi_gen_prime( mbedcrypto_mpi *X, size_t nbits, int dh_flag,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+#ifdef MBEDCRYPTO_HAVE_INT64
+// ceil(2^63.5)
+#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
+#else
+// ceil(2^31.5)
+#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
+#endif
+ int ret = MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE;
+ size_t k, n;
+ mbedcrypto_mpi_uint r;
+ mbedcrypto_mpi Y;
+
+ if( nbits < 3 || nbits > MBEDCRYPTO_MPI_MAX_BITS )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ mbedcrypto_mpi_init( &Y );
+
+ n = BITS_TO_LIMBS( nbits );
+
+ while( 1 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
+ /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
+ if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
+
+ k = n * biL;
+ if( k > nbits ) MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( X, k - nbits ) );
+ X->p[0] |= 1;
+
+ if( dh_flag == 0 )
+ {
+ ret = mbedcrypto_mpi_is_prime( X, f_rng, p_rng );
+
+ if( ret != MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+ }
+ else
+ {
+ /*
+ * An necessary condition for Y and X = 2Y + 1 to be prime
+ * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
+ * Make sure it is satisfied, while keeping X = 3 mod 4
+ */
+
+ X->p[0] |= 2;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_int( &r, X, 3 ) );
+ if( r == 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_int( X, X, 8 ) );
+ else if( r == 1 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_int( X, X, 4 ) );
+
+ /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &Y, X ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &Y, 1 ) );
+
+ while( 1 )
+ {
+ /*
+ * First, check small factors for X and Y
+ * before doing Miller-Rabin on any of them
+ */
+ if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
+ ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
+ ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
+ ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
+ goto cleanup;
+
+ if( ret != MBEDCRYPTO_ERR_MPI_NOT_ACCEPTABLE )
+ goto cleanup;
+
+ /*
+ * Next candidates. We want to preserve Y = (X-1) / 2 and
+ * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
+ * so up Y by 6 and X by 12.
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_int( X, X, 12 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_int( &Y, &Y, 6 ) );
+ }
+ }
+ }
+
+cleanup:
+
+ mbedcrypto_mpi_free( &Y );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_GENPRIME */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+#define GCD_PAIR_COUNT 3
+
+static const int gcd_pairs[GCD_PAIR_COUNT][3] =
+{
+ { 693, 609, 21 },
+ { 1764, 868, 28 },
+ { 768454923, 542167814, 1 }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_mpi_self_test( int verbose )
+{
+ int ret, i;
+ mbedcrypto_mpi A, E, N, X, Y, U, V;
+
+ mbedcrypto_mpi_init( &A ); mbedcrypto_mpi_init( &E ); mbedcrypto_mpi_init( &N ); mbedcrypto_mpi_init( &X );
+ mbedcrypto_mpi_init( &Y ); mbedcrypto_mpi_init( &U ); mbedcrypto_mpi_init( &V );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &A, 16,
+ "EFE021C2645FD1DC586E69184AF4A31E" \
+ "D5F53E93B5F123FA41680867BA110131" \
+ "944FE7952E2517337780CB0DB80E61AA" \
+ "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &E, 16,
+ "B2E7EFD37075B9F03FF989C7C5051C20" \
+ "34D2A323810251127E7BF8625A4F49A5" \
+ "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
+ "5B5C25763222FEFCCFC38B832366C29E" ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &N, 16,
+ "0066A198186C18C10B2F5ED9B522752A" \
+ "9830B69916E535C8F047518A889A43A5" \
+ "94B6BED27A168D31D4A52F88925AA8F5" ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &X, &A, &N ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &U, 16,
+ "602AB7ECA597A3D6B56FF9829A5E8B85" \
+ "9E857EA95A03512E2BAE7391688D264A" \
+ "A5663B0341DB9CCFD2C4C5F421FEC814" \
+ "8001B72E848A38CAE1C65F78E56ABDEF" \
+ "E12D3C039B8A02D6BE593F0BBBDA56F1" \
+ "ECF677152EF804370C1A305CAF3B5BF1" \
+ "30879B56C61DE584A0F53A2447A51E" ) );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " MPI test #1 (mul_mpi): " );
+
+ if( mbedcrypto_mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto cleanup;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_div_mpi( &X, &Y, &A, &N ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &U, 16,
+ "256567336059E52CAE22925474705F39A94" ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &V, 16,
+ "6613F26162223DF488E9CD48CC132C7A" \
+ "0AC93C701B001B092E4E5B9F73BCD27B" \
+ "9EE50D0657C77F374E903CDFA4C642" ) );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " MPI test #2 (div_mpi): " );
+
+ if( mbedcrypto_mpi_cmp_mpi( &X, &U ) != 0 ||
+ mbedcrypto_mpi_cmp_mpi( &Y, &V ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto cleanup;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &U, 16,
+ "36E139AEA55215609D2816998ED020BB" \
+ "BD96C37890F65171D948E9BC7CBAA4D9" \
+ "325D24D6A3C12710F10A09FA08AB87" ) );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " MPI test #3 (exp_mod): " );
+
+ if( mbedcrypto_mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto cleanup;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_inv_mod( &X, &A, &N ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &U, 16,
+ "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
+ "C3DBA76456363A10869622EAC2DD84EC" \
+ "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " MPI test #4 (inv_mod): " );
+
+ if( mbedcrypto_mpi_cmp_mpi( &X, &U ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto cleanup;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " MPI test #5 (simple gcd): " );
+
+ for( i = 0; i < GCD_PAIR_COUNT; i++ )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &X, gcd_pairs[i][0] ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &Y, gcd_pairs[i][1] ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_gcd( &A, &X, &Y ) );
+
+ if( mbedcrypto_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed at %d\n", i );
+
+ ret = 1;
+ goto cleanup;
+ }
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+cleanup:
+
+ if( ret != 0 && verbose != 0 )
+ mbedcrypto_printf( "Unexpected error, return code = %08X\n", ret );
+
+ mbedcrypto_mpi_free( &A ); mbedcrypto_mpi_free( &E ); mbedcrypto_mpi_free( &N ); mbedcrypto_mpi_free( &X );
+ mbedcrypto_mpi_free( &Y ); mbedcrypto_mpi_free( &U ); mbedcrypto_mpi_free( &V );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_BIGNUM_C */
diff --git a/library/blowfish.c b/library/blowfish.c
new file mode 100644
index 0000000..df158ad
--- /dev/null
+++ b/library/blowfish.c
@@ -0,0 +1,652 @@
+/*
+ * Blowfish implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The Blowfish block cipher was designed by Bruce Schneier in 1993.
+ * http://www.schneier.com/blowfish.html
+ * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29
+ *
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_BLOWFISH_C)
+
+#include "mbedcrypto/blowfish.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if !defined(MBEDCRYPTO_BLOWFISH_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+static const uint32_t P[MBEDCRYPTO_BLOWFISH_ROUNDS + 2] = {
+ 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
+ 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
+ 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
+ 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
+ 0x9216D5D9L, 0x8979FB1BL
+};
+
+/* declarations of data at the end of this file */
+static const uint32_t S[4][256];
+
+static uint32_t F( mbedcrypto_blowfish_context *ctx, uint32_t x )
+{
+ unsigned short a, b, c, d;
+ uint32_t y;
+
+ d = (unsigned short)(x & 0xFF);
+ x >>= 8;
+ c = (unsigned short)(x & 0xFF);
+ x >>= 8;
+ b = (unsigned short)(x & 0xFF);
+ x >>= 8;
+ a = (unsigned short)(x & 0xFF);
+ y = ctx->S[0][a] + ctx->S[1][b];
+ y = y ^ ctx->S[2][c];
+ y = y + ctx->S[3][d];
+
+ return( y );
+}
+
+static void blowfish_enc( mbedcrypto_blowfish_context *ctx, uint32_t *xl, uint32_t *xr )
+{
+ uint32_t Xl, Xr, temp;
+ short i;
+
+ Xl = *xl;
+ Xr = *xr;
+
+ for( i = 0; i < MBEDCRYPTO_BLOWFISH_ROUNDS; ++i )
+ {
+ Xl = Xl ^ ctx->P[i];
+ Xr = F( ctx, Xl ) ^ Xr;
+
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+ }
+
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+
+ Xr = Xr ^ ctx->P[MBEDCRYPTO_BLOWFISH_ROUNDS];
+ Xl = Xl ^ ctx->P[MBEDCRYPTO_BLOWFISH_ROUNDS + 1];
+
+ *xl = Xl;
+ *xr = Xr;
+}
+
+static void blowfish_dec( mbedcrypto_blowfish_context *ctx, uint32_t *xl, uint32_t *xr )
+{
+ uint32_t Xl, Xr, temp;
+ short i;
+
+ Xl = *xl;
+ Xr = *xr;
+
+ for( i = MBEDCRYPTO_BLOWFISH_ROUNDS + 1; i > 1; --i )
+ {
+ Xl = Xl ^ ctx->P[i];
+ Xr = F( ctx, Xl ) ^ Xr;
+
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+ }
+
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+
+ Xr = Xr ^ ctx->P[1];
+ Xl = Xl ^ ctx->P[0];
+
+ *xl = Xl;
+ *xr = Xr;
+}
+
+void mbedcrypto_blowfish_init( mbedcrypto_blowfish_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_blowfish_context ) );
+}
+
+void mbedcrypto_blowfish_free( mbedcrypto_blowfish_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_blowfish_context ) );
+}
+
+/*
+ * Blowfish key schedule
+ */
+int mbedcrypto_blowfish_setkey( mbedcrypto_blowfish_context *ctx, const unsigned char *key,
+ unsigned int keybits )
+{
+ unsigned int i, j, k;
+ uint32_t data, datal, datar;
+
+ if( keybits < MBEDCRYPTO_BLOWFISH_MIN_KEY_BITS || keybits > MBEDCRYPTO_BLOWFISH_MAX_KEY_BITS ||
+ ( keybits % 8 ) )
+ {
+ return( MBEDCRYPTO_ERR_BLOWFISH_INVALID_KEY_LENGTH );
+ }
+
+ keybits >>= 3;
+
+ for( i = 0; i < 4; i++ )
+ {
+ for( j = 0; j < 256; j++ )
+ ctx->S[i][j] = S[i][j];
+ }
+
+ j = 0;
+ for( i = 0; i < MBEDCRYPTO_BLOWFISH_ROUNDS + 2; ++i )
+ {
+ data = 0x00000000;
+ for( k = 0; k < 4; ++k )
+ {
+ data = ( data << 8 ) | key[j++];
+ if( j >= keybits )
+ j = 0;
+ }
+ ctx->P[i] = P[i] ^ data;
+ }
+
+ datal = 0x00000000;
+ datar = 0x00000000;
+
+ for( i = 0; i < MBEDCRYPTO_BLOWFISH_ROUNDS + 2; i += 2 )
+ {
+ blowfish_enc( ctx, &datal, &datar );
+ ctx->P[i] = datal;
+ ctx->P[i + 1] = datar;
+ }
+
+ for( i = 0; i < 4; i++ )
+ {
+ for( j = 0; j < 256; j += 2 )
+ {
+ blowfish_enc( ctx, &datal, &datar );
+ ctx->S[i][j] = datal;
+ ctx->S[i][j + 1] = datar;
+ }
+ }
+ return( 0 );
+}
+
+/*
+ * Blowfish-ECB block encryption/decryption
+ */
+int mbedcrypto_blowfish_crypt_ecb( mbedcrypto_blowfish_context *ctx,
+ int mode,
+ const unsigned char input[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+ unsigned char output[MBEDCRYPTO_BLOWFISH_BLOCKSIZE] )
+{
+ uint32_t X0, X1;
+
+ GET_UINT32_BE( X0, input, 0 );
+ GET_UINT32_BE( X1, input, 4 );
+
+ if( mode == MBEDCRYPTO_BLOWFISH_DECRYPT )
+ {
+ blowfish_dec( ctx, &X0, &X1 );
+ }
+ else /* MBEDCRYPTO_BLOWFISH_ENCRYPT */
+ {
+ blowfish_enc( ctx, &X0, &X1 );
+ }
+
+ PUT_UINT32_BE( X0, output, 0 );
+ PUT_UINT32_BE( X1, output, 4 );
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/*
+ * Blowfish-CBC buffer encryption/decryption
+ */
+int mbedcrypto_blowfish_crypt_cbc( mbedcrypto_blowfish_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[MBEDCRYPTO_BLOWFISH_BLOCKSIZE];
+
+ if( length % MBEDCRYPTO_BLOWFISH_BLOCKSIZE )
+ return( MBEDCRYPTO_ERR_BLOWFISH_INVALID_INPUT_LENGTH );
+
+ if( mode == MBEDCRYPTO_BLOWFISH_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, MBEDCRYPTO_BLOWFISH_BLOCKSIZE );
+ mbedcrypto_blowfish_crypt_ecb( ctx, mode, input, output );
+
+ for( i = 0; i < MBEDCRYPTO_BLOWFISH_BLOCKSIZE;i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, MBEDCRYPTO_BLOWFISH_BLOCKSIZE );
+
+ input += MBEDCRYPTO_BLOWFISH_BLOCKSIZE;
+ output += MBEDCRYPTO_BLOWFISH_BLOCKSIZE;
+ length -= MBEDCRYPTO_BLOWFISH_BLOCKSIZE;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < MBEDCRYPTO_BLOWFISH_BLOCKSIZE; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ mbedcrypto_blowfish_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, MBEDCRYPTO_BLOWFISH_BLOCKSIZE );
+
+ input += MBEDCRYPTO_BLOWFISH_BLOCKSIZE;
+ output += MBEDCRYPTO_BLOWFISH_BLOCKSIZE;
+ length -= MBEDCRYPTO_BLOWFISH_BLOCKSIZE;
+ }
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+/*
+ * Blowfish CFB buffer encryption/decryption
+ */
+int mbedcrypto_blowfish_crypt_cfb64( mbedcrypto_blowfish_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c;
+ size_t n = *iv_off;
+
+ if( mode == MBEDCRYPTO_BLOWFISH_DECRYPT )
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ mbedcrypto_blowfish_crypt_ecb( ctx, MBEDCRYPTO_BLOWFISH_ENCRYPT, iv, iv );
+
+ c = *input++;
+ *output++ = (unsigned char)( c ^ iv[n] );
+ iv[n] = (unsigned char) c;
+
+ n = ( n + 1 ) % MBEDCRYPTO_BLOWFISH_BLOCKSIZE;
+ }
+ }
+ else
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ mbedcrypto_blowfish_crypt_ecb( ctx, MBEDCRYPTO_BLOWFISH_ENCRYPT, iv, iv );
+
+ iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+ n = ( n + 1 ) % MBEDCRYPTO_BLOWFISH_BLOCKSIZE;
+ }
+ }
+
+ *iv_off = n;
+
+ return( 0 );
+}
+#endif /*MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/*
+ * Blowfish CTR buffer encryption/decryption
+ */
+int mbedcrypto_blowfish_crypt_ctr( mbedcrypto_blowfish_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+ unsigned char stream_block[MBEDCRYPTO_BLOWFISH_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c, i;
+ size_t n = *nc_off;
+
+ while( length-- )
+ {
+ if( n == 0 ) {
+ mbedcrypto_blowfish_crypt_ecb( ctx, MBEDCRYPTO_BLOWFISH_ENCRYPT, nonce_counter,
+ stream_block );
+
+ for( i = MBEDCRYPTO_BLOWFISH_BLOCKSIZE; i > 0; i-- )
+ if( ++nonce_counter[i - 1] != 0 )
+ break;
+ }
+ c = *input++;
+ *output++ = (unsigned char)( c ^ stream_block[n] );
+
+ n = ( n + 1 ) % MBEDCRYPTO_BLOWFISH_BLOCKSIZE;
+ }
+
+ *nc_off = n;
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+static const uint32_t S[4][256] = {
+ { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
+ 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
+ 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
+ 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
+ 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL,
+ 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L,
+ 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL,
+ 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL,
+ 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L,
+ 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L,
+ 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL,
+ 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL,
+ 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL,
+ 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L,
+ 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L,
+ 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L,
+ 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L,
+ 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L,
+ 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL,
+ 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L,
+ 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L,
+ 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L,
+ 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L,
+ 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL,
+ 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L,
+ 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL,
+ 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL,
+ 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L,
+ 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL,
+ 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L,
+ 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL,
+ 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L,
+ 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L,
+ 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL,
+ 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L,
+ 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L,
+ 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL,
+ 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L,
+ 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL,
+ 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L,
+ 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L,
+ 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL,
+ 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L,
+ 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L,
+ 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L,
+ 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L,
+ 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L,
+ 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL,
+ 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL,
+ 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L,
+ 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L,
+ 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L,
+ 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L,
+ 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL,
+ 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L,
+ 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL,
+ 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL,
+ 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L,
+ 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L,
+ 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L,
+ 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L,
+ 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L,
+ 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L,
+ 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL },
+ { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,
+ 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L,
+ 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L,
+ 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL,
+ 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L,
+ 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L,
+ 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL,
+ 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L,
+ 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L,
+ 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L,
+ 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL,
+ 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL,
+ 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L,
+ 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L,
+ 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L,
+ 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L,
+ 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL,
+ 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL,
+ 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL,
+ 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L,
+ 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL,
+ 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L,
+ 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L,
+ 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL,
+ 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL,
+ 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L,
+ 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL,
+ 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L,
+ 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL,
+ 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL,
+ 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L,
+ 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L,
+ 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L,
+ 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L,
+ 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L,
+ 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L,
+ 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L,
+ 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL,
+ 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L,
+ 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL,
+ 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L,
+ 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L,
+ 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L,
+ 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L,
+ 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L,
+ 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L,
+ 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L,
+ 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L,
+ 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L,
+ 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L,
+ 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L,
+ 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L,
+ 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L,
+ 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L,
+ 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L,
+ 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L,
+ 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL,
+ 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL,
+ 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L,
+ 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL,
+ 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L,
+ 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L,
+ 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L,
+ 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L },
+ { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,
+ 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L,
+ 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL,
+ 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L,
+ 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L,
+ 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L,
+ 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL,
+ 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL,
+ 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL,
+ 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L,
+ 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L,
+ 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL,
+ 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L,
+ 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL,
+ 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L,
+ 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL,
+ 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L,
+ 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL,
+ 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L,
+ 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL,
+ 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L,
+ 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L,
+ 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL,
+ 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L,
+ 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L,
+ 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L,
+ 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L,
+ 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL,
+ 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L,
+ 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL,
+ 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L,
+ 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL,
+ 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L,
+ 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL,
+ 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL,
+ 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL,
+ 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L,
+ 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L,
+ 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL,
+ 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL,
+ 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL,
+ 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL,
+ 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL,
+ 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L,
+ 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L,
+ 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L,
+ 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L,
+ 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL,
+ 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL,
+ 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L,
+ 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L,
+ 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L,
+ 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L,
+ 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L,
+ 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L,
+ 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L,
+ 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L,
+ 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L,
+ 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L,
+ 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL,
+ 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L,
+ 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL,
+ 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L,
+ 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L },
+ { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,
+ 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL,
+ 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL,
+ 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L,
+ 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L,
+ 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L,
+ 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L,
+ 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L,
+ 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L,
+ 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L,
+ 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L,
+ 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L,
+ 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L,
+ 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L,
+ 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L,
+ 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL,
+ 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL,
+ 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L,
+ 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL,
+ 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL,
+ 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL,
+ 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L,
+ 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL,
+ 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL,
+ 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L,
+ 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L,
+ 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L,
+ 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L,
+ 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL,
+ 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL,
+ 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L,
+ 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L,
+ 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L,
+ 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL,
+ 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L,
+ 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L,
+ 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L,
+ 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL,
+ 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L,
+ 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L,
+ 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L,
+ 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL,
+ 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL,
+ 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L,
+ 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L,
+ 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L,
+ 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L,
+ 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL,
+ 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L,
+ 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL,
+ 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL,
+ 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L,
+ 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L,
+ 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL,
+ 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L,
+ 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL,
+ 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L,
+ 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL,
+ 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L,
+ 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L,
+ 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
+ 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
+ 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
+ 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L }
+};
+
+#endif /* !MBEDCRYPTO_BLOWFISH_ALT */
+#endif /* MBEDCRYPTO_BLOWFISH_C */
diff --git a/library/camellia.c b/library/camellia.c
new file mode 100644
index 0000000..a5361fd
--- /dev/null
+++ b/library/camellia.c
@@ -0,0 +1,1068 @@
+/*
+ * Camellia implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The Camellia block cipher was designed by NTT and Mitsubishi Electric
+ * Corporation.
+ *
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_CAMELLIA_C)
+
+#include "mbedcrypto/camellia.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_CAMELLIA_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+static const unsigned char SIGMA_CHARS[6][8] =
+{
+ { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },
+ { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 },
+ { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe },
+ { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c },
+ { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d },
+ { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd }
+};
+
+#if defined(MBEDCRYPTO_CAMELLIA_SMALL_MEMORY)
+
+static const unsigned char FSb[256] =
+{
+ 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65,
+ 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189,
+ 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26,
+ 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77,
+ 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153,
+ 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215,
+ 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34,
+ 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80,
+ 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210,
+ 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148,
+ 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226,
+ 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46,
+ 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89,
+ 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250,
+ 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164,
+ 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158
+};
+
+#define SBOX1(n) FSb[(n)]
+#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff)
+#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)
+#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff]
+
+#else /* MBEDCRYPTO_CAMELLIA_SMALL_MEMORY */
+
+static const unsigned char FSb[256] =
+{
+ 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65,
+ 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189,
+ 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26,
+ 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77,
+ 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153,
+ 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215,
+ 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34,
+ 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80,
+ 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210,
+ 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148,
+ 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226,
+ 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46,
+ 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89,
+ 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250,
+ 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164,
+ 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158
+};
+
+static const unsigned char FSb2[256] =
+{
+ 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130,
+ 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123,
+ 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52,
+ 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154,
+ 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51,
+ 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175,
+ 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68,
+ 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160,
+ 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165,
+ 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41,
+ 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197,
+ 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92,
+ 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178,
+ 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245,
+ 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73,
+ 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61
+};
+
+static const unsigned char FSb3[256] =
+{
+ 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160,
+ 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222,
+ 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13,
+ 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166,
+ 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204,
+ 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235,
+ 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17,
+ 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40,
+ 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105,
+ 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74,
+ 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
+ 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23,
+ 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172,
+ 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125,
+ 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82,
+ 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79
+};
+
+static const unsigned char FSb4[256] =
+{
+ 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146,
+ 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108,
+ 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4,
+ 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105,
+ 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221,
+ 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99,
+ 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141,
+ 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128,
+ 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189,
+ 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77,
+ 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215,
+ 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80,
+ 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148,
+ 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46,
+ 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250,
+ 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158
+};
+
+#define SBOX1(n) FSb[(n)]
+#define SBOX2(n) FSb2[(n)]
+#define SBOX3(n) FSb3[(n)]
+#define SBOX4(n) FSb4[(n)]
+
+#endif /* MBEDCRYPTO_CAMELLIA_SMALL_MEMORY */
+
+static const unsigned char shifts[2][4][4] =
+{
+ {
+ { 1, 1, 1, 1 }, /* KL */
+ { 0, 0, 0, 0 }, /* KR */
+ { 1, 1, 1, 1 }, /* KA */
+ { 0, 0, 0, 0 } /* KB */
+ },
+ {
+ { 1, 0, 1, 1 }, /* KL */
+ { 1, 1, 0, 1 }, /* KR */
+ { 1, 1, 1, 0 }, /* KA */
+ { 1, 1, 0, 1 } /* KB */
+ }
+};
+
+static const signed char indexes[2][4][20] =
+{
+ {
+ { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39,
+ 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */
+ { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17,
+ 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */
+ },
+ {
+ { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1,
+ -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */
+ { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17,
+ 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */
+ { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59,
+ 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */
+ { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21,
+ 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */
+ }
+};
+
+static const signed char transposes[2][20] =
+{
+ {
+ 21, 22, 23, 20,
+ -1, -1, -1, -1,
+ 18, 19, 16, 17,
+ 11, 8, 9, 10,
+ 15, 12, 13, 14
+ },
+ {
+ 25, 26, 27, 24,
+ 29, 30, 31, 28,
+ 18, 19, 16, 17,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1
+ }
+};
+
+/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */
+#define ROTL(DEST, SRC, SHIFT) \
+{ \
+ (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \
+ (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \
+ (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \
+ (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \
+}
+
+#define FL(XL, XR, KL, KR) \
+{ \
+ (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \
+ (XL) = ((XR) | (KR)) ^ (XL); \
+}
+
+#define FLInv(YL, YR, KL, KR) \
+{ \
+ (YL) = ((YR) | (KR)) ^ (YL); \
+ (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \
+}
+
+#define SHIFT_AND_PLACE(INDEX, OFFSET) \
+{ \
+ TK[0] = KC[(OFFSET) * 4 + 0]; \
+ TK[1] = KC[(OFFSET) * 4 + 1]; \
+ TK[2] = KC[(OFFSET) * 4 + 2]; \
+ TK[3] = KC[(OFFSET) * 4 + 3]; \
+ \
+ for( i = 1; i <= 4; i++ ) \
+ if( shifts[(INDEX)][(OFFSET)][i -1] ) \
+ ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \
+ \
+ for( i = 0; i < 20; i++ ) \
+ if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \
+ RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \
+ } \
+}
+
+static void camellia_feistel( const uint32_t x[2], const uint32_t k[2],
+ uint32_t z[2])
+{
+ uint32_t I0, I1;
+ I0 = x[0] ^ k[0];
+ I1 = x[1] ^ k[1];
+
+ I0 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) |
+ ((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) |
+ ((uint32_t) SBOX3((I0 >> 8) & 0xFF) << 8) |
+ ((uint32_t) SBOX4((I0 ) & 0xFF) );
+ I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) |
+ ((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) |
+ ((uint32_t) SBOX4((I1 >> 8) & 0xFF) << 8) |
+ ((uint32_t) SBOX1((I1 ) & 0xFF) );
+
+ I0 ^= (I1 << 8) | (I1 >> 24);
+ I1 ^= (I0 << 16) | (I0 >> 16);
+ I0 ^= (I1 >> 8) | (I1 << 24);
+ I1 ^= (I0 >> 8) | (I0 << 24);
+
+ z[0] ^= I1;
+ z[1] ^= I0;
+}
+
+void mbedcrypto_camellia_init( mbedcrypto_camellia_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_camellia_context ) );
+}
+
+void mbedcrypto_camellia_free( mbedcrypto_camellia_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_camellia_context ) );
+}
+
+/*
+ * Camellia key schedule (encryption)
+ */
+int mbedcrypto_camellia_setkey_enc( mbedcrypto_camellia_context *ctx, const unsigned char *key,
+ unsigned int keybits )
+{
+ int idx;
+ size_t i;
+ uint32_t *RK;
+ unsigned char t[64];
+ uint32_t SIGMA[6][2];
+ uint32_t KC[16];
+ uint32_t TK[20];
+
+ RK = ctx->rk;
+
+ memset( t, 0, 64 );
+ memset( RK, 0, sizeof(ctx->rk) );
+
+ switch( keybits )
+ {
+ case 128: ctx->nr = 3; idx = 0; break;
+ case 192:
+ case 256: ctx->nr = 4; idx = 1; break;
+ default : return( MBEDCRYPTO_ERR_CAMELLIA_INVALID_KEY_LENGTH );
+ }
+
+ for( i = 0; i < keybits / 8; ++i )
+ t[i] = key[i];
+
+ if( keybits == 192 ) {
+ for( i = 0; i < 8; i++ )
+ t[24 + i] = ~t[16 + i];
+ }
+
+ /*
+ * Prepare SIGMA values
+ */
+ for( i = 0; i < 6; i++ ) {
+ GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 );
+ GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 );
+ }
+
+ /*
+ * Key storage in KC
+ * Order: KL, KR, KA, KB
+ */
+ memset( KC, 0, sizeof(KC) );
+
+ /* Store KL, KR */
+ for( i = 0; i < 8; i++ )
+ GET_UINT32_BE( KC[i], t, i * 4 );
+
+ /* Generate KA */
+ for( i = 0; i < 4; ++i )
+ KC[8 + i] = KC[i] ^ KC[4 + i];
+
+ camellia_feistel( KC + 8, SIGMA[0], KC + 10 );
+ camellia_feistel( KC + 10, SIGMA[1], KC + 8 );
+
+ for( i = 0; i < 4; ++i )
+ KC[8 + i] ^= KC[i];
+
+ camellia_feistel( KC + 8, SIGMA[2], KC + 10 );
+ camellia_feistel( KC + 10, SIGMA[3], KC + 8 );
+
+ if( keybits > 128 ) {
+ /* Generate KB */
+ for( i = 0; i < 4; ++i )
+ KC[12 + i] = KC[4 + i] ^ KC[8 + i];
+
+ camellia_feistel( KC + 12, SIGMA[4], KC + 14 );
+ camellia_feistel( KC + 14, SIGMA[5], KC + 12 );
+ }
+
+ /*
+ * Generating subkeys
+ */
+
+ /* Manipulating KL */
+ SHIFT_AND_PLACE( idx, 0 );
+
+ /* Manipulating KR */
+ if( keybits > 128 ) {
+ SHIFT_AND_PLACE( idx, 1 );
+ }
+
+ /* Manipulating KA */
+ SHIFT_AND_PLACE( idx, 2 );
+
+ /* Manipulating KB */
+ if( keybits > 128 ) {
+ SHIFT_AND_PLACE( idx, 3 );
+ }
+
+ /* Do transpositions */
+ for( i = 0; i < 20; i++ ) {
+ if( transposes[idx][i] != -1 ) {
+ RK[32 + 12 * idx + i] = RK[transposes[idx][i]];
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Camellia key schedule (decryption)
+ */
+int mbedcrypto_camellia_setkey_dec( mbedcrypto_camellia_context *ctx, const unsigned char *key,
+ unsigned int keybits )
+{
+ int idx, ret;
+ size_t i;
+ mbedcrypto_camellia_context cty;
+ uint32_t *RK;
+ uint32_t *SK;
+
+ mbedcrypto_camellia_init( &cty );
+
+ /* Also checks keybits */
+ if( ( ret = mbedcrypto_camellia_setkey_enc( &cty, key, keybits ) ) != 0 )
+ goto exit;
+
+ ctx->nr = cty.nr;
+ idx = ( ctx->nr == 4 );
+
+ RK = ctx->rk;
+ SK = cty.rk + 24 * 2 + 8 * idx * 2;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+ for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 )
+ {
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ }
+
+ SK -= 2;
+
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+ *RK++ = *SK++;
+
+exit:
+ mbedcrypto_camellia_free( &cty );
+
+ return( ret );
+}
+
+/*
+ * Camellia-ECB block encryption/decryption
+ */
+int mbedcrypto_camellia_crypt_ecb( mbedcrypto_camellia_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int NR;
+ uint32_t *RK, X[4];
+
+ ( (void) mode );
+
+ NR = ctx->nr;
+ RK = ctx->rk;
+
+ GET_UINT32_BE( X[0], input, 0 );
+ GET_UINT32_BE( X[1], input, 4 );
+ GET_UINT32_BE( X[2], input, 8 );
+ GET_UINT32_BE( X[3], input, 12 );
+
+ X[0] ^= *RK++;
+ X[1] ^= *RK++;
+ X[2] ^= *RK++;
+ X[3] ^= *RK++;
+
+ while( NR ) {
+ --NR;
+ camellia_feistel( X, RK, X + 2 );
+ RK += 2;
+ camellia_feistel( X + 2, RK, X );
+ RK += 2;
+ camellia_feistel( X, RK, X + 2 );
+ RK += 2;
+ camellia_feistel( X + 2, RK, X );
+ RK += 2;
+ camellia_feistel( X, RK, X + 2 );
+ RK += 2;
+ camellia_feistel( X + 2, RK, X );
+ RK += 2;
+
+ if( NR ) {
+ FL(X[0], X[1], RK[0], RK[1]);
+ RK += 2;
+ FLInv(X[2], X[3], RK[0], RK[1]);
+ RK += 2;
+ }
+ }
+
+ X[2] ^= *RK++;
+ X[3] ^= *RK++;
+ X[0] ^= *RK++;
+ X[1] ^= *RK++;
+
+ PUT_UINT32_BE( X[2], output, 0 );
+ PUT_UINT32_BE( X[3], output, 4 );
+ PUT_UINT32_BE( X[0], output, 8 );
+ PUT_UINT32_BE( X[1], output, 12 );
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/*
+ * Camellia-CBC buffer encryption/decryption
+ */
+int mbedcrypto_camellia_crypt_cbc( mbedcrypto_camellia_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[16];
+
+ if( length % 16 )
+ return( MBEDCRYPTO_ERR_CAMELLIA_INVALID_INPUT_LENGTH );
+
+ if( mode == MBEDCRYPTO_CAMELLIA_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 16 );
+ mbedcrypto_camellia_crypt_ecb( ctx, mode, input, output );
+
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 16; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ mbedcrypto_camellia_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, 16 );
+
+ input += 16;
+ output += 16;
+ length -= 16;
+ }
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+/*
+ * Camellia-CFB128 buffer encryption/decryption
+ */
+int mbedcrypto_camellia_crypt_cfb128( mbedcrypto_camellia_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c;
+ size_t n = *iv_off;
+
+ if( mode == MBEDCRYPTO_CAMELLIA_DECRYPT )
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ mbedcrypto_camellia_crypt_ecb( ctx, MBEDCRYPTO_CAMELLIA_ENCRYPT, iv, iv );
+
+ c = *input++;
+ *output++ = (unsigned char)( c ^ iv[n] );
+ iv[n] = (unsigned char) c;
+
+ n = ( n + 1 ) & 0x0F;
+ }
+ }
+ else
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ mbedcrypto_camellia_crypt_ecb( ctx, MBEDCRYPTO_CAMELLIA_ENCRYPT, iv, iv );
+
+ iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+ n = ( n + 1 ) & 0x0F;
+ }
+ }
+
+ *iv_off = n;
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/*
+ * Camellia-CTR buffer encryption/decryption
+ */
+int mbedcrypto_camellia_crypt_ctr( mbedcrypto_camellia_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c, i;
+ size_t n = *nc_off;
+
+ while( length-- )
+ {
+ if( n == 0 ) {
+ mbedcrypto_camellia_crypt_ecb( ctx, MBEDCRYPTO_CAMELLIA_ENCRYPT, nonce_counter,
+ stream_block );
+
+ for( i = 16; i > 0; i-- )
+ if( ++nonce_counter[i - 1] != 0 )
+ break;
+ }
+ c = *input++;
+ *output++ = (unsigned char)( c ^ stream_block[n] );
+
+ n = ( n + 1 ) & 0x0F;
+ }
+
+ *nc_off = n;
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+#endif /* !MBEDCRYPTO_CAMELLIA_ALT */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+/*
+ * Camellia test vectors from:
+ *
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html:
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt
+ * (For each bitlength: Key 0, Nr 39)
+ */
+#define CAMELLIA_TESTS_ECB 2
+
+static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] =
+{
+ {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+ {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+ {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ },
+};
+
+static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] =
+{
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] =
+{
+ {
+ { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+ 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
+ { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE,
+ 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 }
+ },
+ {
+ { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+ 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
+ { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9,
+ 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 }
+ },
+ {
+ { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+ 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
+ { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C,
+ 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 }
+ }
+};
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+#define CAMELLIA_TESTS_CBC 3
+
+static const unsigned char camellia_test_cbc_key[3][32] =
+{
+ { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
+ ,
+ { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+ 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+ 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }
+ ,
+ { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char camellia_test_cbc_iv[16] =
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }
+;
+
+static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] =
+{
+ { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A },
+ { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 },
+ { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF }
+
+};
+
+static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] =
+{
+ {
+ { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0,
+ 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB },
+ { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78,
+ 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 },
+ { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B,
+ 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 }
+ },
+ {
+ { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2,
+ 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 },
+ { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42,
+ 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 },
+ { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8,
+ 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 }
+ },
+ {
+ { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A,
+ 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA },
+ { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40,
+ 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 },
+ { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA,
+ 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 }
+ }
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+/*
+ * Camellia-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc5528.html
+ */
+
+static const unsigned char camellia_test_ctr_key[3][16] =
+{
+ { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+ 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+ { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+ 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+ { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+ 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char camellia_test_ctr_nonce_counter[3][16] =
+{
+ { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+ 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+ { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+ 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char camellia_test_ctr_pt[3][48] =
+{
+ { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+ 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char camellia_test_ctr_ct[3][48] =
+{
+ { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A,
+ 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F },
+ { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4,
+ 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44,
+ 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7,
+ 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 },
+ { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88,
+ 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73,
+ 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1,
+ 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD,
+ 0xDF, 0x50, 0x86, 0x96 }
+};
+
+static const int camellia_test_ctr_len[3] =
+ { 16, 32, 36 };
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_camellia_self_test( int verbose )
+{
+ int i, j, u, v;
+ unsigned char key[32];
+ unsigned char buf[64];
+ unsigned char src[16];
+ unsigned char dst[16];
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ unsigned char iv[16];
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ size_t offset, len;
+ unsigned char nonce_counter[16];
+ unsigned char stream_block[16];
+#endif
+
+ mbedcrypto_camellia_context ctx;
+
+ memset( key, 0, 32 );
+
+ for( j = 0; j < 6; j++ ) {
+ u = j >> 1;
+ v = j & 1;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
+ (v == MBEDCRYPTO_CAMELLIA_DECRYPT) ? "dec" : "enc");
+
+ for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
+ memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u );
+
+ if( v == MBEDCRYPTO_CAMELLIA_DECRYPT ) {
+ mbedcrypto_camellia_setkey_dec( &ctx, key, 128 + u * 64 );
+ memcpy( src, camellia_test_ecb_cipher[u][i], 16 );
+ memcpy( dst, camellia_test_ecb_plain[i], 16 );
+ } else { /* MBEDCRYPTO_CAMELLIA_ENCRYPT */
+ mbedcrypto_camellia_setkey_enc( &ctx, key, 128 + u * 64 );
+ memcpy( src, camellia_test_ecb_plain[i], 16 );
+ memcpy( dst, camellia_test_ecb_cipher[u][i], 16 );
+ }
+
+ mbedcrypto_camellia_crypt_ecb( &ctx, v, src, buf );
+
+ if( memcmp( buf, dst, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ /*
+ * CBC mode
+ */
+ for( j = 0; j < 6; j++ )
+ {
+ u = j >> 1;
+ v = j & 1;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
+ ( v == MBEDCRYPTO_CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( src, camellia_test_cbc_iv, 16 );
+ memcpy( dst, camellia_test_cbc_iv, 16 );
+ memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u );
+
+ if( v == MBEDCRYPTO_CAMELLIA_DECRYPT ) {
+ mbedcrypto_camellia_setkey_dec( &ctx, key, 128 + u * 64 );
+ } else {
+ mbedcrypto_camellia_setkey_enc( &ctx, key, 128 + u * 64 );
+ }
+
+ for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
+
+ if( v == MBEDCRYPTO_CAMELLIA_DECRYPT ) {
+ memcpy( iv , src, 16 );
+ memcpy( src, camellia_test_cbc_cipher[u][i], 16 );
+ memcpy( dst, camellia_test_cbc_plain[i], 16 );
+ } else { /* MBEDCRYPTO_CAMELLIA_ENCRYPT */
+ memcpy( iv , dst, 16 );
+ memcpy( src, camellia_test_cbc_plain[i], 16 );
+ memcpy( dst, camellia_test_cbc_cipher[u][i], 16 );
+ }
+
+ mbedcrypto_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf );
+
+ if( memcmp( buf, dst, 16 ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ /*
+ * CTR mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " CAMELLIA-CTR-128 (%s): ",
+ ( v == MBEDCRYPTO_CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 );
+ memcpy( key, camellia_test_ctr_key[u], 16 );
+
+ offset = 0;
+ mbedcrypto_camellia_setkey_enc( &ctx, key, 128 );
+
+ if( v == MBEDCRYPTO_CAMELLIA_DECRYPT )
+ {
+ len = camellia_test_ctr_len[u];
+ memcpy( buf, camellia_test_ctr_ct[u], len );
+
+ mbedcrypto_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+ buf, buf );
+
+ if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+ else
+ {
+ len = camellia_test_ctr_len[u];
+ memcpy( buf, camellia_test_ctr_pt[u], len );
+
+ mbedcrypto_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+ buf, buf );
+
+ if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( 1 );
+ }
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+ return( 0 );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_CAMELLIA_C */
diff --git a/library/ccm.c b/library/ccm.c
new file mode 100644
index 0000000..d39387f
--- /dev/null
+++ b/library/ccm.c
@@ -0,0 +1,463 @@
+/*
+ * NIST SP800-38C compliant CCM implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * Definition of CCM:
+ * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
+ * RFC 3610 "Counter with CBC-MAC (CCM)"
+ *
+ * Related:
+ * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_CCM_C)
+
+#include "mbedcrypto/ccm.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST) && defined(MBEDCRYPTO_AES_C)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST && MBEDCRYPTO_AES_C */
+
+#if !defined(MBEDCRYPTO_CCM_ALT)
+
+#define CCM_ENCRYPT 0
+#define CCM_DECRYPT 1
+
+/*
+ * Initialize context
+ */
+void mbedcrypto_ccm_init( mbedcrypto_ccm_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_ccm_context ) );
+}
+
+int mbedcrypto_ccm_setkey( mbedcrypto_ccm_context *ctx,
+ mbedcrypto_cipher_id_t cipher,
+ const unsigned char *key,
+ unsigned int keybits )
+{
+ int ret;
+ const mbedcrypto_cipher_info_t *cipher_info;
+
+ cipher_info = mbedcrypto_cipher_info_from_values( cipher, keybits, MBEDCRYPTO_MODE_ECB );
+ if( cipher_info == NULL )
+ return( MBEDCRYPTO_ERR_CCM_BAD_INPUT );
+
+ if( cipher_info->block_size != 16 )
+ return( MBEDCRYPTO_ERR_CCM_BAD_INPUT );
+
+ mbedcrypto_cipher_free( &ctx->cipher_ctx );
+
+ if( ( ret = mbedcrypto_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_cipher_setkey( &ctx->cipher_ctx, key, keybits,
+ MBEDCRYPTO_ENCRYPT ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Free context
+ */
+void mbedcrypto_ccm_free( mbedcrypto_ccm_context *ctx )
+{
+ mbedcrypto_cipher_free( &ctx->cipher_ctx );
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_ccm_context ) );
+}
+
+/*
+ * Macros for common operations.
+ * Results in smaller compiled code than static inline functions.
+ */
+
+/*
+ * Update the CBC-MAC state in y using a block in b
+ * (Always using b as the source helps the compiler optimise a bit better.)
+ */
+#define UPDATE_CBC_MAC \
+ for( i = 0; i < 16; i++ ) \
+ y[i] ^= b[i]; \
+ \
+ if( ( ret = mbedcrypto_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
+ return( ret );
+
+/*
+ * Encrypt or decrypt a partial block with CTR
+ * Warning: using b for temporary storage! src and dst must not be b!
+ * This avoids allocating one more 16 bytes buffer while allowing src == dst.
+ */
+#define CTR_CRYPT( dst, src, len ) \
+ if( ( ret = mbedcrypto_cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \
+ return( ret ); \
+ \
+ for( i = 0; i < len; i++ ) \
+ dst[i] = src[i] ^ b[i];
+
+/*
+ * Authenticated encryption or decryption
+ */
+static int ccm_auth_crypt( mbedcrypto_ccm_context *ctx, int mode, size_t length,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *add, size_t add_len,
+ const unsigned char *input, unsigned char *output,
+ unsigned char *tag, size_t tag_len )
+{
+ int ret;
+ unsigned char i;
+ unsigned char q;
+ size_t len_left, olen;
+ unsigned char b[16];
+ unsigned char y[16];
+ unsigned char ctr[16];
+ const unsigned char *src;
+ unsigned char *dst;
+
+ /*
+ * Check length requirements: SP800-38C A.1
+ * Additional requirement: a < 2^16 - 2^8 to simplify the code.
+ * 'length' checked later (when writing it to the first block)
+ */
+ if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
+ return( MBEDCRYPTO_ERR_CCM_BAD_INPUT );
+
+ /* Also implies q is within bounds */
+ if( iv_len < 7 || iv_len > 13 )
+ return( MBEDCRYPTO_ERR_CCM_BAD_INPUT );
+
+ if( add_len > 0xFF00 )
+ return( MBEDCRYPTO_ERR_CCM_BAD_INPUT );
+
+ q = 16 - 1 - (unsigned char) iv_len;
+
+ /*
+ * First block B_0:
+ * 0 .. 0 flags
+ * 1 .. iv_len nonce (aka iv)
+ * iv_len+1 .. 15 length
+ *
+ * With flags as (bits):
+ * 7 0
+ * 6 add present?
+ * 5 .. 3 (t - 2) / 2
+ * 2 .. 0 q - 1
+ */
+ b[0] = 0;
+ b[0] |= ( add_len > 0 ) << 6;
+ b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
+ b[0] |= q - 1;
+
+ memcpy( b + 1, iv, iv_len );
+
+ for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
+ b[15-i] = (unsigned char)( len_left & 0xFF );
+
+ if( len_left > 0 )
+ return( MBEDCRYPTO_ERR_CCM_BAD_INPUT );
+
+
+ /* Start CBC-MAC with first block */
+ memset( y, 0, 16 );
+ UPDATE_CBC_MAC;
+
+ /*
+ * If there is additional data, update CBC-MAC with
+ * add_len, add, 0 (padding to a block boundary)
+ */
+ if( add_len > 0 )
+ {
+ size_t use_len;
+ len_left = add_len;
+ src = add;
+
+ memset( b, 0, 16 );
+ b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF );
+ b[1] = (unsigned char)( ( add_len ) & 0xFF );
+
+ use_len = len_left < 16 - 2 ? len_left : 16 - 2;
+ memcpy( b + 2, src, use_len );
+ len_left -= use_len;
+ src += use_len;
+
+ UPDATE_CBC_MAC;
+
+ while( len_left > 0 )
+ {
+ use_len = len_left > 16 ? 16 : len_left;
+
+ memset( b, 0, 16 );
+ memcpy( b, src, use_len );
+ UPDATE_CBC_MAC;
+
+ len_left -= use_len;
+ src += use_len;
+ }
+ }
+
+ /*
+ * Prepare counter block for encryption:
+ * 0 .. 0 flags
+ * 1 .. iv_len nonce (aka iv)
+ * iv_len+1 .. 15 counter (initially 1)
+ *
+ * With flags as (bits):
+ * 7 .. 3 0
+ * 2 .. 0 q - 1
+ */
+ ctr[0] = q - 1;
+ memcpy( ctr + 1, iv, iv_len );
+ memset( ctr + 1 + iv_len, 0, q );
+ ctr[15] = 1;
+
+ /*
+ * Authenticate and {en,de}crypt the message.
+ *
+ * The only difference between encryption and decryption is
+ * the respective order of authentication and {en,de}cryption.
+ */
+ len_left = length;
+ src = input;
+ dst = output;
+
+ while( len_left > 0 )
+ {
+ size_t use_len = len_left > 16 ? 16 : len_left;
+
+ if( mode == CCM_ENCRYPT )
+ {
+ memset( b, 0, 16 );
+ memcpy( b, src, use_len );
+ UPDATE_CBC_MAC;
+ }
+
+ CTR_CRYPT( dst, src, use_len );
+
+ if( mode == CCM_DECRYPT )
+ {
+ memset( b, 0, 16 );
+ memcpy( b, dst, use_len );
+ UPDATE_CBC_MAC;
+ }
+
+ dst += use_len;
+ src += use_len;
+ len_left -= use_len;
+
+ /*
+ * Increment counter.
+ * No need to check for overflow thanks to the length check above.
+ */
+ for( i = 0; i < q; i++ )
+ if( ++ctr[15-i] != 0 )
+ break;
+ }
+
+ /*
+ * Authentication: reset counter and crypt/mask internal tag
+ */
+ for( i = 0; i < q; i++ )
+ ctr[15-i] = 0;
+
+ CTR_CRYPT( y, y, 16 );
+ memcpy( tag, y, tag_len );
+
+ return( 0 );
+}
+
+/*
+ * Authenticated encryption
+ */
+int mbedcrypto_ccm_encrypt_and_tag( mbedcrypto_ccm_context *ctx, size_t length,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *add, size_t add_len,
+ const unsigned char *input, unsigned char *output,
+ unsigned char *tag, size_t tag_len )
+{
+ return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
+ add, add_len, input, output, tag, tag_len ) );
+}
+
+/*
+ * Authenticated decryption
+ */
+int mbedcrypto_ccm_auth_decrypt( mbedcrypto_ccm_context *ctx, size_t length,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *add, size_t add_len,
+ const unsigned char *input, unsigned char *output,
+ const unsigned char *tag, size_t tag_len )
+{
+ int ret;
+ unsigned char check_tag[16];
+ unsigned char i;
+ int diff;
+
+ if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
+ iv, iv_len, add, add_len,
+ input, output, check_tag, tag_len ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* Check tag in "constant-time" */
+ for( diff = 0, i = 0; i < tag_len; i++ )
+ diff |= tag[i] ^ check_tag[i];
+
+ if( diff != 0 )
+ {
+ mbedcrypto_platform_zeroize( output, length );
+ return( MBEDCRYPTO_ERR_CCM_AUTH_FAILED );
+ }
+
+ return( 0 );
+}
+
+#endif /* !MBEDCRYPTO_CCM_ALT */
+
+#if defined(MBEDCRYPTO_SELF_TEST) && defined(MBEDCRYPTO_AES_C)
+/*
+ * Examples 1 to 3 from SP800-38C Appendix C
+ */
+
+#define NB_TESTS 3
+
+/*
+ * The data is the same for all tests, only the used length changes
+ */
+static const unsigned char key[] = {
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
+};
+
+static const unsigned char iv[] = {
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b
+};
+
+static const unsigned char ad[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13
+};
+
+static const unsigned char msg[] = {
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+};
+
+static const size_t iv_len [NB_TESTS] = { 7, 8, 12 };
+static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
+static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
+static const size_t tag_len[NB_TESTS] = { 4, 6, 8 };
+
+static const unsigned char res[NB_TESTS][32] = {
+ { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
+ { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
+ 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
+ 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
+ { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
+ 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
+ 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
+ 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
+};
+
+int mbedcrypto_ccm_self_test( int verbose )
+{
+ mbedcrypto_ccm_context ctx;
+ unsigned char out[32];
+ size_t i;
+ int ret;
+
+ mbedcrypto_ccm_init( &ctx );
+
+ if( mbedcrypto_ccm_setkey( &ctx, MBEDCRYPTO_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " CCM: setup failed" );
+
+ return( 1 );
+ }
+
+ for( i = 0; i < NB_TESTS; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " CCM-AES #%u: ", (unsigned int) i + 1 );
+
+ ret = mbedcrypto_ccm_encrypt_and_tag( &ctx, msg_len[i],
+ iv, iv_len[i], ad, add_len[i],
+ msg, out,
+ out + msg_len[i], tag_len[i] );
+
+ if( ret != 0 ||
+ memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ ret = mbedcrypto_ccm_auth_decrypt( &ctx, msg_len[i],
+ iv, iv_len[i], ad, add_len[i],
+ res[i], out,
+ res[i] + msg_len[i], tag_len[i] );
+
+ if( ret != 0 ||
+ memcmp( out, msg, msg_len[i] ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ mbedcrypto_ccm_free( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ return( 0 );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST && MBEDCRYPTO_AES_C */
+
+#endif /* MBEDCRYPTO_CCM_C */
diff --git a/library/cipher.c b/library/cipher.c
new file mode 100644
index 0000000..61ee930
--- /dev/null
+++ b/library/cipher.c
@@ -0,0 +1,924 @@
+/**
+ * \file cipher.c
+ *
+ * \brief Generic cipher wrapper for Mbed Crypto
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_C)
+
+#include "mbedcrypto/cipher.h"
+#include "mbedcrypto/cipher_internal.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(MBEDCRYPTO_GCM_C)
+#include "mbedcrypto/gcm.h"
+#endif
+
+#if defined(MBEDCRYPTO_CCM_C)
+#include "mbedcrypto/ccm.h"
+#endif
+
+#if defined(MBEDCRYPTO_CMAC_C)
+#include "mbedcrypto/cmac.h"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#if defined(MBEDCRYPTO_ARC4_C) || defined(MBEDCRYPTO_CIPHER_NULL_CIPHER)
+#define MBEDCRYPTO_CIPHER_MODE_STREAM
+#endif
+
+static int supported_init = 0;
+
+const int *mbedcrypto_cipher_list( void )
+{
+ const mbedcrypto_cipher_definition_t *def;
+ int *type;
+
+ if( ! supported_init )
+ {
+ def = mbedcrypto_cipher_definitions;
+ type = mbedcrypto_cipher_supported;
+
+ while( def->type != 0 )
+ *type++ = (*def++).type;
+
+ *type = 0;
+
+ supported_init = 1;
+ }
+
+ return( mbedcrypto_cipher_supported );
+}
+
+const mbedcrypto_cipher_info_t *mbedcrypto_cipher_info_from_type( const mbedcrypto_cipher_type_t cipher_type )
+{
+ const mbedcrypto_cipher_definition_t *def;
+
+ for( def = mbedcrypto_cipher_definitions; def->info != NULL; def++ )
+ if( def->type == cipher_type )
+ return( def->info );
+
+ return( NULL );
+}
+
+const mbedcrypto_cipher_info_t *mbedcrypto_cipher_info_from_string( const char *cipher_name )
+{
+ const mbedcrypto_cipher_definition_t *def;
+
+ if( NULL == cipher_name )
+ return( NULL );
+
+ for( def = mbedcrypto_cipher_definitions; def->info != NULL; def++ )
+ if( ! strcmp( def->info->name, cipher_name ) )
+ return( def->info );
+
+ return( NULL );
+}
+
+const mbedcrypto_cipher_info_t *mbedcrypto_cipher_info_from_values( const mbedcrypto_cipher_id_t cipher_id,
+ int key_bitlen,
+ const mbedcrypto_cipher_mode_t mode )
+{
+ const mbedcrypto_cipher_definition_t *def;
+
+ for( def = mbedcrypto_cipher_definitions; def->info != NULL; def++ )
+ if( def->info->base->cipher == cipher_id &&
+ def->info->key_bitlen == (unsigned) key_bitlen &&
+ def->info->mode == mode )
+ return( def->info );
+
+ return( NULL );
+}
+
+void mbedcrypto_cipher_init( mbedcrypto_cipher_context_t *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_cipher_context_t ) );
+}
+
+void mbedcrypto_cipher_free( mbedcrypto_cipher_context_t *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+#if defined(MBEDCRYPTO_CMAC_C)
+ if( ctx->cmac_ctx )
+ {
+ mbedcrypto_platform_zeroize( ctx->cmac_ctx,
+ sizeof( mbedcrypto_cmac_context_t ) );
+ mbedcrypto_free( ctx->cmac_ctx );
+ }
+#endif
+
+ if( ctx->cipher_ctx )
+ ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
+
+ mbedcrypto_platform_zeroize( ctx, sizeof(mbedcrypto_cipher_context_t) );
+}
+
+int mbedcrypto_cipher_setup( mbedcrypto_cipher_context_t *ctx, const mbedcrypto_cipher_info_t *cipher_info )
+{
+ if( NULL == cipher_info || NULL == ctx )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ memset( ctx, 0, sizeof( mbedcrypto_cipher_context_t ) );
+
+ if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
+ return( MBEDCRYPTO_ERR_CIPHER_ALLOC_FAILED );
+
+ ctx->cipher_info = cipher_info;
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_WITH_PADDING)
+ /*
+ * Ignore possible errors caused by a cipher mode that doesn't use padding
+ */
+#if defined(MBEDCRYPTO_CIPHER_PADDING_PKCS7)
+ (void) mbedcrypto_cipher_set_padding_mode( ctx, MBEDCRYPTO_PADDING_PKCS7 );
+#else
+ (void) mbedcrypto_cipher_set_padding_mode( ctx, MBEDCRYPTO_PADDING_NONE );
+#endif
+#endif /* MBEDCRYPTO_CIPHER_MODE_WITH_PADDING */
+
+ return( 0 );
+}
+
+int mbedcrypto_cipher_setkey( mbedcrypto_cipher_context_t *ctx, const unsigned char *key,
+ int key_bitlen, const mbedcrypto_operation_t operation )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( ( ctx->cipher_info->flags & MBEDCRYPTO_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
+ (int) ctx->cipher_info->key_bitlen != key_bitlen )
+ {
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ ctx->key_bitlen = key_bitlen;
+ ctx->operation = operation;
+
+ /*
+ * For CFB and CTR mode always use the encryption key schedule
+ */
+ if( MBEDCRYPTO_ENCRYPT == operation ||
+ MBEDCRYPTO_MODE_CFB == ctx->cipher_info->mode ||
+ MBEDCRYPTO_MODE_CTR == ctx->cipher_info->mode )
+ {
+ return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
+ ctx->key_bitlen );
+ }
+
+ if( MBEDCRYPTO_DECRYPT == operation )
+ return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
+ ctx->key_bitlen );
+
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+}
+
+int mbedcrypto_cipher_set_iv( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len )
+{
+ size_t actual_iv_size;
+
+ if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ /* avoid buffer overflow in ctx->iv */
+ if( iv_len > MBEDCRYPTO_MAX_IV_LENGTH )
+ return( MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE );
+
+ if( ( ctx->cipher_info->flags & MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN ) != 0 )
+ actual_iv_size = iv_len;
+ else
+ {
+ actual_iv_size = ctx->cipher_info->iv_size;
+
+ /* avoid reading past the end of input buffer */
+ if( actual_iv_size > iv_len )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ memcpy( ctx->iv, iv, actual_iv_size );
+ ctx->iv_size = actual_iv_size;
+
+ return( 0 );
+}
+
+int mbedcrypto_cipher_reset( mbedcrypto_cipher_context_t *ctx )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ ctx->unprocessed_len = 0;
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_GCM_C)
+int mbedcrypto_cipher_update_ad( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *ad, size_t ad_len )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( MBEDCRYPTO_MODE_GCM == ctx->cipher_info->mode )
+ {
+ return mbedcrypto_gcm_starts( (mbedcrypto_gcm_context *) ctx->cipher_ctx, ctx->operation,
+ ctx->iv, ctx->iv_size, ad, ad_len );
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_GCM_C */
+
+int mbedcrypto_cipher_update( mbedcrypto_cipher_context_t *ctx, const unsigned char *input,
+ size_t ilen, unsigned char *output, size_t *olen )
+{
+ int ret;
+ size_t block_size = 0;
+
+ if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
+ {
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ *olen = 0;
+ block_size = mbedcrypto_cipher_get_block_size( ctx );
+
+ if( ctx->cipher_info->mode == MBEDCRYPTO_MODE_ECB )
+ {
+ if( ilen != block_size )
+ return( MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+
+ *olen = ilen;
+
+ if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
+ ctx->operation, input, output ) ) )
+ {
+ return( ret );
+ }
+
+ return( 0 );
+ }
+
+#if defined(MBEDCRYPTO_GCM_C)
+ if( ctx->cipher_info->mode == MBEDCRYPTO_MODE_GCM )
+ {
+ *olen = ilen;
+ return mbedcrypto_gcm_update( (mbedcrypto_gcm_context *) ctx->cipher_ctx, ilen, input,
+ output );
+ }
+#endif
+
+ if ( 0 == block_size )
+ {
+ return MBEDCRYPTO_ERR_CIPHER_INVALID_CONTEXT;
+ }
+
+ if( input == output &&
+ ( ctx->unprocessed_len != 0 || ilen % block_size ) )
+ {
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ if( ctx->cipher_info->mode == MBEDCRYPTO_MODE_CBC )
+ {
+ size_t copy_len = 0;
+
+ /*
+ * If there is not enough data for a full block, cache it.
+ */
+ if( ( ctx->operation == MBEDCRYPTO_DECRYPT && NULL != ctx->add_padding &&
+ ilen <= block_size - ctx->unprocessed_len ) ||
+ ( ctx->operation == MBEDCRYPTO_DECRYPT && NULL == ctx->add_padding &&
+ ilen < block_size - ctx->unprocessed_len ) ||
+ ( ctx->operation == MBEDCRYPTO_ENCRYPT &&
+ ilen < block_size - ctx->unprocessed_len ) )
+ {
+ memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+ ilen );
+
+ ctx->unprocessed_len += ilen;
+ return( 0 );
+ }
+
+ /*
+ * Process cached data first
+ */
+ if( 0 != ctx->unprocessed_len )
+ {
+ copy_len = block_size - ctx->unprocessed_len;
+
+ memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
+ copy_len );
+
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, block_size, ctx->iv,
+ ctx->unprocessed_data, output ) ) )
+ {
+ return( ret );
+ }
+
+ *olen += block_size;
+ output += block_size;
+ ctx->unprocessed_len = 0;
+
+ input += copy_len;
+ ilen -= copy_len;
+ }
+
+ /*
+ * Cache final, incomplete block
+ */
+ if( 0 != ilen )
+ {
+ if( 0 == block_size )
+ {
+ return MBEDCRYPTO_ERR_CIPHER_INVALID_CONTEXT;
+ }
+
+ /* Encryption: only cache partial blocks
+ * Decryption w/ padding: always keep at least one whole block
+ * Decryption w/o padding: only cache partial blocks
+ */
+ copy_len = ilen % block_size;
+ if( copy_len == 0 &&
+ ctx->operation == MBEDCRYPTO_DECRYPT &&
+ NULL != ctx->add_padding)
+ {
+ copy_len = block_size;
+ }
+
+ memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
+ copy_len );
+
+ ctx->unprocessed_len += copy_len;
+ ilen -= copy_len;
+ }
+
+ /*
+ * Process remaining full blocks
+ */
+ if( ilen )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, ilen, ctx->iv, input, output ) ) )
+ {
+ return( ret );
+ }
+
+ *olen += ilen;
+ }
+
+ return( 0 );
+ }
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ if( ctx->cipher_info->mode == MBEDCRYPTO_MODE_CFB )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
+ ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
+ input, output ) ) )
+ {
+ return( ret );
+ }
+
+ *olen = ilen;
+
+ return( 0 );
+ }
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ if( ctx->cipher_info->mode == MBEDCRYPTO_MODE_CTR )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
+ ilen, &ctx->unprocessed_len, ctx->iv,
+ ctx->unprocessed_data, input, output ) ) )
+ {
+ return( ret );
+ }
+
+ *olen = ilen;
+
+ return( 0 );
+ }
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ if( ctx->cipher_info->mode == MBEDCRYPTO_MODE_STREAM )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
+ ilen, input, output ) ) )
+ {
+ return( ret );
+ }
+
+ *olen = ilen;
+
+ return( 0 );
+ }
+#endif /* MBEDCRYPTO_CIPHER_MODE_STREAM */
+
+ return( MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_WITH_PADDING)
+#if defined(MBEDCRYPTO_CIPHER_PADDING_PKCS7)
+/*
+ * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
+ */
+static void add_pkcs_padding( unsigned char *output, size_t output_len,
+ size_t data_len )
+{
+ size_t padding_len = output_len - data_len;
+ unsigned char i;
+
+ for( i = 0; i < padding_len; i++ )
+ output[data_len + i] = (unsigned char) padding_len;
+}
+
+static int get_pkcs_padding( unsigned char *input, size_t input_len,
+ size_t *data_len )
+{
+ size_t i, pad_idx;
+ unsigned char padding_len, bad = 0;
+
+ if( NULL == input || NULL == data_len )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ padding_len = input[input_len - 1];
+ *data_len = input_len - padding_len;
+
+ /* Avoid logical || since it results in a branch */
+ bad |= padding_len > input_len;
+ bad |= padding_len == 0;
+
+ /* The number of bytes checked must be independent of padding_len,
+ * so pick input_len, which is usually 8 or 16 (one block) */
+ pad_idx = input_len - padding_len;
+ for( i = 0; i < input_len; i++ )
+ bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
+
+ return( MBEDCRYPTO_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
+}
+#endif /* MBEDCRYPTO_CIPHER_PADDING_PKCS7 */
+
+#if defined(MBEDCRYPTO_CIPHER_PADDING_ONE_AND_ZEROS)
+/*
+ * One and zeros padding: fill with 80 00 ... 00
+ */
+static void add_one_and_zeros_padding( unsigned char *output,
+ size_t output_len, size_t data_len )
+{
+ size_t padding_len = output_len - data_len;
+ unsigned char i = 0;
+
+ output[data_len] = 0x80;
+ for( i = 1; i < padding_len; i++ )
+ output[data_len + i] = 0x00;
+}
+
+static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
+ size_t *data_len )
+{
+ size_t i;
+ unsigned char done = 0, prev_done, bad;
+
+ if( NULL == input || NULL == data_len )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ bad = 0x80;
+ *data_len = 0;
+ for( i = input_len; i > 0; i-- )
+ {
+ prev_done = done;
+ done |= ( input[i - 1] != 0 );
+ *data_len |= ( i - 1 ) * ( done != prev_done );
+ bad ^= input[i - 1] * ( done != prev_done );
+ }
+
+ return( MBEDCRYPTO_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
+
+}
+#endif /* MBEDCRYPTO_CIPHER_PADDING_ONE_AND_ZEROS */
+
+#if defined(MBEDCRYPTO_CIPHER_PADDING_ZEROS_AND_LEN)
+/*
+ * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
+ */
+static void add_zeros_and_len_padding( unsigned char *output,
+ size_t output_len, size_t data_len )
+{
+ size_t padding_len = output_len - data_len;
+ unsigned char i = 0;
+
+ for( i = 1; i < padding_len; i++ )
+ output[data_len + i - 1] = 0x00;
+ output[output_len - 1] = (unsigned char) padding_len;
+}
+
+static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
+ size_t *data_len )
+{
+ size_t i, pad_idx;
+ unsigned char padding_len, bad = 0;
+
+ if( NULL == input || NULL == data_len )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ padding_len = input[input_len - 1];
+ *data_len = input_len - padding_len;
+
+ /* Avoid logical || since it results in a branch */
+ bad |= padding_len > input_len;
+ bad |= padding_len == 0;
+
+ /* The number of bytes checked must be independent of padding_len */
+ pad_idx = input_len - padding_len;
+ for( i = 0; i < input_len - 1; i++ )
+ bad |= input[i] * ( i >= pad_idx );
+
+ return( MBEDCRYPTO_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
+}
+#endif /* MBEDCRYPTO_CIPHER_PADDING_ZEROS_AND_LEN */
+
+#if defined(MBEDCRYPTO_CIPHER_PADDING_ZEROS)
+/*
+ * Zero padding: fill with 00 ... 00
+ */
+static void add_zeros_padding( unsigned char *output,
+ size_t output_len, size_t data_len )
+{
+ size_t i;
+
+ for( i = data_len; i < output_len; i++ )
+ output[i] = 0x00;
+}
+
+static int get_zeros_padding( unsigned char *input, size_t input_len,
+ size_t *data_len )
+{
+ size_t i;
+ unsigned char done = 0, prev_done;
+
+ if( NULL == input || NULL == data_len )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ *data_len = 0;
+ for( i = input_len; i > 0; i-- )
+ {
+ prev_done = done;
+ done |= ( input[i-1] != 0 );
+ *data_len |= i * ( done != prev_done );
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_PADDING_ZEROS */
+
+/*
+ * No padding: don't pad :)
+ *
+ * There is no add_padding function (check for NULL in mbedcrypto_cipher_finish)
+ * but a trivial get_padding function
+ */
+static int get_no_padding( unsigned char *input, size_t input_len,
+ size_t *data_len )
+{
+ if( NULL == input || NULL == data_len )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ *data_len = input_len;
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_WITH_PADDING */
+
+int mbedcrypto_cipher_finish( mbedcrypto_cipher_context_t *ctx,
+ unsigned char *output, size_t *olen )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ *olen = 0;
+
+ if( MBEDCRYPTO_MODE_CFB == ctx->cipher_info->mode ||
+ MBEDCRYPTO_MODE_CTR == ctx->cipher_info->mode ||
+ MBEDCRYPTO_MODE_GCM == ctx->cipher_info->mode ||
+ MBEDCRYPTO_MODE_STREAM == ctx->cipher_info->mode )
+ {
+ return( 0 );
+ }
+
+ if( MBEDCRYPTO_MODE_ECB == ctx->cipher_info->mode )
+ {
+ if( ctx->unprocessed_len != 0 )
+ return( MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+
+ return( 0 );
+ }
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ if( MBEDCRYPTO_MODE_CBC == ctx->cipher_info->mode )
+ {
+ int ret = 0;
+
+ if( MBEDCRYPTO_ENCRYPT == ctx->operation )
+ {
+ /* check for 'no padding' mode */
+ if( NULL == ctx->add_padding )
+ {
+ if( 0 != ctx->unprocessed_len )
+ return( MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+
+ return( 0 );
+ }
+
+ ctx->add_padding( ctx->unprocessed_data, mbedcrypto_cipher_get_iv_size( ctx ),
+ ctx->unprocessed_len );
+ }
+ else if( mbedcrypto_cipher_get_block_size( ctx ) != ctx->unprocessed_len )
+ {
+ /*
+ * For decrypt operations, expect a full block,
+ * or an empty block if no padding
+ */
+ if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
+ return( 0 );
+
+ return( MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+ }
+
+ /* cipher block */
+ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
+ ctx->operation, mbedcrypto_cipher_get_block_size( ctx ), ctx->iv,
+ ctx->unprocessed_data, output ) ) )
+ {
+ return( ret );
+ }
+
+ /* Set output size for decryption */
+ if( MBEDCRYPTO_DECRYPT == ctx->operation )
+ return ctx->get_padding( output, mbedcrypto_cipher_get_block_size( ctx ),
+ olen );
+
+ /* Set output size for encryption */
+ *olen = mbedcrypto_cipher_get_block_size( ctx );
+ return( 0 );
+ }
+#else
+ ((void) output);
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+ return( MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_WITH_PADDING)
+int mbedcrypto_cipher_set_padding_mode( mbedcrypto_cipher_context_t *ctx, mbedcrypto_cipher_padding_t mode )
+{
+ if( NULL == ctx ||
+ MBEDCRYPTO_MODE_CBC != ctx->cipher_info->mode )
+ {
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ switch( mode )
+ {
+#if defined(MBEDCRYPTO_CIPHER_PADDING_PKCS7)
+ case MBEDCRYPTO_PADDING_PKCS7:
+ ctx->add_padding = add_pkcs_padding;
+ ctx->get_padding = get_pkcs_padding;
+ break;
+#endif
+#if defined(MBEDCRYPTO_CIPHER_PADDING_ONE_AND_ZEROS)
+ case MBEDCRYPTO_PADDING_ONE_AND_ZEROS:
+ ctx->add_padding = add_one_and_zeros_padding;
+ ctx->get_padding = get_one_and_zeros_padding;
+ break;
+#endif
+#if defined(MBEDCRYPTO_CIPHER_PADDING_ZEROS_AND_LEN)
+ case MBEDCRYPTO_PADDING_ZEROS_AND_LEN:
+ ctx->add_padding = add_zeros_and_len_padding;
+ ctx->get_padding = get_zeros_and_len_padding;
+ break;
+#endif
+#if defined(MBEDCRYPTO_CIPHER_PADDING_ZEROS)
+ case MBEDCRYPTO_PADDING_ZEROS:
+ ctx->add_padding = add_zeros_padding;
+ ctx->get_padding = get_zeros_padding;
+ break;
+#endif
+ case MBEDCRYPTO_PADDING_NONE:
+ ctx->add_padding = NULL;
+ ctx->get_padding = get_no_padding;
+ break;
+
+ default:
+ return( MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_WITH_PADDING */
+
+#if defined(MBEDCRYPTO_GCM_C)
+int mbedcrypto_cipher_write_tag( mbedcrypto_cipher_context_t *ctx,
+ unsigned char *tag, size_t tag_len )
+{
+ if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( MBEDCRYPTO_ENCRYPT != ctx->operation )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( MBEDCRYPTO_MODE_GCM == ctx->cipher_info->mode )
+ return mbedcrypto_gcm_finish( (mbedcrypto_gcm_context *) ctx->cipher_ctx, tag, tag_len );
+
+ return( 0 );
+}
+
+int mbedcrypto_cipher_check_tag( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *tag, size_t tag_len )
+{
+ int ret;
+
+ if( NULL == ctx || NULL == ctx->cipher_info ||
+ MBEDCRYPTO_DECRYPT != ctx->operation )
+ {
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ if( MBEDCRYPTO_MODE_GCM == ctx->cipher_info->mode )
+ {
+ unsigned char check_tag[16];
+ size_t i;
+ int diff;
+
+ if( tag_len > sizeof( check_tag ) )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( 0 != ( ret = mbedcrypto_gcm_finish( (mbedcrypto_gcm_context *) ctx->cipher_ctx,
+ check_tag, tag_len ) ) )
+ {
+ return( ret );
+ }
+
+ /* Check the tag in "constant-time" */
+ for( diff = 0, i = 0; i < tag_len; i++ )
+ diff |= tag[i] ^ check_tag[i];
+
+ if( diff != 0 )
+ return( MBEDCRYPTO_ERR_CIPHER_AUTH_FAILED );
+
+ return( 0 );
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_GCM_C */
+
+/*
+ * Packet-oriented wrapper for non-AEAD modes
+ */
+int mbedcrypto_cipher_crypt( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen )
+{
+ int ret;
+ size_t finish_olen;
+
+ if( ( ret = mbedcrypto_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_cipher_reset( ctx ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_cipher_update( ctx, input, ilen, output, olen ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 )
+ return( ret );
+
+ *olen += finish_olen;
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_AEAD)
+/*
+ * Packet-oriented encryption for AEAD modes
+ */
+int mbedcrypto_cipher_auth_encrypt( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *ad, size_t ad_len,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen,
+ unsigned char *tag, size_t tag_len )
+{
+#if defined(MBEDCRYPTO_GCM_C)
+ if( MBEDCRYPTO_MODE_GCM == ctx->cipher_info->mode )
+ {
+ *olen = ilen;
+ return( mbedcrypto_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDCRYPTO_GCM_ENCRYPT, ilen,
+ iv, iv_len, ad, ad_len, input, output,
+ tag_len, tag ) );
+ }
+#endif /* MBEDCRYPTO_GCM_C */
+#if defined(MBEDCRYPTO_CCM_C)
+ if( MBEDCRYPTO_MODE_CCM == ctx->cipher_info->mode )
+ {
+ *olen = ilen;
+ return( mbedcrypto_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen,
+ iv, iv_len, ad, ad_len, input, output,
+ tag, tag_len ) );
+ }
+#endif /* MBEDCRYPTO_CCM_C */
+
+ return( MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+
+/*
+ * Packet-oriented decryption for AEAD modes
+ */
+int mbedcrypto_cipher_auth_decrypt( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *ad, size_t ad_len,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen,
+ const unsigned char *tag, size_t tag_len )
+{
+#if defined(MBEDCRYPTO_GCM_C)
+ if( MBEDCRYPTO_MODE_GCM == ctx->cipher_info->mode )
+ {
+ int ret;
+
+ *olen = ilen;
+ ret = mbedcrypto_gcm_auth_decrypt( ctx->cipher_ctx, ilen,
+ iv, iv_len, ad, ad_len,
+ tag, tag_len, input, output );
+
+ if( ret == MBEDCRYPTO_ERR_GCM_AUTH_FAILED )
+ ret = MBEDCRYPTO_ERR_CIPHER_AUTH_FAILED;
+
+ return( ret );
+ }
+#endif /* MBEDCRYPTO_GCM_C */
+#if defined(MBEDCRYPTO_CCM_C)
+ if( MBEDCRYPTO_MODE_CCM == ctx->cipher_info->mode )
+ {
+ int ret;
+
+ *olen = ilen;
+ ret = mbedcrypto_ccm_auth_decrypt( ctx->cipher_ctx, ilen,
+ iv, iv_len, ad, ad_len,
+ input, output, tag, tag_len );
+
+ if( ret == MBEDCRYPTO_ERR_CCM_AUTH_FAILED )
+ ret = MBEDCRYPTO_ERR_CIPHER_AUTH_FAILED;
+
+ return( ret );
+ }
+#endif /* MBEDCRYPTO_CCM_C */
+
+ return( MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_AEAD */
+
+#endif /* MBEDCRYPTO_CIPHER_C */
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
new file mode 100644
index 0000000..0418b5f
--- /dev/null
+++ b/library/cipher_wrap.c
@@ -0,0 +1,1451 @@
+/**
+ * \file cipher_wrap.c
+ *
+ * \brief Generic cipher wrapper for Mbed Crypto
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_C)
+
+#include "mbedcrypto/cipher_internal.h"
+
+#if defined(MBEDCRYPTO_AES_C)
+#include "mbedcrypto/aes.h"
+#endif
+
+#if defined(MBEDCRYPTO_ARC4_C)
+#include "mbedcrypto/arc4.h"
+#endif
+
+#if defined(MBEDCRYPTO_CAMELLIA_C)
+#include "mbedcrypto/camellia.h"
+#endif
+
+#if defined(MBEDCRYPTO_DES_C)
+#include "mbedcrypto/des.h"
+#endif
+
+#if defined(MBEDCRYPTO_BLOWFISH_C)
+#include "mbedcrypto/blowfish.h"
+#endif
+
+#if defined(MBEDCRYPTO_GCM_C)
+#include "mbedcrypto/gcm.h"
+#endif
+
+#if defined(MBEDCRYPTO_CCM_C)
+#include "mbedcrypto/ccm.h"
+#endif
+
+#if defined(MBEDCRYPTO_CIPHER_NULL_CIPHER)
+#include <string.h>
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#if defined(MBEDCRYPTO_GCM_C)
+/* shared by all GCM ciphers */
+static void *gcm_ctx_alloc( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_gcm_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_gcm_init( (mbedcrypto_gcm_context *) ctx );
+
+ return( ctx );
+}
+
+static void gcm_ctx_free( void *ctx )
+{
+ mbedcrypto_gcm_free( ctx );
+ mbedcrypto_free( ctx );
+}
+#endif /* MBEDCRYPTO_GCM_C */
+
+#if defined(MBEDCRYPTO_CCM_C)
+/* shared by all CCM ciphers */
+static void *ccm_ctx_alloc( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_ccm_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_ccm_init( (mbedcrypto_ccm_context *) ctx );
+
+ return( ctx );
+}
+
+static void ccm_ctx_free( void *ctx )
+{
+ mbedcrypto_ccm_free( ctx );
+ mbedcrypto_free( ctx );
+}
+#endif /* MBEDCRYPTO_CCM_C */
+
+#if defined(MBEDCRYPTO_AES_C)
+
+static int aes_crypt_ecb_wrap( void *ctx, mbedcrypto_operation_t operation,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_aes_crypt_ecb( (mbedcrypto_aes_context *) ctx, operation, input, output );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static int aes_crypt_cbc_wrap( void *ctx, mbedcrypto_operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_aes_crypt_cbc( (mbedcrypto_aes_context *) ctx, operation, length, iv, input,
+ output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+static int aes_crypt_cfb128_wrap( void *ctx, mbedcrypto_operation_t operation,
+ size_t length, size_t *iv_off, unsigned char *iv,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_aes_crypt_cfb128( (mbedcrypto_aes_context *) ctx, operation, length, iv_off, iv,
+ input, output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+ unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_aes_crypt_ctr( (mbedcrypto_aes_context *) ctx, length, nc_off, nonce_counter,
+ stream_block, input, output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedcrypto_aes_setkey_dec( (mbedcrypto_aes_context *) ctx, key, key_bitlen );
+}
+
+static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedcrypto_aes_setkey_enc( (mbedcrypto_aes_context *) ctx, key, key_bitlen );
+}
+
+static void * aes_ctx_alloc( void )
+{
+ mbedcrypto_aes_context *aes = mbedcrypto_calloc( 1, sizeof( mbedcrypto_aes_context ) );
+
+ if( aes == NULL )
+ return( NULL );
+
+ mbedcrypto_aes_init( aes );
+
+ return( aes );
+}
+
+static void aes_ctx_free( void *ctx )
+{
+ mbedcrypto_aes_free( (mbedcrypto_aes_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static const mbedcrypto_cipher_base_t aes_info = {
+ MBEDCRYPTO_CIPHER_ID_AES,
+ aes_crypt_ecb_wrap,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ aes_crypt_cbc_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ aes_crypt_cfb128_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ aes_crypt_ctr_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ aes_setkey_enc_wrap,
+ aes_setkey_dec_wrap,
+ aes_ctx_alloc,
+ aes_ctx_free
+};
+
+static const mbedcrypto_cipher_info_t aes_128_ecb_info = {
+ MBEDCRYPTO_CIPHER_AES_128_ECB,
+ MBEDCRYPTO_MODE_ECB,
+ 128,
+ "AES-128-ECB",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_192_ecb_info = {
+ MBEDCRYPTO_CIPHER_AES_192_ECB,
+ MBEDCRYPTO_MODE_ECB,
+ 192,
+ "AES-192-ECB",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_256_ecb_info = {
+ MBEDCRYPTO_CIPHER_AES_256_ECB,
+ MBEDCRYPTO_MODE_ECB,
+ 256,
+ "AES-256-ECB",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static const mbedcrypto_cipher_info_t aes_128_cbc_info = {
+ MBEDCRYPTO_CIPHER_AES_128_CBC,
+ MBEDCRYPTO_MODE_CBC,
+ 128,
+ "AES-128-CBC",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_192_cbc_info = {
+ MBEDCRYPTO_CIPHER_AES_192_CBC,
+ MBEDCRYPTO_MODE_CBC,
+ 192,
+ "AES-192-CBC",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_256_cbc_info = {
+ MBEDCRYPTO_CIPHER_AES_256_CBC,
+ MBEDCRYPTO_MODE_CBC,
+ 256,
+ "AES-256-CBC",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+static const mbedcrypto_cipher_info_t aes_128_cfb128_info = {
+ MBEDCRYPTO_CIPHER_AES_128_CFB128,
+ MBEDCRYPTO_MODE_CFB,
+ 128,
+ "AES-128-CFB128",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_192_cfb128_info = {
+ MBEDCRYPTO_CIPHER_AES_192_CFB128,
+ MBEDCRYPTO_MODE_CFB,
+ 192,
+ "AES-192-CFB128",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_256_cfb128_info = {
+ MBEDCRYPTO_CIPHER_AES_256_CFB128,
+ MBEDCRYPTO_MODE_CFB,
+ 256,
+ "AES-256-CFB128",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+static const mbedcrypto_cipher_info_t aes_128_ctr_info = {
+ MBEDCRYPTO_CIPHER_AES_128_CTR,
+ MBEDCRYPTO_MODE_CTR,
+ 128,
+ "AES-128-CTR",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_192_ctr_info = {
+ MBEDCRYPTO_CIPHER_AES_192_CTR,
+ MBEDCRYPTO_MODE_CTR,
+ 192,
+ "AES-192-CTR",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_256_ctr_info = {
+ MBEDCRYPTO_CIPHER_AES_256_CTR,
+ MBEDCRYPTO_MODE_CTR,
+ 256,
+ "AES-256-CTR",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+#if defined(MBEDCRYPTO_GCM_C)
+static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedcrypto_gcm_setkey( (mbedcrypto_gcm_context *) ctx, MBEDCRYPTO_CIPHER_ID_AES,
+ key, key_bitlen );
+}
+
+static const mbedcrypto_cipher_base_t gcm_aes_info = {
+ MBEDCRYPTO_CIPHER_ID_AES,
+ NULL,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ gcm_aes_setkey_wrap,
+ gcm_aes_setkey_wrap,
+ gcm_ctx_alloc,
+ gcm_ctx_free,
+};
+
+static const mbedcrypto_cipher_info_t aes_128_gcm_info = {
+ MBEDCRYPTO_CIPHER_AES_128_GCM,
+ MBEDCRYPTO_MODE_GCM,
+ 128,
+ "AES-128-GCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_192_gcm_info = {
+ MBEDCRYPTO_CIPHER_AES_192_GCM,
+ MBEDCRYPTO_MODE_GCM,
+ 192,
+ "AES-192-GCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_256_gcm_info = {
+ MBEDCRYPTO_CIPHER_AES_256_GCM,
+ MBEDCRYPTO_MODE_GCM,
+ 256,
+ "AES-256-GCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_aes_info
+};
+#endif /* MBEDCRYPTO_GCM_C */
+
+#if defined(MBEDCRYPTO_CCM_C)
+static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedcrypto_ccm_setkey( (mbedcrypto_ccm_context *) ctx, MBEDCRYPTO_CIPHER_ID_AES,
+ key, key_bitlen );
+}
+
+static const mbedcrypto_cipher_base_t ccm_aes_info = {
+ MBEDCRYPTO_CIPHER_ID_AES,
+ NULL,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ ccm_aes_setkey_wrap,
+ ccm_aes_setkey_wrap,
+ ccm_ctx_alloc,
+ ccm_ctx_free,
+};
+
+static const mbedcrypto_cipher_info_t aes_128_ccm_info = {
+ MBEDCRYPTO_CIPHER_AES_128_CCM,
+ MBEDCRYPTO_MODE_CCM,
+ 128,
+ "AES-128-CCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &ccm_aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_192_ccm_info = {
+ MBEDCRYPTO_CIPHER_AES_192_CCM,
+ MBEDCRYPTO_MODE_CCM,
+ 192,
+ "AES-192-CCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &ccm_aes_info
+};
+
+static const mbedcrypto_cipher_info_t aes_256_ccm_info = {
+ MBEDCRYPTO_CIPHER_AES_256_CCM,
+ MBEDCRYPTO_MODE_CCM,
+ 256,
+ "AES-256-CCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &ccm_aes_info
+};
+#endif /* MBEDCRYPTO_CCM_C */
+
+#endif /* MBEDCRYPTO_AES_C */
+
+#if defined(MBEDCRYPTO_CAMELLIA_C)
+
+static int camellia_crypt_ecb_wrap( void *ctx, mbedcrypto_operation_t operation,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_camellia_crypt_ecb( (mbedcrypto_camellia_context *) ctx, operation, input,
+ output );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static int camellia_crypt_cbc_wrap( void *ctx, mbedcrypto_operation_t operation,
+ size_t length, unsigned char *iv,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_camellia_crypt_cbc( (mbedcrypto_camellia_context *) ctx, operation, length, iv,
+ input, output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+static int camellia_crypt_cfb128_wrap( void *ctx, mbedcrypto_operation_t operation,
+ size_t length, size_t *iv_off, unsigned char *iv,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_camellia_crypt_cfb128( (mbedcrypto_camellia_context *) ctx, operation, length,
+ iv_off, iv, input, output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+ unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_camellia_crypt_ctr( (mbedcrypto_camellia_context *) ctx, length, nc_off,
+ nonce_counter, stream_block, input, output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedcrypto_camellia_setkey_dec( (mbedcrypto_camellia_context *) ctx, key, key_bitlen );
+}
+
+static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedcrypto_camellia_setkey_enc( (mbedcrypto_camellia_context *) ctx, key, key_bitlen );
+}
+
+static void * camellia_ctx_alloc( void )
+{
+ mbedcrypto_camellia_context *ctx;
+ ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_camellia_context ) );
+
+ if( ctx == NULL )
+ return( NULL );
+
+ mbedcrypto_camellia_init( ctx );
+
+ return( ctx );
+}
+
+static void camellia_ctx_free( void *ctx )
+{
+ mbedcrypto_camellia_free( (mbedcrypto_camellia_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static const mbedcrypto_cipher_base_t camellia_info = {
+ MBEDCRYPTO_CIPHER_ID_CAMELLIA,
+ camellia_crypt_ecb_wrap,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ camellia_crypt_cbc_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ camellia_crypt_cfb128_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ camellia_crypt_ctr_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ camellia_setkey_enc_wrap,
+ camellia_setkey_dec_wrap,
+ camellia_ctx_alloc,
+ camellia_ctx_free
+};
+
+static const mbedcrypto_cipher_info_t camellia_128_ecb_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_ECB,
+ MBEDCRYPTO_MODE_ECB,
+ 128,
+ "CAMELLIA-128-ECB",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_192_ecb_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_ECB,
+ MBEDCRYPTO_MODE_ECB,
+ 192,
+ "CAMELLIA-192-ECB",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_256_ecb_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_ECB,
+ MBEDCRYPTO_MODE_ECB,
+ 256,
+ "CAMELLIA-256-ECB",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static const mbedcrypto_cipher_info_t camellia_128_cbc_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_CBC,
+ MBEDCRYPTO_MODE_CBC,
+ 128,
+ "CAMELLIA-128-CBC",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_192_cbc_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_CBC,
+ MBEDCRYPTO_MODE_CBC,
+ 192,
+ "CAMELLIA-192-CBC",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_256_cbc_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_CBC,
+ MBEDCRYPTO_MODE_CBC,
+ 256,
+ "CAMELLIA-256-CBC",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+static const mbedcrypto_cipher_info_t camellia_128_cfb128_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_CFB128,
+ MBEDCRYPTO_MODE_CFB,
+ 128,
+ "CAMELLIA-128-CFB128",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_192_cfb128_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_CFB128,
+ MBEDCRYPTO_MODE_CFB,
+ 192,
+ "CAMELLIA-192-CFB128",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_256_cfb128_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_CFB128,
+ MBEDCRYPTO_MODE_CFB,
+ 256,
+ "CAMELLIA-256-CFB128",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+static const mbedcrypto_cipher_info_t camellia_128_ctr_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_CTR,
+ MBEDCRYPTO_MODE_CTR,
+ 128,
+ "CAMELLIA-128-CTR",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_192_ctr_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_CTR,
+ MBEDCRYPTO_MODE_CTR,
+ 192,
+ "CAMELLIA-192-CTR",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_256_ctr_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_CTR,
+ MBEDCRYPTO_MODE_CTR,
+ 256,
+ "CAMELLIA-256-CTR",
+ 16,
+ 0,
+ 16,
+ &camellia_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+#if defined(MBEDCRYPTO_GCM_C)
+static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedcrypto_gcm_setkey( (mbedcrypto_gcm_context *) ctx, MBEDCRYPTO_CIPHER_ID_CAMELLIA,
+ key, key_bitlen );
+}
+
+static const mbedcrypto_cipher_base_t gcm_camellia_info = {
+ MBEDCRYPTO_CIPHER_ID_CAMELLIA,
+ NULL,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ gcm_camellia_setkey_wrap,
+ gcm_camellia_setkey_wrap,
+ gcm_ctx_alloc,
+ gcm_ctx_free,
+};
+
+static const mbedcrypto_cipher_info_t camellia_128_gcm_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_GCM,
+ MBEDCRYPTO_MODE_GCM,
+ 128,
+ "CAMELLIA-128-GCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_192_gcm_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_GCM,
+ MBEDCRYPTO_MODE_GCM,
+ 192,
+ "CAMELLIA-192-GCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_256_gcm_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_GCM,
+ MBEDCRYPTO_MODE_GCM,
+ 256,
+ "CAMELLIA-256-GCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_camellia_info
+};
+#endif /* MBEDCRYPTO_GCM_C */
+
+#if defined(MBEDCRYPTO_CCM_C)
+static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedcrypto_ccm_setkey( (mbedcrypto_ccm_context *) ctx, MBEDCRYPTO_CIPHER_ID_CAMELLIA,
+ key, key_bitlen );
+}
+
+static const mbedcrypto_cipher_base_t ccm_camellia_info = {
+ MBEDCRYPTO_CIPHER_ID_CAMELLIA,
+ NULL,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ ccm_camellia_setkey_wrap,
+ ccm_camellia_setkey_wrap,
+ ccm_ctx_alloc,
+ ccm_ctx_free,
+};
+
+static const mbedcrypto_cipher_info_t camellia_128_ccm_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_128_CCM,
+ MBEDCRYPTO_MODE_CCM,
+ 128,
+ "CAMELLIA-128-CCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &ccm_camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_192_ccm_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_192_CCM,
+ MBEDCRYPTO_MODE_CCM,
+ 192,
+ "CAMELLIA-192-CCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &ccm_camellia_info
+};
+
+static const mbedcrypto_cipher_info_t camellia_256_ccm_info = {
+ MBEDCRYPTO_CIPHER_CAMELLIA_256_CCM,
+ MBEDCRYPTO_MODE_CCM,
+ 256,
+ "CAMELLIA-256-CCM",
+ 12,
+ MBEDCRYPTO_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &ccm_camellia_info
+};
+#endif /* MBEDCRYPTO_CCM_C */
+
+#endif /* MBEDCRYPTO_CAMELLIA_C */
+
+#if defined(MBEDCRYPTO_DES_C)
+
+static int des_crypt_ecb_wrap( void *ctx, mbedcrypto_operation_t operation,
+ const unsigned char *input, unsigned char *output )
+{
+ ((void) operation);
+ return mbedcrypto_des_crypt_ecb( (mbedcrypto_des_context *) ctx, input, output );
+}
+
+static int des3_crypt_ecb_wrap( void *ctx, mbedcrypto_operation_t operation,
+ const unsigned char *input, unsigned char *output )
+{
+ ((void) operation);
+ return mbedcrypto_des3_crypt_ecb( (mbedcrypto_des3_context *) ctx, input, output );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static int des_crypt_cbc_wrap( void *ctx, mbedcrypto_operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_des_crypt_cbc( (mbedcrypto_des_context *) ctx, operation, length, iv, input,
+ output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static int des3_crypt_cbc_wrap( void *ctx, mbedcrypto_operation_t operation, size_t length,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_des3_crypt_cbc( (mbedcrypto_des3_context *) ctx, operation, length, iv, input,
+ output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+static int des_setkey_dec_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ ((void) key_bitlen);
+
+ return mbedcrypto_des_setkey_dec( (mbedcrypto_des_context *) ctx, key );
+}
+
+static int des_setkey_enc_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ ((void) key_bitlen);
+
+ return mbedcrypto_des_setkey_enc( (mbedcrypto_des_context *) ctx, key );
+}
+
+static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ ((void) key_bitlen);
+
+ return mbedcrypto_des3_set2key_dec( (mbedcrypto_des3_context *) ctx, key );
+}
+
+static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ ((void) key_bitlen);
+
+ return mbedcrypto_des3_set2key_enc( (mbedcrypto_des3_context *) ctx, key );
+}
+
+static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ ((void) key_bitlen);
+
+ return mbedcrypto_des3_set3key_dec( (mbedcrypto_des3_context *) ctx, key );
+}
+
+static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ ((void) key_bitlen);
+
+ return mbedcrypto_des3_set3key_enc( (mbedcrypto_des3_context *) ctx, key );
+}
+
+static void * des_ctx_alloc( void )
+{
+ mbedcrypto_des_context *des = mbedcrypto_calloc( 1, sizeof( mbedcrypto_des_context ) );
+
+ if( des == NULL )
+ return( NULL );
+
+ mbedcrypto_des_init( des );
+
+ return( des );
+}
+
+static void des_ctx_free( void *ctx )
+{
+ mbedcrypto_des_free( (mbedcrypto_des_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static void * des3_ctx_alloc( void )
+{
+ mbedcrypto_des3_context *des3;
+ des3 = mbedcrypto_calloc( 1, sizeof( mbedcrypto_des3_context ) );
+
+ if( des3 == NULL )
+ return( NULL );
+
+ mbedcrypto_des3_init( des3 );
+
+ return( des3 );
+}
+
+static void des3_ctx_free( void *ctx )
+{
+ mbedcrypto_des3_free( (mbedcrypto_des3_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static const mbedcrypto_cipher_base_t des_info = {
+ MBEDCRYPTO_CIPHER_ID_DES,
+ des_crypt_ecb_wrap,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ des_crypt_cbc_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ des_setkey_enc_wrap,
+ des_setkey_dec_wrap,
+ des_ctx_alloc,
+ des_ctx_free
+};
+
+static const mbedcrypto_cipher_info_t des_ecb_info = {
+ MBEDCRYPTO_CIPHER_DES_ECB,
+ MBEDCRYPTO_MODE_ECB,
+ MBEDCRYPTO_KEY_LENGTH_DES,
+ "DES-ECB",
+ 8,
+ 0,
+ 8,
+ &des_info
+};
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static const mbedcrypto_cipher_info_t des_cbc_info = {
+ MBEDCRYPTO_CIPHER_DES_CBC,
+ MBEDCRYPTO_MODE_CBC,
+ MBEDCRYPTO_KEY_LENGTH_DES,
+ "DES-CBC",
+ 8,
+ 0,
+ 8,
+ &des_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+static const mbedcrypto_cipher_base_t des_ede_info = {
+ MBEDCRYPTO_CIPHER_ID_DES,
+ des3_crypt_ecb_wrap,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ des3_crypt_cbc_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ des3_set2key_enc_wrap,
+ des3_set2key_dec_wrap,
+ des3_ctx_alloc,
+ des3_ctx_free
+};
+
+static const mbedcrypto_cipher_info_t des_ede_ecb_info = {
+ MBEDCRYPTO_CIPHER_DES_EDE_ECB,
+ MBEDCRYPTO_MODE_ECB,
+ MBEDCRYPTO_KEY_LENGTH_DES_EDE,
+ "DES-EDE-ECB",
+ 8,
+ 0,
+ 8,
+ &des_ede_info
+};
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static const mbedcrypto_cipher_info_t des_ede_cbc_info = {
+ MBEDCRYPTO_CIPHER_DES_EDE_CBC,
+ MBEDCRYPTO_MODE_CBC,
+ MBEDCRYPTO_KEY_LENGTH_DES_EDE,
+ "DES-EDE-CBC",
+ 8,
+ 0,
+ 8,
+ &des_ede_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+static const mbedcrypto_cipher_base_t des_ede3_info = {
+ MBEDCRYPTO_CIPHER_ID_3DES,
+ des3_crypt_ecb_wrap,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ des3_crypt_cbc_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ des3_set3key_enc_wrap,
+ des3_set3key_dec_wrap,
+ des3_ctx_alloc,
+ des3_ctx_free
+};
+
+static const mbedcrypto_cipher_info_t des_ede3_ecb_info = {
+ MBEDCRYPTO_CIPHER_DES_EDE3_ECB,
+ MBEDCRYPTO_MODE_ECB,
+ MBEDCRYPTO_KEY_LENGTH_DES_EDE3,
+ "DES-EDE3-ECB",
+ 8,
+ 0,
+ 8,
+ &des_ede3_info
+};
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static const mbedcrypto_cipher_info_t des_ede3_cbc_info = {
+ MBEDCRYPTO_CIPHER_DES_EDE3_CBC,
+ MBEDCRYPTO_MODE_CBC,
+ MBEDCRYPTO_KEY_LENGTH_DES_EDE3,
+ "DES-EDE3-CBC",
+ 8,
+ 0,
+ 8,
+ &des_ede3_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+#endif /* MBEDCRYPTO_DES_C */
+
+#if defined(MBEDCRYPTO_BLOWFISH_C)
+
+static int blowfish_crypt_ecb_wrap( void *ctx, mbedcrypto_operation_t operation,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_blowfish_crypt_ecb( (mbedcrypto_blowfish_context *) ctx, operation, input,
+ output );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static int blowfish_crypt_cbc_wrap( void *ctx, mbedcrypto_operation_t operation,
+ size_t length, unsigned char *iv, const unsigned char *input,
+ unsigned char *output )
+{
+ return mbedcrypto_blowfish_crypt_cbc( (mbedcrypto_blowfish_context *) ctx, operation, length, iv,
+ input, output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+static int blowfish_crypt_cfb64_wrap( void *ctx, mbedcrypto_operation_t operation,
+ size_t length, size_t *iv_off, unsigned char *iv,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_blowfish_crypt_cfb64( (mbedcrypto_blowfish_context *) ctx, operation, length,
+ iv_off, iv, input, output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+ unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedcrypto_blowfish_crypt_ctr( (mbedcrypto_blowfish_context *) ctx, length, nc_off,
+ nonce_counter, stream_block, input, output );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+
+static int blowfish_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedcrypto_blowfish_setkey( (mbedcrypto_blowfish_context *) ctx, key, key_bitlen );
+}
+
+static void * blowfish_ctx_alloc( void )
+{
+ mbedcrypto_blowfish_context *ctx;
+ ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_blowfish_context ) );
+
+ if( ctx == NULL )
+ return( NULL );
+
+ mbedcrypto_blowfish_init( ctx );
+
+ return( ctx );
+}
+
+static void blowfish_ctx_free( void *ctx )
+{
+ mbedcrypto_blowfish_free( (mbedcrypto_blowfish_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static const mbedcrypto_cipher_base_t blowfish_info = {
+ MBEDCRYPTO_CIPHER_ID_BLOWFISH,
+ blowfish_crypt_ecb_wrap,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ blowfish_crypt_cbc_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ blowfish_crypt_cfb64_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ blowfish_crypt_ctr_wrap,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ blowfish_setkey_wrap,
+ blowfish_setkey_wrap,
+ blowfish_ctx_alloc,
+ blowfish_ctx_free
+};
+
+static const mbedcrypto_cipher_info_t blowfish_ecb_info = {
+ MBEDCRYPTO_CIPHER_BLOWFISH_ECB,
+ MBEDCRYPTO_MODE_ECB,
+ 128,
+ "BLOWFISH-ECB",
+ 8,
+ MBEDCRYPTO_CIPHER_VARIABLE_KEY_LEN,
+ 8,
+ &blowfish_info
+};
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static const mbedcrypto_cipher_info_t blowfish_cbc_info = {
+ MBEDCRYPTO_CIPHER_BLOWFISH_CBC,
+ MBEDCRYPTO_MODE_CBC,
+ 128,
+ "BLOWFISH-CBC",
+ 8,
+ MBEDCRYPTO_CIPHER_VARIABLE_KEY_LEN,
+ 8,
+ &blowfish_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+static const mbedcrypto_cipher_info_t blowfish_cfb64_info = {
+ MBEDCRYPTO_CIPHER_BLOWFISH_CFB64,
+ MBEDCRYPTO_MODE_CFB,
+ 128,
+ "BLOWFISH-CFB64",
+ 8,
+ MBEDCRYPTO_CIPHER_VARIABLE_KEY_LEN,
+ 8,
+ &blowfish_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CFB */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+static const mbedcrypto_cipher_info_t blowfish_ctr_info = {
+ MBEDCRYPTO_CIPHER_BLOWFISH_CTR,
+ MBEDCRYPTO_MODE_CTR,
+ 128,
+ "BLOWFISH-CTR",
+ 8,
+ MBEDCRYPTO_CIPHER_VARIABLE_KEY_LEN,
+ 8,
+ &blowfish_info
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CTR */
+#endif /* MBEDCRYPTO_BLOWFISH_C */
+
+#if defined(MBEDCRYPTO_ARC4_C)
+static int arc4_crypt_stream_wrap( void *ctx, size_t length,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ return( mbedcrypto_arc4_crypt( (mbedcrypto_arc4_context *) ctx, length, input, output ) );
+}
+
+static int arc4_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ /* we get key_bitlen in bits, arc4 expects it in bytes */
+ if( key_bitlen % 8 != 0 )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ mbedcrypto_arc4_setup( (mbedcrypto_arc4_context *) ctx, key, key_bitlen / 8 );
+ return( 0 );
+}
+
+static void * arc4_ctx_alloc( void )
+{
+ mbedcrypto_arc4_context *ctx;
+ ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_arc4_context ) );
+
+ if( ctx == NULL )
+ return( NULL );
+
+ mbedcrypto_arc4_init( ctx );
+
+ return( ctx );
+}
+
+static void arc4_ctx_free( void *ctx )
+{
+ mbedcrypto_arc4_free( (mbedcrypto_arc4_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static const mbedcrypto_cipher_base_t arc4_base_info = {
+ MBEDCRYPTO_CIPHER_ID_ARC4,
+ NULL,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ arc4_crypt_stream_wrap,
+#endif
+ arc4_setkey_wrap,
+ arc4_setkey_wrap,
+ arc4_ctx_alloc,
+ arc4_ctx_free
+};
+
+static const mbedcrypto_cipher_info_t arc4_128_info = {
+ MBEDCRYPTO_CIPHER_ARC4_128,
+ MBEDCRYPTO_MODE_STREAM,
+ 128,
+ "ARC4-128",
+ 0,
+ 0,
+ 1,
+ &arc4_base_info
+};
+#endif /* MBEDCRYPTO_ARC4_C */
+
+#if defined(MBEDCRYPTO_CIPHER_NULL_CIPHER)
+static int null_crypt_stream( void *ctx, size_t length,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ ((void) ctx);
+ memmove( output, input, length );
+ return( 0 );
+}
+
+static int null_setkey( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ ((void) ctx);
+ ((void) key);
+ ((void) key_bitlen);
+
+ return( 0 );
+}
+
+static void * null_ctx_alloc( void )
+{
+ return( (void *) 1 );
+}
+
+static void null_ctx_free( void *ctx )
+{
+ ((void) ctx);
+}
+
+static const mbedcrypto_cipher_base_t null_base_info = {
+ MBEDCRYPTO_CIPHER_ID_NULL,
+ NULL,
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_STREAM)
+ null_crypt_stream,
+#endif
+ null_setkey,
+ null_setkey,
+ null_ctx_alloc,
+ null_ctx_free
+};
+
+static const mbedcrypto_cipher_info_t null_cipher_info = {
+ MBEDCRYPTO_CIPHER_NULL,
+ MBEDCRYPTO_MODE_STREAM,
+ 0,
+ "NULL",
+ 0,
+ 0,
+ 1,
+ &null_base_info
+};
+#endif /* defined(MBEDCRYPTO_CIPHER_NULL_CIPHER) */
+
+const mbedcrypto_cipher_definition_t mbedcrypto_cipher_definitions[] =
+{
+#if defined(MBEDCRYPTO_AES_C)
+ { MBEDCRYPTO_CIPHER_AES_128_ECB, &aes_128_ecb_info },
+ { MBEDCRYPTO_CIPHER_AES_192_ECB, &aes_192_ecb_info },
+ { MBEDCRYPTO_CIPHER_AES_256_ECB, &aes_256_ecb_info },
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ { MBEDCRYPTO_CIPHER_AES_128_CBC, &aes_128_cbc_info },
+ { MBEDCRYPTO_CIPHER_AES_192_CBC, &aes_192_cbc_info },
+ { MBEDCRYPTO_CIPHER_AES_256_CBC, &aes_256_cbc_info },
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ { MBEDCRYPTO_CIPHER_AES_128_CFB128, &aes_128_cfb128_info },
+ { MBEDCRYPTO_CIPHER_AES_192_CFB128, &aes_192_cfb128_info },
+ { MBEDCRYPTO_CIPHER_AES_256_CFB128, &aes_256_cfb128_info },
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ { MBEDCRYPTO_CIPHER_AES_128_CTR, &aes_128_ctr_info },
+ { MBEDCRYPTO_CIPHER_AES_192_CTR, &aes_192_ctr_info },
+ { MBEDCRYPTO_CIPHER_AES_256_CTR, &aes_256_ctr_info },
+#endif
+#if defined(MBEDCRYPTO_GCM_C)
+ { MBEDCRYPTO_CIPHER_AES_128_GCM, &aes_128_gcm_info },
+ { MBEDCRYPTO_CIPHER_AES_192_GCM, &aes_192_gcm_info },
+ { MBEDCRYPTO_CIPHER_AES_256_GCM, &aes_256_gcm_info },
+#endif
+#if defined(MBEDCRYPTO_CCM_C)
+ { MBEDCRYPTO_CIPHER_AES_128_CCM, &aes_128_ccm_info },
+ { MBEDCRYPTO_CIPHER_AES_192_CCM, &aes_192_ccm_info },
+ { MBEDCRYPTO_CIPHER_AES_256_CCM, &aes_256_ccm_info },
+#endif
+#endif /* MBEDCRYPTO_AES_C */
+
+#if defined(MBEDCRYPTO_ARC4_C)
+ { MBEDCRYPTO_CIPHER_ARC4_128, &arc4_128_info },
+#endif
+
+#if defined(MBEDCRYPTO_BLOWFISH_C)
+ { MBEDCRYPTO_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info },
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ { MBEDCRYPTO_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info },
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ { MBEDCRYPTO_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info },
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ { MBEDCRYPTO_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info },
+#endif
+#endif /* MBEDCRYPTO_BLOWFISH_C */
+
+#if defined(MBEDCRYPTO_CAMELLIA_C)
+ { MBEDCRYPTO_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info },
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ { MBEDCRYPTO_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info },
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CFB)
+ { MBEDCRYPTO_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info },
+#endif
+#if defined(MBEDCRYPTO_CIPHER_MODE_CTR)
+ { MBEDCRYPTO_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info },
+#endif
+#if defined(MBEDCRYPTO_GCM_C)
+ { MBEDCRYPTO_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info },
+#endif
+#if defined(MBEDCRYPTO_CCM_C)
+ { MBEDCRYPTO_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info },
+ { MBEDCRYPTO_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info },
+#endif
+#endif /* MBEDCRYPTO_CAMELLIA_C */
+
+#if defined(MBEDCRYPTO_DES_C)
+ { MBEDCRYPTO_CIPHER_DES_ECB, &des_ecb_info },
+ { MBEDCRYPTO_CIPHER_DES_EDE_ECB, &des_ede_ecb_info },
+ { MBEDCRYPTO_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info },
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ { MBEDCRYPTO_CIPHER_DES_CBC, &des_cbc_info },
+ { MBEDCRYPTO_CIPHER_DES_EDE_CBC, &des_ede_cbc_info },
+ { MBEDCRYPTO_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info },
+#endif
+#endif /* MBEDCRYPTO_DES_C */
+
+#if defined(MBEDCRYPTO_CIPHER_NULL_CIPHER)
+ { MBEDCRYPTO_CIPHER_NULL, &null_cipher_info },
+#endif /* MBEDCRYPTO_CIPHER_NULL_CIPHER */
+
+ { MBEDCRYPTO_CIPHER_NONE, NULL }
+};
+
+#define NUM_CIPHERS sizeof mbedcrypto_cipher_definitions / sizeof mbedcrypto_cipher_definitions[0]
+int mbedcrypto_cipher_supported[NUM_CIPHERS];
+
+#endif /* MBEDCRYPTO_CIPHER_C */
diff --git a/library/cmac.c b/library/cmac.c
new file mode 100644
index 0000000..e12f7bd
--- /dev/null
+++ b/library/cmac.c
@@ -0,0 +1,1076 @@
+/**
+ * \file cmac.c
+ *
+ * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES
+ *
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * References:
+ *
+ * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The
+ * CMAC Mode for Authentication
+ * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf
+ *
+ * - RFC 4493 - The AES-CMAC Algorithm
+ * https://tools.ietf.org/html/rfc4493
+ *
+ * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message
+ * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128)
+ * Algorithm for the Internet Key Exchange Protocol (IKE)
+ * https://tools.ietf.org/html/rfc4615
+ *
+ * Additional test vectors: ISO/IEC 9797-1
+ *
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_CMAC_C)
+
+#include "mbedcrypto/cmac.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#if defined(MBEDCRYPTO_SELF_TEST)
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_SELF_TEST */
+#endif /* MBEDCRYPTO_PLATFORM_C */
+
+#if !defined(MBEDCRYPTO_CMAC_ALT) || defined(MBEDCRYPTO_SELF_TEST)
+
+/*
+ * Multiplication by u in the Galois field of GF(2^n)
+ *
+ * As explained in NIST SP 800-38B, this can be computed:
+ *
+ * If MSB(p) = 0, then p = (p << 1)
+ * If MSB(p) = 1, then p = (p << 1) ^ R_n
+ * with R_64 = 0x1B and R_128 = 0x87
+ *
+ * Input and output MUST NOT point to the same buffer
+ * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES.
+ */
+static int cmac_multiply_by_u( unsigned char *output,
+ const unsigned char *input,
+ size_t blocksize )
+{
+ const unsigned char R_128 = 0x87;
+ const unsigned char R_64 = 0x1B;
+ unsigned char R_n, mask;
+ unsigned char overflow = 0x00;
+ int i;
+
+ if( blocksize == MBEDCRYPTO_AES_BLOCK_SIZE )
+ {
+ R_n = R_128;
+ }
+ else if( blocksize == MBEDCRYPTO_DES3_BLOCK_SIZE )
+ {
+ R_n = R_64;
+ }
+ else
+ {
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ for( i = (int)blocksize - 1; i >= 0; i-- )
+ {
+ output[i] = input[i] << 1 | overflow;
+ overflow = input[i] >> 7;
+ }
+
+ /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
+ * using bit operations to avoid branches */
+
+ /* MSVC has a warning about unary minus on unsigned, but this is
+ * well-defined and precisely what we want to do here */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+ mask = - ( input[0] >> 7 );
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+ output[ blocksize - 1 ] ^= R_n & mask;
+
+ return( 0 );
+}
+
+/*
+ * Generate subkeys
+ *
+ * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
+ */
+static int cmac_generate_subkeys( mbedcrypto_cipher_context_t *ctx,
+ unsigned char* K1, unsigned char* K2 )
+{
+ int ret;
+ unsigned char L[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+ size_t olen, block_size;
+
+ mbedcrypto_platform_zeroize( L, sizeof( L ) );
+
+ block_size = ctx->cipher_info->block_size;
+
+ /* Calculate Ek(0) */
+ if( ( ret = mbedcrypto_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 )
+ goto exit;
+
+ /*
+ * Generate K1 and K2
+ */
+ if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 )
+ goto exit;
+
+ if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedcrypto_platform_zeroize( L, sizeof( L ) );
+
+ return( ret );
+}
+#endif /* !defined(MBEDCRYPTO_CMAC_ALT) || defined(MBEDCRYPTO_SELF_TEST) */
+
+#if !defined(MBEDCRYPTO_CMAC_ALT)
+static void cmac_xor_block( unsigned char *output, const unsigned char *input1,
+ const unsigned char *input2,
+ const size_t block_size )
+{
+ size_t idx;
+
+ for( idx = 0; idx < block_size; idx++ )
+ output[ idx ] = input1[ idx ] ^ input2[ idx ];
+}
+
+/*
+ * Create padded last block from (partial) last block.
+ *
+ * We can't use the padding option from the cipher layer, as it only works for
+ * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
+ */
+static void cmac_pad( unsigned char padded_block[MBEDCRYPTO_CIPHER_BLKSIZE_MAX],
+ size_t padded_block_len,
+ const unsigned char *last_block,
+ size_t last_block_len )
+{
+ size_t j;
+
+ for( j = 0; j < padded_block_len; j++ )
+ {
+ if( j < last_block_len )
+ padded_block[j] = last_block[j];
+ else if( j == last_block_len )
+ padded_block[j] = 0x80;
+ else
+ padded_block[j] = 0x00;
+ }
+}
+
+int mbedcrypto_cipher_cmac_starts( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *key, size_t keybits )
+{
+ mbedcrypto_cipher_type_t type;
+ mbedcrypto_cmac_context_t *cmac_ctx;
+ int retval;
+
+ if( ctx == NULL || ctx->cipher_info == NULL || key == NULL )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( ( retval = mbedcrypto_cipher_setkey( ctx, key, (int)keybits,
+ MBEDCRYPTO_ENCRYPT ) ) != 0 )
+ return( retval );
+
+ type = ctx->cipher_info->type;
+
+ switch( type )
+ {
+ case MBEDCRYPTO_CIPHER_AES_128_ECB:
+ case MBEDCRYPTO_CIPHER_AES_192_ECB:
+ case MBEDCRYPTO_CIPHER_AES_256_ECB:
+ case MBEDCRYPTO_CIPHER_DES_EDE3_ECB:
+ break;
+ default:
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ /* Allocated and initialise in the cipher context memory for the CMAC
+ * context */
+ cmac_ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_cmac_context_t ) );
+ if( cmac_ctx == NULL )
+ return( MBEDCRYPTO_ERR_CIPHER_ALLOC_FAILED );
+
+ ctx->cmac_ctx = cmac_ctx;
+
+ mbedcrypto_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) );
+
+ return 0;
+}
+
+int mbedcrypto_cipher_cmac_update( mbedcrypto_cipher_context_t *ctx,
+ const unsigned char *input, size_t ilen )
+{
+ mbedcrypto_cmac_context_t* cmac_ctx;
+ unsigned char *state;
+ int ret = 0;
+ size_t n, j, olen, block_size;
+
+ if( ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
+ ctx->cmac_ctx == NULL )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ cmac_ctx = ctx->cmac_ctx;
+ block_size = ctx->cipher_info->block_size;
+ state = ctx->cmac_ctx->state;
+
+ /* Is there data still to process from the last call, that's greater in
+ * size than a block? */
+ if( cmac_ctx->unprocessed_len > 0 &&
+ ilen > block_size - cmac_ctx->unprocessed_len )
+ {
+ memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
+ input,
+ block_size - cmac_ctx->unprocessed_len );
+
+ cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size );
+
+ if( ( ret = mbedcrypto_cipher_update( ctx, state, block_size, state,
+ &olen ) ) != 0 )
+ {
+ goto exit;
+ }
+
+ input += block_size - cmac_ctx->unprocessed_len;
+ ilen -= block_size - cmac_ctx->unprocessed_len;
+ cmac_ctx->unprocessed_len = 0;
+ }
+
+ /* n is the number of blocks including any final partial block */
+ n = ( ilen + block_size - 1 ) / block_size;
+
+ /* Iterate across the input data in block sized chunks, excluding any
+ * final partial or complete block */
+ for( j = 1; j < n; j++ )
+ {
+ cmac_xor_block( state, input, state, block_size );
+
+ if( ( ret = mbedcrypto_cipher_update( ctx, state, block_size, state,
+ &olen ) ) != 0 )
+ goto exit;
+
+ ilen -= block_size;
+ input += block_size;
+ }
+
+ /* If there is data left over that wasn't aligned to a block */
+ if( ilen > 0 )
+ {
+ memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
+ input,
+ ilen );
+ cmac_ctx->unprocessed_len += ilen;
+ }
+
+exit:
+ return( ret );
+}
+
+int mbedcrypto_cipher_cmac_finish( mbedcrypto_cipher_context_t *ctx,
+ unsigned char *output )
+{
+ mbedcrypto_cmac_context_t* cmac_ctx;
+ unsigned char *state, *last_block;
+ unsigned char K1[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+ unsigned char K2[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+ unsigned char M_last[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+ int ret;
+ size_t olen, block_size;
+
+ if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
+ output == NULL )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ cmac_ctx = ctx->cmac_ctx;
+ block_size = ctx->cipher_info->block_size;
+ state = cmac_ctx->state;
+
+ mbedcrypto_platform_zeroize( K1, sizeof( K1 ) );
+ mbedcrypto_platform_zeroize( K2, sizeof( K2 ) );
+ cmac_generate_subkeys( ctx, K1, K2 );
+
+ last_block = cmac_ctx->unprocessed_block;
+
+ /* Calculate last block */
+ if( cmac_ctx->unprocessed_len < block_size )
+ {
+ cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len );
+ cmac_xor_block( M_last, M_last, K2, block_size );
+ }
+ else
+ {
+ /* Last block is complete block */
+ cmac_xor_block( M_last, last_block, K1, block_size );
+ }
+
+
+ cmac_xor_block( state, M_last, state, block_size );
+ if( ( ret = mbedcrypto_cipher_update( ctx, state, block_size, state,
+ &olen ) ) != 0 )
+ {
+ goto exit;
+ }
+
+ memcpy( output, state, block_size );
+
+exit:
+ /* Wipe the generated keys on the stack, and any other transients to avoid
+ * side channel leakage */
+ mbedcrypto_platform_zeroize( K1, sizeof( K1 ) );
+ mbedcrypto_platform_zeroize( K2, sizeof( K2 ) );
+
+ cmac_ctx->unprocessed_len = 0;
+ mbedcrypto_platform_zeroize( cmac_ctx->unprocessed_block,
+ sizeof( cmac_ctx->unprocessed_block ) );
+
+ mbedcrypto_platform_zeroize( state, MBEDCRYPTO_CIPHER_BLKSIZE_MAX );
+ return( ret );
+}
+
+int mbedcrypto_cipher_cmac_reset( mbedcrypto_cipher_context_t *ctx )
+{
+ mbedcrypto_cmac_context_t* cmac_ctx;
+
+ if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ cmac_ctx = ctx->cmac_ctx;
+
+ /* Reset the internal state */
+ cmac_ctx->unprocessed_len = 0;
+ mbedcrypto_platform_zeroize( cmac_ctx->unprocessed_block,
+ sizeof( cmac_ctx->unprocessed_block ) );
+ mbedcrypto_platform_zeroize( cmac_ctx->state,
+ sizeof( cmac_ctx->state ) );
+
+ return( 0 );
+}
+
+int mbedcrypto_cipher_cmac( const mbedcrypto_cipher_info_t *cipher_info,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ mbedcrypto_cipher_context_t ctx;
+ int ret;
+
+ if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ mbedcrypto_cipher_init( &ctx );
+
+ if( ( ret = mbedcrypto_cipher_setup( &ctx, cipher_info ) ) != 0 )
+ goto exit;
+
+ ret = mbedcrypto_cipher_cmac_starts( &ctx, key, keylen );
+ if( ret != 0 )
+ goto exit;
+
+ ret = mbedcrypto_cipher_cmac_update( &ctx, input, ilen );
+ if( ret != 0 )
+ goto exit;
+
+ ret = mbedcrypto_cipher_cmac_finish( &ctx, output );
+
+exit:
+ mbedcrypto_cipher_free( &ctx );
+
+ return( ret );
+}
+
+#if defined(MBEDCRYPTO_AES_C)
+/*
+ * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
+ */
+int mbedcrypto_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
+ const unsigned char *input, size_t in_len,
+ unsigned char *output )
+{
+ int ret;
+ const mbedcrypto_cipher_info_t *cipher_info;
+ unsigned char zero_key[MBEDCRYPTO_AES_BLOCK_SIZE];
+ unsigned char int_key[MBEDCRYPTO_AES_BLOCK_SIZE];
+
+ if( key == NULL || input == NULL || output == NULL )
+ return( MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA );
+
+ cipher_info = mbedcrypto_cipher_info_from_type( MBEDCRYPTO_CIPHER_AES_128_ECB );
+ if( cipher_info == NULL )
+ {
+ /* Failing at this point must be due to a build issue */
+ ret = MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ goto exit;
+ }
+
+ if( key_length == MBEDCRYPTO_AES_BLOCK_SIZE )
+ {
+ /* Use key as is */
+ memcpy( int_key, key, MBEDCRYPTO_AES_BLOCK_SIZE );
+ }
+ else
+ {
+ memset( zero_key, 0, MBEDCRYPTO_AES_BLOCK_SIZE );
+
+ ret = mbedcrypto_cipher_cmac( cipher_info, zero_key, 128, key,
+ key_length, int_key );
+ if( ret != 0 )
+ goto exit;
+ }
+
+ ret = mbedcrypto_cipher_cmac( cipher_info, int_key, 128, input, in_len,
+ output );
+
+exit:
+ mbedcrypto_platform_zeroize( int_key, sizeof( int_key ) );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_AES_C */
+
+#endif /* !MBEDCRYPTO_CMAC_ALT */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/*
+ * CMAC test data for SP800-38B
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf
+ *
+ * AES-CMAC-PRF-128 test data from RFC 4615
+ * https://tools.ietf.org/html/rfc4615#page-4
+ */
+
+#define NB_CMAC_TESTS_PER_KEY 4
+#define NB_PRF_TESTS 3
+
+#if defined(MBEDCRYPTO_AES_C) || defined(MBEDCRYPTO_DES_C)
+/* All CMAC test inputs are truncated from the same 64 byte buffer. */
+static const unsigned char test_message[] = {
+ /* PT */
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+ 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+ 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+ 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+ 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+};
+#endif /* MBEDCRYPTO_AES_C || MBEDCRYPTO_DES_C */
+
+#if defined(MBEDCRYPTO_AES_C)
+/* Truncation point of message for AES CMAC tests */
+static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
+ /* Mlen */
+ 0,
+ 16,
+ 20,
+ 64
+};
+
+/* CMAC-AES128 Test Data */
+static const unsigned char aes_128_key[16] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+};
+static const unsigned char aes_128_subkeys[2][MBEDCRYPTO_AES_BLOCK_SIZE] = {
+ {
+ /* K1 */
+ 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
+ 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
+ },
+ {
+ /* K2 */
+ 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
+ 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
+ }
+};
+static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDCRYPTO_AES_BLOCK_SIZE] = {
+ {
+ /* Example #1 */
+ 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+ 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
+ },
+ {
+ /* Example #2 */
+ 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
+ 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
+ },
+ {
+ /* Example #3 */
+ 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8,
+ 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde
+ },
+ {
+ /* Example #4 */
+ 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
+ 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
+ }
+};
+
+/* CMAC-AES192 Test Data */
+static const unsigned char aes_192_key[24] = {
+ 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+ 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+ 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
+};
+static const unsigned char aes_192_subkeys[2][MBEDCRYPTO_AES_BLOCK_SIZE] = {
+ {
+ /* K1 */
+ 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
+ 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
+ },
+ {
+ /* K2 */
+ 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
+ 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
+ }
+};
+static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDCRYPTO_AES_BLOCK_SIZE] = {
+ {
+ /* Example #1 */
+ 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
+ 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
+ },
+ {
+ /* Example #2 */
+ 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
+ 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
+ },
+ {
+ /* Example #3 */
+ 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04,
+ 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8
+ },
+ {
+ /* Example #4 */
+ 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
+ 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
+ }
+};
+
+/* CMAC-AES256 Test Data */
+static const unsigned char aes_256_key[32] = {
+ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+ 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+ 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
+};
+static const unsigned char aes_256_subkeys[2][MBEDCRYPTO_AES_BLOCK_SIZE] = {
+ {
+ /* K1 */
+ 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
+ 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
+ },
+ {
+ /* K2 */
+ 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
+ 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
+ }
+};
+static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDCRYPTO_AES_BLOCK_SIZE] = {
+ {
+ /* Example #1 */
+ 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
+ 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
+ },
+ {
+ /* Example #2 */
+ 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
+ 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
+ },
+ {
+ /* Example #3 */
+ 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a,
+ 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93
+ },
+ {
+ /* Example #4 */
+ 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
+ 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
+ }
+};
+#endif /* MBEDCRYPTO_AES_C */
+
+#if defined(MBEDCRYPTO_DES_C)
+/* Truncation point of message for 3DES CMAC tests */
+static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
+ 0,
+ 16,
+ 20,
+ 32
+};
+
+/* CMAC-TDES (Generation) - 2 Key Test Data */
+static const unsigned char des3_2key_key[24] = {
+ /* Key1 */
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ /* Key2 */
+ 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01,
+ /* Key3 */
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
+};
+static const unsigned char des3_2key_subkeys[2][8] = {
+ {
+ /* K1 */
+ 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9
+ },
+ {
+ /* K2 */
+ 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2
+ }
+};
+static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDCRYPTO_DES3_BLOCK_SIZE] = {
+ {
+ /* Sample #1 */
+ 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60
+ },
+ {
+ /* Sample #2 */
+ 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b
+ },
+ {
+ /* Sample #3 */
+ 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69
+ },
+ {
+ /* Sample #4 */
+ 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb
+ }
+};
+
+/* CMAC-TDES (Generation) - 3 Key Test Data */
+static const unsigned char des3_3key_key[24] = {
+ /* Key1 */
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef,
+ /* Key2 */
+ 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
+ /* Key3 */
+ 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
+};
+static const unsigned char des3_3key_subkeys[2][8] = {
+ {
+ /* K1 */
+ 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0
+ },
+ {
+ /* K2 */
+ 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b
+ }
+};
+static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDCRYPTO_DES3_BLOCK_SIZE] = {
+ {
+ /* Sample #1 */
+ 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50
+ },
+ {
+ /* Sample #2 */
+ 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09
+ },
+ {
+ /* Sample #3 */
+ 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2
+ },
+ {
+ /* Sample #4 */
+ 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5
+ }
+};
+
+#endif /* MBEDCRYPTO_DES_C */
+
+#if defined(MBEDCRYPTO_AES_C)
+/* AES AES-CMAC-PRF-128 Test Data */
+static const unsigned char PRFK[] = {
+ /* Key */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0xed, 0xcb
+};
+
+/* Sizes in bytes */
+static const size_t PRFKlen[NB_PRF_TESTS] = {
+ 18,
+ 16,
+ 10
+};
+
+/* Message */
+static const unsigned char PRFM[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13
+};
+
+static const unsigned char PRFT[NB_PRF_TESTS][16] = {
+ {
+ 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
+ 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
+ },
+ {
+ 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
+ 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
+ },
+ {
+ 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
+ 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
+ }
+};
+#endif /* MBEDCRYPTO_AES_C */
+
+static int cmac_test_subkeys( int verbose,
+ const char* testname,
+ const unsigned char* key,
+ int keybits,
+ const unsigned char* subkeys,
+ mbedcrypto_cipher_type_t cipher_type,
+ int block_size,
+ int num_tests )
+{
+ int i, ret = 0;
+ mbedcrypto_cipher_context_t ctx;
+ const mbedcrypto_cipher_info_t *cipher_info;
+ unsigned char K1[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+ unsigned char K2[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+
+ cipher_info = mbedcrypto_cipher_info_from_type( cipher_type );
+ if( cipher_info == NULL )
+ {
+ /* Failing at this point must be due to a build issue */
+ return( MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+
+ for( i = 0; i < num_tests; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " %s CMAC subkey #%u: ", testname, i + 1 );
+
+ mbedcrypto_cipher_init( &ctx );
+
+ if( ( ret = mbedcrypto_cipher_setup( &ctx, cipher_info ) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "test execution failed\n" );
+
+ goto cleanup;
+ }
+
+ if( ( ret = mbedcrypto_cipher_setkey( &ctx, key, keybits,
+ MBEDCRYPTO_ENCRYPT ) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "test execution failed\n" );
+
+ goto cleanup;
+ }
+
+ ret = cmac_generate_subkeys( &ctx, K1, K2 );
+ if( ret != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ goto cleanup;
+ }
+
+ if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 ||
+ ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ goto cleanup;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ mbedcrypto_cipher_free( &ctx );
+ }
+
+ goto exit;
+
+cleanup:
+ mbedcrypto_cipher_free( &ctx );
+
+exit:
+ return( ret );
+}
+
+static int cmac_test_wth_cipher( int verbose,
+ const char* testname,
+ const unsigned char* key,
+ int keybits,
+ const unsigned char* messages,
+ const unsigned int message_lengths[4],
+ const unsigned char* expected_result,
+ mbedcrypto_cipher_type_t cipher_type,
+ int block_size,
+ int num_tests )
+{
+ const mbedcrypto_cipher_info_t *cipher_info;
+ int i, ret = 0;
+ unsigned char output[MBEDCRYPTO_CIPHER_BLKSIZE_MAX];
+
+ cipher_info = mbedcrypto_cipher_info_from_type( cipher_type );
+ if( cipher_info == NULL )
+ {
+ /* Failing at this point must be due to a build issue */
+ ret = MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ goto exit;
+ }
+
+ for( i = 0; i < num_tests; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " %s CMAC #%u: ", testname, i + 1 );
+
+ if( ( ret = mbedcrypto_cipher_cmac( cipher_info, key, keybits, messages,
+ message_lengths[i], output ) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+ goto exit;
+ }
+
+ if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+exit:
+ return( ret );
+}
+
+#if defined(MBEDCRYPTO_AES_C)
+static int test_aes128_cmac_prf( int verbose )
+{
+ int i;
+ int ret;
+ unsigned char output[MBEDCRYPTO_AES_BLOCK_SIZE];
+
+ for( i = 0; i < NB_PRF_TESTS; i++ )
+ {
+ mbedcrypto_printf( " AES CMAC 128 PRF #%u: ", i );
+ ret = mbedcrypto_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
+ if( ret != 0 ||
+ memcmp( output, PRFT[i], MBEDCRYPTO_AES_BLOCK_SIZE ) != 0 )
+ {
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( ret );
+ }
+ else if( verbose != 0 )
+ {
+ mbedcrypto_printf( "passed\n" );
+ }
+ }
+ return( ret );
+}
+#endif /* MBEDCRYPTO_AES_C */
+
+int mbedcrypto_cmac_self_test( int verbose )
+{
+ int ret;
+
+#if defined(MBEDCRYPTO_AES_C)
+ /* AES-128 */
+ if( ( ret = cmac_test_subkeys( verbose,
+ "AES 128",
+ aes_128_key,
+ 128,
+ (const unsigned char*)aes_128_subkeys,
+ MBEDCRYPTO_CIPHER_AES_128_ECB,
+ MBEDCRYPTO_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cmac_test_wth_cipher( verbose,
+ "AES 128",
+ aes_128_key,
+ 128,
+ test_message,
+ aes_message_lengths,
+ (const unsigned char*)aes_128_expected_result,
+ MBEDCRYPTO_CIPHER_AES_128_ECB,
+ MBEDCRYPTO_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* AES-192 */
+ if( ( ret = cmac_test_subkeys( verbose,
+ "AES 192",
+ aes_192_key,
+ 192,
+ (const unsigned char*)aes_192_subkeys,
+ MBEDCRYPTO_CIPHER_AES_192_ECB,
+ MBEDCRYPTO_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cmac_test_wth_cipher( verbose,
+ "AES 192",
+ aes_192_key,
+ 192,
+ test_message,
+ aes_message_lengths,
+ (const unsigned char*)aes_192_expected_result,
+ MBEDCRYPTO_CIPHER_AES_192_ECB,
+ MBEDCRYPTO_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* AES-256 */
+ if( ( ret = cmac_test_subkeys( verbose,
+ "AES 256",
+ aes_256_key,
+ 256,
+ (const unsigned char*)aes_256_subkeys,
+ MBEDCRYPTO_CIPHER_AES_256_ECB,
+ MBEDCRYPTO_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cmac_test_wth_cipher ( verbose,
+ "AES 256",
+ aes_256_key,
+ 256,
+ test_message,
+ aes_message_lengths,
+ (const unsigned char*)aes_256_expected_result,
+ MBEDCRYPTO_CIPHER_AES_256_ECB,
+ MBEDCRYPTO_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+#endif /* MBEDCRYPTO_AES_C */
+
+#if defined(MBEDCRYPTO_DES_C)
+ /* 3DES 2 key */
+ if( ( ret = cmac_test_subkeys( verbose,
+ "3DES 2 key",
+ des3_2key_key,
+ 192,
+ (const unsigned char*)des3_2key_subkeys,
+ MBEDCRYPTO_CIPHER_DES_EDE3_ECB,
+ MBEDCRYPTO_DES3_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cmac_test_wth_cipher( verbose,
+ "3DES 2 key",
+ des3_2key_key,
+ 192,
+ test_message,
+ des3_message_lengths,
+ (const unsigned char*)des3_2key_expected_result,
+ MBEDCRYPTO_CIPHER_DES_EDE3_ECB,
+ MBEDCRYPTO_DES3_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* 3DES 3 key */
+ if( ( ret = cmac_test_subkeys( verbose,
+ "3DES 3 key",
+ des3_3key_key,
+ 192,
+ (const unsigned char*)des3_3key_subkeys,
+ MBEDCRYPTO_CIPHER_DES_EDE3_ECB,
+ MBEDCRYPTO_DES3_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cmac_test_wth_cipher( verbose,
+ "3DES 3 key",
+ des3_3key_key,
+ 192,
+ test_message,
+ des3_message_lengths,
+ (const unsigned char*)des3_3key_expected_result,
+ MBEDCRYPTO_CIPHER_DES_EDE3_ECB,
+ MBEDCRYPTO_DES3_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+#endif /* MBEDCRYPTO_DES_C */
+
+#if defined(MBEDCRYPTO_AES_C)
+ if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 )
+ return( ret );
+#endif /* MBEDCRYPTO_AES_C */
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ return( 0 );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_CMAC_C */
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
new file mode 100644
index 0000000..36ea251
--- /dev/null
+++ b/library/ctr_drbg.c
@@ -0,0 +1,650 @@
+/*
+ * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The NIST SP 800-90 DRBGs are described in the following publication.
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_CTR_DRBG_C)
+
+#include "mbedcrypto/ctr_drbg.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+/*
+ * CTR_DRBG context initialization
+ */
+void mbedcrypto_ctr_drbg_init( mbedcrypto_ctr_drbg_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_ctr_drbg_context ) );
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_mutex_init( &ctx->mutex );
+#endif
+}
+
+/*
+ * Non-public function wrapped by mbedcrypto_ctr_drbg_seed(). Necessary to allow
+ * NIST tests to succeed (which require known length fixed entropy)
+ */
+int mbedcrypto_ctr_drbg_seed_entropy_len(
+ mbedcrypto_ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len,
+ size_t entropy_len )
+{
+ int ret;
+ unsigned char key[MBEDCRYPTO_CTR_DRBG_KEYSIZE];
+
+ memset( key, 0, MBEDCRYPTO_CTR_DRBG_KEYSIZE );
+
+ mbedcrypto_aes_init( &ctx->aes_ctx );
+
+ ctx->f_entropy = f_entropy;
+ ctx->p_entropy = p_entropy;
+
+ ctx->entropy_len = entropy_len;
+ ctx->reseed_interval = MBEDCRYPTO_CTR_DRBG_RESEED_INTERVAL;
+
+ /*
+ * Initialize with an empty key
+ */
+ if( ( ret = mbedcrypto_aes_setkey_enc( &ctx->aes_ctx, key, MBEDCRYPTO_CTR_DRBG_KEYBITS ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = mbedcrypto_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
+ {
+ return( ret );
+ }
+ return( 0 );
+}
+
+int mbedcrypto_ctr_drbg_seed( mbedcrypto_ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len )
+{
+ return( mbedcrypto_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
+ MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN ) );
+}
+
+void mbedcrypto_ctr_drbg_free( mbedcrypto_ctr_drbg_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_mutex_free( &ctx->mutex );
+#endif
+ mbedcrypto_aes_free( &ctx->aes_ctx );
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_ctr_drbg_context ) );
+}
+
+void mbedcrypto_ctr_drbg_set_prediction_resistance( mbedcrypto_ctr_drbg_context *ctx, int resistance )
+{
+ ctx->prediction_resistance = resistance;
+}
+
+void mbedcrypto_ctr_drbg_set_entropy_len( mbedcrypto_ctr_drbg_context *ctx, size_t len )
+{
+ ctx->entropy_len = len;
+}
+
+void mbedcrypto_ctr_drbg_set_reseed_interval( mbedcrypto_ctr_drbg_context *ctx, int interval )
+{
+ ctx->reseed_interval = interval;
+}
+
+static int block_cipher_df( unsigned char *output,
+ const unsigned char *data, size_t data_len )
+{
+ unsigned char buf[MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT + MBEDCRYPTO_CTR_DRBG_BLOCKSIZE + 16];
+ unsigned char tmp[MBEDCRYPTO_CTR_DRBG_SEEDLEN];
+ unsigned char key[MBEDCRYPTO_CTR_DRBG_KEYSIZE];
+ unsigned char chain[MBEDCRYPTO_CTR_DRBG_BLOCKSIZE];
+ unsigned char *p, *iv;
+ mbedcrypto_aes_context aes_ctx;
+ int ret = 0;
+
+ int i, j;
+ size_t buf_len, use_len;
+
+ if( data_len > MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT )
+ return( MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+ memset( buf, 0, MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT + MBEDCRYPTO_CTR_DRBG_BLOCKSIZE + 16 );
+ mbedcrypto_aes_init( &aes_ctx );
+
+ /*
+ * Construct IV (16 bytes) and S in buffer
+ * IV = Counter (in 32-bits) padded to 16 with zeroes
+ * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
+ * data || 0x80
+ * (Total is padded to a multiple of 16-bytes with zeroes)
+ */
+ p = buf + MBEDCRYPTO_CTR_DRBG_BLOCKSIZE;
+ *p++ = ( data_len >> 24 ) & 0xff;
+ *p++ = ( data_len >> 16 ) & 0xff;
+ *p++ = ( data_len >> 8 ) & 0xff;
+ *p++ = ( data_len ) & 0xff;
+ p += 3;
+ *p++ = MBEDCRYPTO_CTR_DRBG_SEEDLEN;
+ memcpy( p, data, data_len );
+ p[data_len] = 0x80;
+
+ buf_len = MBEDCRYPTO_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
+
+ for( i = 0; i < MBEDCRYPTO_CTR_DRBG_KEYSIZE; i++ )
+ key[i] = i;
+
+ if( ( ret = mbedcrypto_aes_setkey_enc( &aes_ctx, key, MBEDCRYPTO_CTR_DRBG_KEYBITS ) ) != 0 )
+ {
+ goto exit;
+ }
+
+ /*
+ * Reduce data to MBEDCRYPTO_CTR_DRBG_SEEDLEN bytes of data
+ */
+ for( j = 0; j < MBEDCRYPTO_CTR_DRBG_SEEDLEN; j += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE )
+ {
+ p = buf;
+ memset( chain, 0, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE );
+ use_len = buf_len;
+
+ while( use_len > 0 )
+ {
+ for( i = 0; i < MBEDCRYPTO_CTR_DRBG_BLOCKSIZE; i++ )
+ chain[i] ^= p[i];
+ p += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE;
+ use_len -= ( use_len >= MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) ?
+ MBEDCRYPTO_CTR_DRBG_BLOCKSIZE : use_len;
+
+ if( ( ret = mbedcrypto_aes_crypt_ecb( &aes_ctx, MBEDCRYPTO_AES_ENCRYPT, chain, chain ) ) != 0 )
+ {
+ goto exit;
+ }
+ }
+
+ memcpy( tmp + j, chain, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE );
+
+ /*
+ * Update IV
+ */
+ buf[3]++;
+ }
+
+ /*
+ * Do final encryption with reduced data
+ */
+ if( ( ret = mbedcrypto_aes_setkey_enc( &aes_ctx, tmp, MBEDCRYPTO_CTR_DRBG_KEYBITS ) ) != 0 )
+ {
+ goto exit;
+ }
+ iv = tmp + MBEDCRYPTO_CTR_DRBG_KEYSIZE;
+ p = output;
+
+ for( j = 0; j < MBEDCRYPTO_CTR_DRBG_SEEDLEN; j += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE )
+ {
+ if( ( ret = mbedcrypto_aes_crypt_ecb( &aes_ctx, MBEDCRYPTO_AES_ENCRYPT, iv, iv ) ) != 0 )
+ {
+ goto exit;
+ }
+ memcpy( p, iv, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE );
+ p += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE;
+ }
+exit:
+ mbedcrypto_aes_free( &aes_ctx );
+ /*
+ * tidy up the stack
+ */
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+ mbedcrypto_platform_zeroize( tmp, sizeof( tmp ) );
+ mbedcrypto_platform_zeroize( key, sizeof( key ) );
+ mbedcrypto_platform_zeroize( chain, sizeof( chain ) );
+ if( 0 != ret )
+ {
+ /*
+ * wipe partial seed from memory
+ */
+ mbedcrypto_platform_zeroize( output, MBEDCRYPTO_CTR_DRBG_SEEDLEN );
+ }
+
+ return( ret );
+}
+
+static int ctr_drbg_update_internal( mbedcrypto_ctr_drbg_context *ctx,
+ const unsigned char data[MBEDCRYPTO_CTR_DRBG_SEEDLEN] )
+{
+ unsigned char tmp[MBEDCRYPTO_CTR_DRBG_SEEDLEN];
+ unsigned char *p = tmp;
+ int i, j;
+ int ret = 0;
+
+ memset( tmp, 0, MBEDCRYPTO_CTR_DRBG_SEEDLEN );
+
+ for( j = 0; j < MBEDCRYPTO_CTR_DRBG_SEEDLEN; j += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE )
+ {
+ /*
+ * Increase counter
+ */
+ for( i = MBEDCRYPTO_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
+ if( ++ctx->counter[i - 1] != 0 )
+ break;
+
+ /*
+ * Crypt counter block
+ */
+ if( ( ret = mbedcrypto_aes_crypt_ecb( &ctx->aes_ctx, MBEDCRYPTO_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ p += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE;
+ }
+
+ for( i = 0; i < MBEDCRYPTO_CTR_DRBG_SEEDLEN; i++ )
+ tmp[i] ^= data[i];
+
+ /*
+ * Update key and counter
+ */
+ if( ( ret = mbedcrypto_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDCRYPTO_CTR_DRBG_KEYBITS ) ) != 0 )
+ {
+ return( ret );
+ }
+ memcpy( ctx->counter, tmp + MBEDCRYPTO_CTR_DRBG_KEYSIZE, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE );
+
+ return( 0 );
+}
+
+void mbedcrypto_ctr_drbg_update( mbedcrypto_ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len )
+{
+ unsigned char add_input[MBEDCRYPTO_CTR_DRBG_SEEDLEN];
+
+ if( add_len > 0 )
+ {
+ /* MAX_INPUT would be more logical here, but we have to match
+ * block_cipher_df()'s limits since we can't propagate errors */
+ if( add_len > MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT )
+ add_len = MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT;
+
+ block_cipher_df( add_input, additional, add_len );
+ ctr_drbg_update_internal( ctx, add_input );
+ }
+}
+
+int mbedcrypto_ctr_drbg_reseed( mbedcrypto_ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t len )
+{
+ unsigned char seed[MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT];
+ size_t seedlen = 0;
+ int ret;
+
+ if( ctx->entropy_len > MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT ||
+ len > MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
+ return( MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+ memset( seed, 0, MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT );
+
+ /*
+ * Gather entropy_len bytes of entropy to seed state
+ */
+ if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
+ ctx->entropy_len ) )
+ {
+ return( MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+ }
+
+ seedlen += ctx->entropy_len;
+
+ /*
+ * Add additional data
+ */
+ if( additional && len )
+ {
+ memcpy( seed + seedlen, additional, len );
+ seedlen += len;
+ }
+
+ /*
+ * Reduce to 384 bits
+ */
+ if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /*
+ * Update state
+ */
+ if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
+ {
+ return( ret );
+ }
+ ctx->reseed_counter = 1;
+
+ return( 0 );
+}
+
+int mbedcrypto_ctr_drbg_random_with_add( void *p_rng,
+ unsigned char *output, size_t output_len,
+ const unsigned char *additional, size_t add_len )
+{
+ int ret = 0;
+ mbedcrypto_ctr_drbg_context *ctx = (mbedcrypto_ctr_drbg_context *) p_rng;
+ unsigned char add_input[MBEDCRYPTO_CTR_DRBG_SEEDLEN];
+ unsigned char *p = output;
+ unsigned char tmp[MBEDCRYPTO_CTR_DRBG_BLOCKSIZE];
+ int i;
+ size_t use_len;
+
+ if( output_len > MBEDCRYPTO_CTR_DRBG_MAX_REQUEST )
+ return( MBEDCRYPTO_ERR_CTR_DRBG_REQUEST_TOO_BIG );
+
+ if( add_len > MBEDCRYPTO_CTR_DRBG_MAX_INPUT )
+ return( MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+ memset( add_input, 0, MBEDCRYPTO_CTR_DRBG_SEEDLEN );
+
+ if( ctx->reseed_counter > ctx->reseed_interval ||
+ ctx->prediction_resistance )
+ {
+ if( ( ret = mbedcrypto_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
+ {
+ return( ret );
+ }
+ add_len = 0;
+ }
+
+ if( add_len > 0 )
+ {
+ if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
+ {
+ return( ret );
+ }
+ if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
+ {
+ return( ret );
+ }
+ }
+
+ while( output_len > 0 )
+ {
+ /*
+ * Increase counter
+ */
+ for( i = MBEDCRYPTO_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
+ if( ++ctx->counter[i - 1] != 0 )
+ break;
+
+ /*
+ * Crypt counter block
+ */
+ if( ( ret = mbedcrypto_aes_crypt_ecb( &ctx->aes_ctx, MBEDCRYPTO_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ use_len = ( output_len > MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) ? MBEDCRYPTO_CTR_DRBG_BLOCKSIZE :
+ output_len;
+ /*
+ * Copy random block to destination
+ */
+ memcpy( p, tmp, use_len );
+ p += use_len;
+ output_len -= use_len;
+ }
+
+ if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ ctx->reseed_counter++;
+
+ return( 0 );
+}
+
+int mbedcrypto_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
+{
+ int ret;
+ mbedcrypto_ctr_drbg_context *ctx = (mbedcrypto_ctr_drbg_context *) p_rng;
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( ( ret = mbedcrypto_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ ret = mbedcrypto_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( mbedcrypto_mutex_unlock( &ctx->mutex ) != 0 )
+ return( MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+ return( ret );
+}
+
+#if defined(MBEDCRYPTO_FS_IO)
+int mbedcrypto_ctr_drbg_write_seed_file( mbedcrypto_ctr_drbg_context *ctx, const char *path )
+{
+ int ret = MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR;
+ FILE *f;
+ unsigned char buf[ MBEDCRYPTO_CTR_DRBG_MAX_INPUT ];
+
+ if( ( f = fopen( path, "wb" ) ) == NULL )
+ return( MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR );
+
+ if( ( ret = mbedcrypto_ctr_drbg_random( ctx, buf, MBEDCRYPTO_CTR_DRBG_MAX_INPUT ) ) != 0 )
+ goto exit;
+
+ if( fwrite( buf, 1, MBEDCRYPTO_CTR_DRBG_MAX_INPUT, f ) != MBEDCRYPTO_CTR_DRBG_MAX_INPUT )
+ ret = MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR;
+ else
+ ret = 0;
+
+exit:
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+
+ fclose( f );
+ return( ret );
+}
+
+int mbedcrypto_ctr_drbg_update_seed_file( mbedcrypto_ctr_drbg_context *ctx, const char *path )
+{
+ int ret = 0;
+ FILE *f;
+ size_t n;
+ unsigned char buf[ MBEDCRYPTO_CTR_DRBG_MAX_INPUT ];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR );
+
+ fseek( f, 0, SEEK_END );
+ n = (size_t) ftell( f );
+ fseek( f, 0, SEEK_SET );
+
+ if( n > MBEDCRYPTO_CTR_DRBG_MAX_INPUT )
+ {
+ fclose( f );
+ return( MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG );
+ }
+
+ if( fread( buf, 1, n, f ) != n )
+ ret = MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR;
+ else
+ mbedcrypto_ctr_drbg_update( ctx, buf, n );
+
+ fclose( f );
+
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+
+ if( ret != 0 )
+ return( ret );
+
+ return( mbedcrypto_ctr_drbg_write_seed_file( ctx, path ) );
+}
+#endif /* MBEDCRYPTO_FS_IO */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+static const unsigned char entropy_source_pr[96] =
+ { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
+ 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
+ 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
+ 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
+ 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
+ 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
+ 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
+ 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
+ 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
+ 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
+ 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
+ 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
+
+static const unsigned char entropy_source_nopr[64] =
+ { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
+ 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
+ 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
+ 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
+ 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
+ 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
+ 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
+ 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
+
+static const unsigned char nonce_pers_pr[16] =
+ { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
+ 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
+
+static const unsigned char nonce_pers_nopr[16] =
+ { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
+ 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
+
+static const unsigned char result_pr[16] =
+ { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
+ 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
+
+static const unsigned char result_nopr[16] =
+ { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
+ 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
+
+static size_t test_offset;
+static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
+ size_t len )
+{
+ const unsigned char *p = data;
+ memcpy( buf, p + test_offset, len );
+ test_offset += len;
+ return( 0 );
+}
+
+#define CHK( c ) if( (c) != 0 ) \
+ { \
+ if( verbose != 0 ) \
+ mbedcrypto_printf( "failed\n" ); \
+ return( 1 ); \
+ }
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_ctr_drbg_self_test( int verbose )
+{
+ mbedcrypto_ctr_drbg_context ctx;
+ unsigned char buf[16];
+
+ mbedcrypto_ctr_drbg_init( &ctx );
+
+ /*
+ * Based on a NIST CTR_DRBG test vector (PR = True)
+ */
+ if( verbose != 0 )
+ mbedcrypto_printf( " CTR_DRBG (PR = TRUE) : " );
+
+ test_offset = 0;
+ CHK( mbedcrypto_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
+ (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
+ mbedcrypto_ctr_drbg_set_prediction_resistance( &ctx, MBEDCRYPTO_CTR_DRBG_PR_ON );
+ CHK( mbedcrypto_ctr_drbg_random( &ctx, buf, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) );
+ CHK( mbedcrypto_ctr_drbg_random( &ctx, buf, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) );
+ CHK( memcmp( buf, result_pr, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) );
+
+ mbedcrypto_ctr_drbg_free( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ /*
+ * Based on a NIST CTR_DRBG test vector (PR = FALSE)
+ */
+ if( verbose != 0 )
+ mbedcrypto_printf( " CTR_DRBG (PR = FALSE): " );
+
+ mbedcrypto_ctr_drbg_init( &ctx );
+
+ test_offset = 0;
+ CHK( mbedcrypto_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
+ (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
+ CHK( mbedcrypto_ctr_drbg_random( &ctx, buf, 16 ) );
+ CHK( mbedcrypto_ctr_drbg_reseed( &ctx, NULL, 0 ) );
+ CHK( mbedcrypto_ctr_drbg_random( &ctx, buf, 16 ) );
+ CHK( memcmp( buf, result_nopr, 16 ) );
+
+ mbedcrypto_ctr_drbg_free( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_CTR_DRBG_C */
diff --git a/library/des.c b/library/des.c
new file mode 100644
index 0000000..b967dab
--- /dev/null
+++ b/library/des.c
@@ -0,0 +1,1057 @@
+/*
+ * FIPS-46-3 compliant Triple-DES implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * DES, on which TDES is based, was originally designed by Horst Feistel
+ * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
+ *
+ * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_DES_C)
+
+#include "mbedcrypto/des.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_DES_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * Expanded DES S-boxes
+ */
+static const uint32_t SB1[64] =
+{
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404,
+ 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400, 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400, 0x01000400, 0x00010400,
+ 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004,
+ 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404, 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000, 0x00010400, 0x01000004,
+ 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404,
+ 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400, 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400, 0x00000000, 0x01010004
+};
+
+static const uint32_t SB2[64] =
+{
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020,
+ 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020, 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020, 0x80008020, 0x00000000,
+ 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000,
+ 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020, 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000, 0x00000020, 0x80108020,
+ 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020,
+ 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000, 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020, 0x80108020, 0x00108000
+};
+
+static const uint32_t SB3[64] =
+{
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008,
+ 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008, 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008, 0x08020200, 0x00000200,
+ 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208,
+ 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000, 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008, 0x08020208, 0x08000200,
+ 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208,
+ 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208, 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008, 0x08020008, 0x00020200
+};
+
+static const uint32_t SB4[64] =
+{
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080,
+ 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080, 0x00800081, 0x00000001,
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000,
+ 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002000, 0x00802080
+};
+
+static const uint32_t SB5[64] =
+{
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100,
+ 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000, 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000, 0x40080000, 0x00000000,
+ 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000,
+ 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100, 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000, 0x42080000, 0x02080100,
+ 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100,
+ 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100, 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000, 0x02080100, 0x40000100
+};
+
+static const uint32_t SB6[64] =
+{
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010,
+ 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010, 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010, 0x20004010, 0x00004000,
+ 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000,
+ 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010, 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000, 0x20000000, 0x00004010,
+ 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010,
+ 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010, 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000, 0x00400010, 0x20004010
+};
+
+static const uint32_t SB7[64] =
+{
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000,
+ 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000, 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802, 0x00200002, 0x04000800,
+ 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802,
+ 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800, 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000, 0x04000800, 0x00200000,
+ 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000,
+ 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802, 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800, 0x00000800, 0x00200002
+};
+
+static const uint32_t SB8[64] =
+{
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040,
+ 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000, 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040, 0x10001000, 0x00001040,
+ 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040,
+ 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000, 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040, 0x10000040, 0x10040000,
+ 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040,
+ 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000, 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040, 0x10000000, 0x10041000
+};
+
+/*
+ * PC1: left and right halves bit-swap
+ */
+static const uint32_t LHs[16] =
+{
+ 0x00000000, 0x00000001, 0x00000100, 0x00000101,
+ 0x00010000, 0x00010001, 0x00010100, 0x00010101,
+ 0x01000000, 0x01000001, 0x01000100, 0x01000101,
+ 0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const uint32_t RHs[16] =
+{
+ 0x00000000, 0x01000000, 0x00010000, 0x01010000,
+ 0x00000100, 0x01000100, 0x00010100, 0x01010100,
+ 0x00000001, 0x01000001, 0x00010001, 0x01010001,
+ 0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+/*
+ * Initial Permutation macro
+ */
+#define DES_IP(X,Y) \
+{ \
+ T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
+ T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
+ T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
+ T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
+ Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \
+ T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \
+ X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \
+}
+
+/*
+ * Final Permutation macro
+ */
+#define DES_FP(X,Y) \
+{ \
+ X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \
+ T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \
+ Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \
+ T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \
+ T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \
+ T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \
+ T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \
+}
+
+/*
+ * DES round macro
+ */
+#define DES_ROUND(X,Y) \
+{ \
+ T = *SK++ ^ X; \
+ Y ^= SB8[ (T ) & 0x3F ] ^ \
+ SB6[ (T >> 8) & 0x3F ] ^ \
+ SB4[ (T >> 16) & 0x3F ] ^ \
+ SB2[ (T >> 24) & 0x3F ]; \
+ \
+ T = *SK++ ^ ((X << 28) | (X >> 4)); \
+ Y ^= SB7[ (T ) & 0x3F ] ^ \
+ SB5[ (T >> 8) & 0x3F ] ^ \
+ SB3[ (T >> 16) & 0x3F ] ^ \
+ SB1[ (T >> 24) & 0x3F ]; \
+}
+
+#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; }
+
+void mbedcrypto_des_init( mbedcrypto_des_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_des_context ) );
+}
+
+void mbedcrypto_des_free( mbedcrypto_des_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_des_context ) );
+}
+
+void mbedcrypto_des3_init( mbedcrypto_des3_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_des3_context ) );
+}
+
+void mbedcrypto_des3_free( mbedcrypto_des3_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_des3_context ) );
+}
+
+static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8,
+ 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
+ 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
+ 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
+ 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
+ 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
+ 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
+ 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
+ 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
+ 254 };
+
+void mbedcrypto_des_key_set_parity( unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] )
+{
+ int i;
+
+ for( i = 0; i < MBEDCRYPTO_DES_KEY_SIZE; i++ )
+ key[i] = odd_parity_table[key[i] / 2];
+}
+
+/*
+ * Check the given key's parity, returns 1 on failure, 0 on SUCCESS
+ */
+int mbedcrypto_des_key_check_key_parity( const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] )
+{
+ int i;
+
+ for( i = 0; i < MBEDCRYPTO_DES_KEY_SIZE; i++ )
+ if( key[i] != odd_parity_table[key[i] / 2] )
+ return( 1 );
+
+ return( 0 );
+}
+
+/*
+ * Table of weak and semi-weak keys
+ *
+ * Source: http://en.wikipedia.org/wiki/Weak_key
+ *
+ * Weak:
+ * Alternating ones + zeros (0x0101010101010101)
+ * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
+ * '0xE0E0E0E0F1F1F1F1'
+ * '0x1F1F1F1F0E0E0E0E'
+ *
+ * Semi-weak:
+ * 0x011F011F010E010E and 0x1F011F010E010E01
+ * 0x01E001E001F101F1 and 0xE001E001F101F101
+ * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
+ * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
+ * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
+ * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
+ *
+ */
+
+#define WEAK_KEY_COUNT 16
+
+static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDCRYPTO_DES_KEY_SIZE] =
+{
+ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+ { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
+ { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
+ { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
+
+ { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
+ { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
+ { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
+ { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
+ { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
+ { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
+ { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
+ { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
+ { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
+ { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
+ { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
+ { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
+};
+
+int mbedcrypto_des_key_check_weak( const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] )
+{
+ int i;
+
+ for( i = 0; i < WEAK_KEY_COUNT; i++ )
+ if( memcmp( weak_key_table[i], key, MBEDCRYPTO_DES_KEY_SIZE) == 0 )
+ return( 1 );
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DES_SETKEY_ALT)
+void mbedcrypto_des_setkey( uint32_t SK[32], const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] )
+{
+ int i;
+ uint32_t X, Y, T;
+
+ GET_UINT32_BE( X, key, 0 );
+ GET_UINT32_BE( Y, key, 4 );
+
+ /*
+ * Permuted Choice 1
+ */
+ T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4);
+ T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T );
+
+ X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2)
+ | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] )
+ | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
+ | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
+
+ Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2)
+ | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] )
+ | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
+ | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
+
+ X &= 0x0FFFFFFF;
+ Y &= 0x0FFFFFFF;
+
+ /*
+ * calculate subkeys
+ */
+ for( i = 0; i < 16; i++ )
+ {
+ if( i < 2 || i == 8 || i == 15 )
+ {
+ X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF;
+ Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF;
+ }
+ else
+ {
+ X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF;
+ Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF;
+ }
+
+ *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000)
+ | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
+ | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000)
+ | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000)
+ | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000)
+ | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000)
+ | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400)
+ | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100)
+ | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010)
+ | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004)
+ | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
+
+ *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
+ | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
+ | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000)
+ | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
+ | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000)
+ | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000)
+ | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000)
+ | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400)
+ | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100)
+ | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011)
+ | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002);
+ }
+}
+#endif /* !MBEDCRYPTO_DES_SETKEY_ALT */
+
+/*
+ * DES key schedule (56-bit, encryption)
+ */
+int mbedcrypto_des_setkey_enc( mbedcrypto_des_context *ctx, const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] )
+{
+ mbedcrypto_des_setkey( ctx->sk, key );
+
+ return( 0 );
+}
+
+/*
+ * DES key schedule (56-bit, decryption)
+ */
+int mbedcrypto_des_setkey_dec( mbedcrypto_des_context *ctx, const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE] )
+{
+ int i;
+
+ mbedcrypto_des_setkey( ctx->sk, key );
+
+ for( i = 0; i < 16; i += 2 )
+ {
+ SWAP( ctx->sk[i ], ctx->sk[30 - i] );
+ SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
+ }
+
+ return( 0 );
+}
+
+static void des3_set2key( uint32_t esk[96],
+ uint32_t dsk[96],
+ const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE*2] )
+{
+ int i;
+
+ mbedcrypto_des_setkey( esk, key );
+ mbedcrypto_des_setkey( dsk + 32, key + 8 );
+
+ for( i = 0; i < 32; i += 2 )
+ {
+ dsk[i ] = esk[30 - i];
+ dsk[i + 1] = esk[31 - i];
+
+ esk[i + 32] = dsk[62 - i];
+ esk[i + 33] = dsk[63 - i];
+
+ esk[i + 64] = esk[i ];
+ esk[i + 65] = esk[i + 1];
+
+ dsk[i + 64] = dsk[i ];
+ dsk[i + 65] = dsk[i + 1];
+ }
+}
+
+/*
+ * Triple-DES key schedule (112-bit, encryption)
+ */
+int mbedcrypto_des3_set2key_enc( mbedcrypto_des3_context *ctx,
+ const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 2] )
+{
+ uint32_t sk[96];
+
+ des3_set2key( ctx->sk, sk, key );
+ mbedcrypto_platform_zeroize( sk, sizeof( sk ) );
+
+ return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (112-bit, decryption)
+ */
+int mbedcrypto_des3_set2key_dec( mbedcrypto_des3_context *ctx,
+ const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 2] )
+{
+ uint32_t sk[96];
+
+ des3_set2key( sk, ctx->sk, key );
+ mbedcrypto_platform_zeroize( sk, sizeof( sk ) );
+
+ return( 0 );
+}
+
+static void des3_set3key( uint32_t esk[96],
+ uint32_t dsk[96],
+ const unsigned char key[24] )
+{
+ int i;
+
+ mbedcrypto_des_setkey( esk, key );
+ mbedcrypto_des_setkey( dsk + 32, key + 8 );
+ mbedcrypto_des_setkey( esk + 64, key + 16 );
+
+ for( i = 0; i < 32; i += 2 )
+ {
+ dsk[i ] = esk[94 - i];
+ dsk[i + 1] = esk[95 - i];
+
+ esk[i + 32] = dsk[62 - i];
+ esk[i + 33] = dsk[63 - i];
+
+ dsk[i + 64] = esk[30 - i];
+ dsk[i + 65] = esk[31 - i];
+ }
+}
+
+/*
+ * Triple-DES key schedule (168-bit, encryption)
+ */
+int mbedcrypto_des3_set3key_enc( mbedcrypto_des3_context *ctx,
+ const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 3] )
+{
+ uint32_t sk[96];
+
+ des3_set3key( ctx->sk, sk, key );
+ mbedcrypto_platform_zeroize( sk, sizeof( sk ) );
+
+ return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (168-bit, decryption)
+ */
+int mbedcrypto_des3_set3key_dec( mbedcrypto_des3_context *ctx,
+ const unsigned char key[MBEDCRYPTO_DES_KEY_SIZE * 3] )
+{
+ uint32_t sk[96];
+
+ des3_set3key( sk, ctx->sk, key );
+ mbedcrypto_platform_zeroize( sk, sizeof( sk ) );
+
+ return( 0 );
+}
+
+/*
+ * DES-ECB block encryption/decryption
+ */
+#if !defined(MBEDCRYPTO_DES_CRYPT_ECB_ALT)
+int mbedcrypto_des_crypt_ecb( mbedcrypto_des_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] )
+{
+ int i;
+ uint32_t X, Y, T, *SK;
+
+ SK = ctx->sk;
+
+ GET_UINT32_BE( X, input, 0 );
+ GET_UINT32_BE( Y, input, 4 );
+
+ DES_IP( X, Y );
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( Y, X );
+ DES_ROUND( X, Y );
+ }
+
+ DES_FP( Y, X );
+
+ PUT_UINT32_BE( Y, output, 0 );
+ PUT_UINT32_BE( X, output, 4 );
+
+ return( 0 );
+}
+#endif /* !MBEDCRYPTO_DES_CRYPT_ECB_ALT */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/*
+ * DES-CBC buffer encryption/decryption
+ */
+int mbedcrypto_des_crypt_cbc( mbedcrypto_des_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[8];
+
+ if( length % 8 )
+ return( MBEDCRYPTO_ERR_DES_INVALID_INPUT_LENGTH );
+
+ if( mode == MBEDCRYPTO_DES_ENCRYPT )
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ mbedcrypto_des_crypt_ecb( ctx, output, output );
+ memcpy( iv, output, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+ else /* MBEDCRYPTO_DES_DECRYPT */
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 8 );
+ mbedcrypto_des_crypt_ecb( ctx, input, output );
+
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+/*
+ * 3DES-ECB block encryption/decryption
+ */
+#if !defined(MBEDCRYPTO_DES3_CRYPT_ECB_ALT)
+int mbedcrypto_des3_crypt_ecb( mbedcrypto_des3_context *ctx,
+ const unsigned char input[8],
+ unsigned char output[8] )
+{
+ int i;
+ uint32_t X, Y, T, *SK;
+
+ SK = ctx->sk;
+
+ GET_UINT32_BE( X, input, 0 );
+ GET_UINT32_BE( Y, input, 4 );
+
+ DES_IP( X, Y );
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( Y, X );
+ DES_ROUND( X, Y );
+ }
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( X, Y );
+ DES_ROUND( Y, X );
+ }
+
+ for( i = 0; i < 8; i++ )
+ {
+ DES_ROUND( Y, X );
+ DES_ROUND( X, Y );
+ }
+
+ DES_FP( Y, X );
+
+ PUT_UINT32_BE( Y, output, 0 );
+ PUT_UINT32_BE( X, output, 4 );
+
+ return( 0 );
+}
+#endif /* !MBEDCRYPTO_DES3_CRYPT_ECB_ALT */
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/*
+ * 3DES-CBC buffer encryption/decryption
+ */
+int mbedcrypto_des3_crypt_cbc( mbedcrypto_des3_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[8],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[8];
+
+ if( length % 8 )
+ return( MBEDCRYPTO_ERR_DES_INVALID_INPUT_LENGTH );
+
+ if( mode == MBEDCRYPTO_DES_ENCRYPT )
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ mbedcrypto_des3_crypt_ecb( ctx, output, output );
+ memcpy( iv, output, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+ else /* MBEDCRYPTO_DES_DECRYPT */
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 8 );
+ mbedcrypto_des3_crypt_ecb( ctx, input, output );
+
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+#endif /* !MBEDCRYPTO_DES_ALT */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/*
+ * DES and 3DES test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip
+ */
+static const unsigned char des3_test_keys[24] =
+{
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+ 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+ 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+
+static const unsigned char des3_test_buf[8] =
+{
+ 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
+};
+
+static const unsigned char des3_test_ecb_dec[3][8] =
+{
+ { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
+ { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
+ { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
+};
+
+static const unsigned char des3_test_ecb_enc[3][8] =
+{
+ { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
+ { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
+ { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
+};
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+static const unsigned char des3_test_iv[8] =
+{
+ 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
+};
+
+static const unsigned char des3_test_cbc_dec[3][8] =
+{
+ { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
+ { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
+ { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
+};
+
+static const unsigned char des3_test_cbc_enc[3][8] =
+{
+ { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
+ { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
+ { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
+};
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_des_self_test( int verbose )
+{
+ int i, j, u, v, ret = 0;
+ mbedcrypto_des_context ctx;
+ mbedcrypto_des3_context ctx3;
+ unsigned char buf[8];
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ unsigned char prv[8];
+ unsigned char iv[8];
+#endif
+
+ mbedcrypto_des_init( &ctx );
+ mbedcrypto_des3_init( &ctx3 );
+ /*
+ * ECB mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " DES%c-ECB-%3d (%s): ",
+ ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+ ( v == MBEDCRYPTO_DES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( buf, des3_test_buf, 8 );
+
+ switch( i )
+ {
+ case 0:
+ mbedcrypto_des_setkey_dec( &ctx, des3_test_keys );
+ break;
+
+ case 1:
+ mbedcrypto_des_setkey_enc( &ctx, des3_test_keys );
+ break;
+
+ case 2:
+ mbedcrypto_des3_set2key_dec( &ctx3, des3_test_keys );
+ break;
+
+ case 3:
+ mbedcrypto_des3_set2key_enc( &ctx3, des3_test_keys );
+ break;
+
+ case 4:
+ mbedcrypto_des3_set3key_dec( &ctx3, des3_test_keys );
+ break;
+
+ case 5:
+ mbedcrypto_des3_set3key_enc( &ctx3, des3_test_keys );
+ break;
+
+ default:
+ return( 1 );
+ }
+
+ for( j = 0; j < 10000; j++ )
+ {
+ if( u == 0 )
+ mbedcrypto_des_crypt_ecb( &ctx, buf, buf );
+ else
+ mbedcrypto_des3_crypt_ecb( &ctx3, buf, buf );
+ }
+
+ if( ( v == MBEDCRYPTO_DES_DECRYPT &&
+ memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
+ ( v != MBEDCRYPTO_DES_DECRYPT &&
+ memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+ /*
+ * CBC mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " DES%c-CBC-%3d (%s): ",
+ ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+ ( v == MBEDCRYPTO_DES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( iv, des3_test_iv, 8 );
+ memcpy( prv, des3_test_iv, 8 );
+ memcpy( buf, des3_test_buf, 8 );
+
+ switch( i )
+ {
+ case 0:
+ mbedcrypto_des_setkey_dec( &ctx, des3_test_keys );
+ break;
+
+ case 1:
+ mbedcrypto_des_setkey_enc( &ctx, des3_test_keys );
+ break;
+
+ case 2:
+ mbedcrypto_des3_set2key_dec( &ctx3, des3_test_keys );
+ break;
+
+ case 3:
+ mbedcrypto_des3_set2key_enc( &ctx3, des3_test_keys );
+ break;
+
+ case 4:
+ mbedcrypto_des3_set3key_dec( &ctx3, des3_test_keys );
+ break;
+
+ case 5:
+ mbedcrypto_des3_set3key_enc( &ctx3, des3_test_keys );
+ break;
+
+ default:
+ return( 1 );
+ }
+
+ if( v == MBEDCRYPTO_DES_DECRYPT )
+ {
+ for( j = 0; j < 10000; j++ )
+ {
+ if( u == 0 )
+ mbedcrypto_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+ else
+ mbedcrypto_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+ }
+ }
+ else
+ {
+ for( j = 0; j < 10000; j++ )
+ {
+ unsigned char tmp[8];
+
+ if( u == 0 )
+ mbedcrypto_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+ else
+ mbedcrypto_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+
+ memcpy( tmp, prv, 8 );
+ memcpy( prv, buf, 8 );
+ memcpy( buf, tmp, 8 );
+ }
+
+ memcpy( buf, prv, 8 );
+ }
+
+ if( ( v == MBEDCRYPTO_DES_DECRYPT &&
+ memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
+ ( v != MBEDCRYPTO_DES_DECRYPT &&
+ memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+exit:
+ mbedcrypto_des_free( &ctx );
+ mbedcrypto_des3_free( &ctx3 );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_DES_C */
diff --git a/library/ecdsa.c b/library/ecdsa.c
new file mode 100644
index 0000000..a05cae4
--- /dev/null
+++ b/library/ecdsa.c
@@ -0,0 +1,461 @@
+/*
+ * Elliptic curve DSA
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * References:
+ *
+ * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+
+#include "mbedcrypto/ecdsa.h"
+#include "mbedcrypto/asn1write.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_ECDSA_DETERMINISTIC)
+#include "mbedcrypto/hmac_drbg.h"
+#endif
+
+/*
+ * Derive a suitable integer for group grp from a buffer of length len
+ * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
+ */
+static int derive_mpi( const mbedcrypto_ecp_group *grp, mbedcrypto_mpi *x,
+ const unsigned char *buf, size_t blen )
+{
+ int ret;
+ size_t n_size = ( grp->nbits + 7 ) / 8;
+ size_t use_size = blen > n_size ? n_size : blen;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( x, buf, use_size ) );
+ if( use_size * 8 > grp->nbits )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( x, use_size * 8 - grp->nbits ) );
+
+ /* While at it, reduce modulo N */
+ if( mbedcrypto_mpi_cmp_mpi( x, &grp->N ) >= 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( x, x, &grp->N ) );
+
+cleanup:
+ return( ret );
+}
+
+#if !defined(MBEDCRYPTO_ECDSA_SIGN_ALT)
+/*
+ * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
+ * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
+ */
+int mbedcrypto_ecdsa_sign( mbedcrypto_ecp_group *grp, mbedcrypto_mpi *r, mbedcrypto_mpi *s,
+ const mbedcrypto_mpi *d, const unsigned char *buf, size_t blen,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ int ret, key_tries, sign_tries, blind_tries;
+ mbedcrypto_ecp_point R;
+ mbedcrypto_mpi k, e, t;
+
+ /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
+ if( grp->N.p == NULL )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ /* Make sure d is in range 1..n-1 */
+ if( mbedcrypto_mpi_cmp_int( d, 1 ) < 0 || mbedcrypto_mpi_cmp_mpi( d, &grp->N ) >= 0 )
+ return( MBEDCRYPTO_ERR_ECP_INVALID_KEY );
+
+ mbedcrypto_ecp_point_init( &R );
+ mbedcrypto_mpi_init( &k ); mbedcrypto_mpi_init( &e ); mbedcrypto_mpi_init( &t );
+
+ sign_tries = 0;
+ do
+ {
+ /*
+ * Steps 1-3: generate a suitable ephemeral keypair
+ * and set r = xR mod n
+ */
+ key_tries = 0;
+ do
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( r, &R.X, &grp->N ) );
+
+ if( key_tries++ > 10 )
+ {
+ ret = MBEDCRYPTO_ERR_ECP_RANDOM_FAILED;
+ goto cleanup;
+ }
+ }
+ while( mbedcrypto_mpi_cmp_int( r, 0 ) == 0 );
+
+ /*
+ * Step 5: derive MPI from hashed message
+ */
+ MBEDCRYPTO_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
+
+ /*
+ * Generate a random value to blind inv_mod in next step,
+ * avoiding a potential timing leak.
+ */
+ blind_tries = 0;
+ do
+ {
+ size_t n_size = ( grp->nbits + 7 ) / 8;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( &t, n_size, f_rng, p_rng ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
+
+ /* See mbedcrypto_ecp_gen_keypair() */
+ if( ++blind_tries > 30 )
+ return( MBEDCRYPTO_ERR_ECP_RANDOM_FAILED );
+ }
+ while( mbedcrypto_mpi_cmp_int( &t, 1 ) < 0 ||
+ mbedcrypto_mpi_cmp_mpi( &t, &grp->N ) >= 0 );
+
+ /*
+ * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( s, r, d ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &e, &e, s ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &e, &e, &t ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &k, &k, &t ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_inv_mod( s, &k, &grp->N ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( s, s, &e ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( s, s, &grp->N ) );
+
+ if( sign_tries++ > 10 )
+ {
+ ret = MBEDCRYPTO_ERR_ECP_RANDOM_FAILED;
+ goto cleanup;
+ }
+ }
+ while( mbedcrypto_mpi_cmp_int( s, 0 ) == 0 );
+
+cleanup:
+ mbedcrypto_ecp_point_free( &R );
+ mbedcrypto_mpi_free( &k ); mbedcrypto_mpi_free( &e ); mbedcrypto_mpi_free( &t );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECDSA_SIGN_ALT */
+
+#if defined(MBEDCRYPTO_ECDSA_DETERMINISTIC)
+/*
+ * Deterministic signature wrapper
+ */
+int mbedcrypto_ecdsa_sign_det( mbedcrypto_ecp_group *grp, mbedcrypto_mpi *r, mbedcrypto_mpi *s,
+ const mbedcrypto_mpi *d, const unsigned char *buf, size_t blen,
+ mbedcrypto_md_type_t md_alg )
+{
+ int ret;
+ mbedcrypto_hmac_drbg_context rng_ctx;
+ unsigned char data[2 * MBEDCRYPTO_ECP_MAX_BYTES];
+ size_t grp_len = ( grp->nbits + 7 ) / 8;
+ const mbedcrypto_md_info_t *md_info;
+ mbedcrypto_mpi h;
+
+ if( ( md_info = mbedcrypto_md_info_from_type( md_alg ) ) == NULL )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ mbedcrypto_mpi_init( &h );
+ mbedcrypto_hmac_drbg_init( &rng_ctx );
+
+ /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( d, data, grp_len ) );
+ MBEDCRYPTO_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &h, data + grp_len, grp_len ) );
+ mbedcrypto_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len );
+
+ ret = mbedcrypto_ecdsa_sign( grp, r, s, d, buf, blen,
+ mbedcrypto_hmac_drbg_random, &rng_ctx );
+
+cleanup:
+ mbedcrypto_hmac_drbg_free( &rng_ctx );
+ mbedcrypto_mpi_free( &h );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECDSA_DETERMINISTIC */
+
+#if !defined(MBEDCRYPTO_ECDSA_VERIFY_ALT)
+/*
+ * Verify ECDSA signature of hashed message (SEC1 4.1.4)
+ * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
+ */
+int mbedcrypto_ecdsa_verify( mbedcrypto_ecp_group *grp,
+ const unsigned char *buf, size_t blen,
+ const mbedcrypto_ecp_point *Q, const mbedcrypto_mpi *r, const mbedcrypto_mpi *s)
+{
+ int ret;
+ mbedcrypto_mpi e, s_inv, u1, u2;
+ mbedcrypto_ecp_point R;
+
+ mbedcrypto_ecp_point_init( &R );
+ mbedcrypto_mpi_init( &e ); mbedcrypto_mpi_init( &s_inv ); mbedcrypto_mpi_init( &u1 ); mbedcrypto_mpi_init( &u2 );
+
+ /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
+ if( grp->N.p == NULL )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ /*
+ * Step 1: make sure r and s are in range 1..n-1
+ */
+ if( mbedcrypto_mpi_cmp_int( r, 1 ) < 0 || mbedcrypto_mpi_cmp_mpi( r, &grp->N ) >= 0 ||
+ mbedcrypto_mpi_cmp_int( s, 1 ) < 0 || mbedcrypto_mpi_cmp_mpi( s, &grp->N ) >= 0 )
+ {
+ ret = MBEDCRYPTO_ERR_ECP_VERIFY_FAILED;
+ goto cleanup;
+ }
+
+ /*
+ * Additional precaution: make sure Q is valid
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_check_pubkey( grp, Q ) );
+
+ /*
+ * Step 3: derive MPI from hashed message
+ */
+ MBEDCRYPTO_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
+
+ /*
+ * Step 4: u1 = e / s mod n, u2 = r / s mod n
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_inv_mod( &s_inv, s, &grp->N ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &u1, &e, &s_inv ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &u1, &u1, &grp->N ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &u2, r, &s_inv ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &u2, &u2, &grp->N ) );
+
+ /*
+ * Step 5: R = u1 G + u2 Q
+ *
+ * Since we're not using any secret data, no need to pass a RNG to
+ * mbedcrypto_ecp_mul() for countermesures.
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) );
+
+ if( mbedcrypto_ecp_is_zero( &R ) )
+ {
+ ret = MBEDCRYPTO_ERR_ECP_VERIFY_FAILED;
+ goto cleanup;
+ }
+
+ /*
+ * Step 6: convert xR to an integer (no-op)
+ * Step 7: reduce xR mod n (gives v)
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &R.X, &R.X, &grp->N ) );
+
+ /*
+ * Step 8: check if v (that is, R.X) is equal to r
+ */
+ if( mbedcrypto_mpi_cmp_mpi( &R.X, r ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_ECP_VERIFY_FAILED;
+ goto cleanup;
+ }
+
+cleanup:
+ mbedcrypto_ecp_point_free( &R );
+ mbedcrypto_mpi_free( &e ); mbedcrypto_mpi_free( &s_inv ); mbedcrypto_mpi_free( &u1 ); mbedcrypto_mpi_free( &u2 );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECDSA_VERIFY_ALT */
+
+/*
+ * Convert a signature (given by context) to ASN.1
+ */
+static int ecdsa_signature_to_asn1( const mbedcrypto_mpi *r, const mbedcrypto_mpi *s,
+ unsigned char *sig, size_t *slen )
+{
+ int ret;
+ unsigned char buf[MBEDCRYPTO_ECDSA_MAX_LEN];
+ unsigned char *p = buf + sizeof( buf );
+ size_t len = 0;
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_mpi( &p, buf, s ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_mpi( &p, buf, r ) );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( &p, buf, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( &p, buf,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) );
+
+ memcpy( sig, p, len );
+ *slen = len;
+
+ return( 0 );
+}
+
+/*
+ * Compute and write signature
+ */
+int mbedcrypto_ecdsa_write_signature( mbedcrypto_ecdsa_context *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hlen,
+ unsigned char *sig, size_t *slen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ mbedcrypto_mpi r, s;
+
+ mbedcrypto_mpi_init( &r );
+ mbedcrypto_mpi_init( &s );
+
+#if defined(MBEDCRYPTO_ECDSA_DETERMINISTIC)
+ (void) f_rng;
+ (void) p_rng;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d,
+ hash, hlen, md_alg ) );
+#else
+ (void) md_alg;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
+ hash, hlen, f_rng, p_rng ) );
+#endif
+
+ MBEDCRYPTO_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
+
+cleanup:
+ mbedcrypto_mpi_free( &r );
+ mbedcrypto_mpi_free( &s );
+
+ return( ret );
+}
+
+#if ! defined(MBEDCRYPTO_DEPRECATED_REMOVED) && \
+ defined(MBEDCRYPTO_ECDSA_DETERMINISTIC)
+int mbedcrypto_ecdsa_write_signature_det( mbedcrypto_ecdsa_context *ctx,
+ const unsigned char *hash, size_t hlen,
+ unsigned char *sig, size_t *slen,
+ mbedcrypto_md_type_t md_alg )
+{
+ return( mbedcrypto_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen,
+ NULL, NULL ) );
+}
+#endif
+
+/*
+ * Read and check signature
+ */
+int mbedcrypto_ecdsa_read_signature( mbedcrypto_ecdsa_context *ctx,
+ const unsigned char *hash, size_t hlen,
+ const unsigned char *sig, size_t slen )
+{
+ int ret;
+ unsigned char *p = (unsigned char *) sig;
+ const unsigned char *end = sig + slen;
+ size_t len;
+ mbedcrypto_mpi r, s;
+
+ mbedcrypto_mpi_init( &r );
+ mbedcrypto_mpi_init( &s );
+
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ {
+ ret += MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+ if( p + len != end )
+ {
+ ret = MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH;
+ goto cleanup;
+ }
+
+ if( ( ret = mbedcrypto_asn1_get_mpi( &p, end, &r ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_get_mpi( &p, end, &s ) ) != 0 )
+ {
+ ret += MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+ if( ( ret = mbedcrypto_ecdsa_verify( &ctx->grp, hash, hlen,
+ &ctx->Q, &r, &s ) ) != 0 )
+ goto cleanup;
+
+ /* At this point we know that the buffer starts with a valid signature.
+ * Return 0 if the buffer just contains the signature, and a specific
+ * error code if the valid signature is followed by more data. */
+ if( p != end )
+ ret = MBEDCRYPTO_ERR_ECP_SIG_LEN_MISMATCH;
+
+cleanup:
+ mbedcrypto_mpi_free( &r );
+ mbedcrypto_mpi_free( &s );
+
+ return( ret );
+}
+
+#if !defined(MBEDCRYPTO_ECDSA_GENKEY_ALT)
+/*
+ * Generate key pair
+ */
+int mbedcrypto_ecdsa_genkey( mbedcrypto_ecdsa_context *ctx, mbedcrypto_ecp_group_id gid,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ return( mbedcrypto_ecp_group_load( &ctx->grp, gid ) ||
+ mbedcrypto_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
+}
+#endif /* MBEDCRYPTO_ECDSA_GENKEY_ALT */
+
+/*
+ * Set context from an mbedcrypto_ecp_keypair
+ */
+int mbedcrypto_ecdsa_from_keypair( mbedcrypto_ecdsa_context *ctx, const mbedcrypto_ecp_keypair *key )
+{
+ int ret;
+
+ if( ( ret = mbedcrypto_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ||
+ ( ret = mbedcrypto_mpi_copy( &ctx->d, &key->d ) ) != 0 ||
+ ( ret = mbedcrypto_ecp_copy( &ctx->Q, &key->Q ) ) != 0 )
+ {
+ mbedcrypto_ecdsa_free( ctx );
+ }
+
+ return( ret );
+}
+
+/*
+ * Initialize context
+ */
+void mbedcrypto_ecdsa_init( mbedcrypto_ecdsa_context *ctx )
+{
+ mbedcrypto_ecp_keypair_init( ctx );
+}
+
+/*
+ * Free context
+ */
+void mbedcrypto_ecdsa_free( mbedcrypto_ecdsa_context *ctx )
+{
+ mbedcrypto_ecp_keypair_free( ctx );
+}
+
+#endif /* MBEDCRYPTO_ECDSA_C */
diff --git a/library/ecp.c b/library/ecp.c
new file mode 100644
index 0000000..d29c4a2
--- /dev/null
+++ b/library/ecp.c
@@ -0,0 +1,2203 @@
+/*
+ * Elliptic curves over GF(p): generic functions
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * References:
+ *
+ * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
+ * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
+ * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
+ * RFC 4492 for the related TLS structures and constants
+ * RFC 7748 for the Curve448 and Curve25519 curve definitions
+ *
+ * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
+ *
+ * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
+ * for elliptic curve cryptosystems. In : Cryptographic Hardware and
+ * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
+ * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
+ *
+ * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
+ * render ECC resistant against Side Channel Attacks. IACR Cryptology
+ * ePrint Archive, 2004, vol. 2004, p. 342.
+ * <http://eprint.iacr.org/2004/342.pdf>
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_ECP_C)
+
+#include "mbedcrypto/ecp.h"
+#include "mbedcrypto/threading.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if !defined(MBEDCRYPTO_ECP_ALT)
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#include "mbedcrypto/ecp_internal.h"
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/*
+ * Counts of point addition and doubling, and field multiplications.
+ * Used to test resistance of point multiplication to simple timing attacks.
+ */
+static unsigned long add_count, dbl_count, mul_count;
+#endif
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_BP256R1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_BP384R1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_BP512R1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED)
+#define ECP_SHORTWEIERSTRASS
+#endif
+
+#if defined(MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_CURVE448_ENABLED)
+#define ECP_MONTGOMERY
+#endif
+
+/*
+ * Curve types: internal for now, might be exposed later
+ */
+typedef enum
+{
+ ECP_TYPE_NONE = 0,
+ ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
+ ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
+} ecp_curve_type;
+
+/*
+ * List of supported curves:
+ * - internal ID
+ * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
+ * - size in bits
+ * - readable name
+ *
+ * Curves are listed in order: largest curves first, and for a given size,
+ * fastest curves first. This provides the default order for the SSL module.
+ *
+ * Reminder: update profiles in x509_crt.c when adding a new curves!
+ */
+static const mbedcrypto_ecp_curve_info ecp_supported_curves[] =
+{
+#if defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_BP512R1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_BP384R1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_BP256R1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED)
+ { MBEDCRYPTO_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
+#endif
+ { MBEDCRYPTO_ECP_DP_NONE, 0, 0, NULL },
+};
+
+#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
+ sizeof( ecp_supported_curves[0] )
+
+static mbedcrypto_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
+
+/*
+ * List of supported curves and associated info
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_list( void )
+{
+ return( ecp_supported_curves );
+}
+
+/*
+ * List of supported curves, group ID only
+ */
+const mbedcrypto_ecp_group_id *mbedcrypto_ecp_grp_id_list( void )
+{
+ static int init_done = 0;
+
+ if( ! init_done )
+ {
+ size_t i = 0;
+ const mbedcrypto_ecp_curve_info *curve_info;
+
+ for( curve_info = mbedcrypto_ecp_curve_list();
+ curve_info->grp_id != MBEDCRYPTO_ECP_DP_NONE;
+ curve_info++ )
+ {
+ ecp_supported_grp_id[i++] = curve_info->grp_id;
+ }
+ ecp_supported_grp_id[i] = MBEDCRYPTO_ECP_DP_NONE;
+
+ init_done = 1;
+ }
+
+ return( ecp_supported_grp_id );
+}
+
+/*
+ * Get the curve info for the internal identifier
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_info_from_grp_id( mbedcrypto_ecp_group_id grp_id )
+{
+ const mbedcrypto_ecp_curve_info *curve_info;
+
+ for( curve_info = mbedcrypto_ecp_curve_list();
+ curve_info->grp_id != MBEDCRYPTO_ECP_DP_NONE;
+ curve_info++ )
+ {
+ if( curve_info->grp_id == grp_id )
+ return( curve_info );
+ }
+
+ return( NULL );
+}
+
+/*
+ * Get the curve info from the TLS identifier
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_info_from_tls_id( uint16_t tls_id )
+{
+ const mbedcrypto_ecp_curve_info *curve_info;
+
+ for( curve_info = mbedcrypto_ecp_curve_list();
+ curve_info->grp_id != MBEDCRYPTO_ECP_DP_NONE;
+ curve_info++ )
+ {
+ if( curve_info->tls_id == tls_id )
+ return( curve_info );
+ }
+
+ return( NULL );
+}
+
+/*
+ * Get the curve info from the name
+ */
+const mbedcrypto_ecp_curve_info *mbedcrypto_ecp_curve_info_from_name( const char *name )
+{
+ const mbedcrypto_ecp_curve_info *curve_info;
+
+ for( curve_info = mbedcrypto_ecp_curve_list();
+ curve_info->grp_id != MBEDCRYPTO_ECP_DP_NONE;
+ curve_info++ )
+ {
+ if( strcmp( curve_info->name, name ) == 0 )
+ return( curve_info );
+ }
+
+ return( NULL );
+}
+
+/*
+ * Get the type of a curve
+ */
+static inline ecp_curve_type ecp_get_type( const mbedcrypto_ecp_group *grp )
+{
+ if( grp->G.X.p == NULL )
+ return( ECP_TYPE_NONE );
+
+ if( grp->G.Y.p == NULL )
+ return( ECP_TYPE_MONTGOMERY );
+ else
+ return( ECP_TYPE_SHORT_WEIERSTRASS );
+}
+
+/*
+ * Initialize (the components of) a point
+ */
+void mbedcrypto_ecp_point_init( mbedcrypto_ecp_point *pt )
+{
+ if( pt == NULL )
+ return;
+
+ mbedcrypto_mpi_init( &pt->X );
+ mbedcrypto_mpi_init( &pt->Y );
+ mbedcrypto_mpi_init( &pt->Z );
+}
+
+/*
+ * Initialize (the components of) a group
+ */
+void mbedcrypto_ecp_group_init( mbedcrypto_ecp_group *grp )
+{
+ if( grp == NULL )
+ return;
+
+ memset( grp, 0, sizeof( mbedcrypto_ecp_group ) );
+}
+
+/*
+ * Initialize (the components of) a key pair
+ */
+void mbedcrypto_ecp_keypair_init( mbedcrypto_ecp_keypair *key )
+{
+ if( key == NULL )
+ return;
+
+ mbedcrypto_ecp_group_init( &key->grp );
+ mbedcrypto_mpi_init( &key->d );
+ mbedcrypto_ecp_point_init( &key->Q );
+}
+
+/*
+ * Unallocate (the components of) a point
+ */
+void mbedcrypto_ecp_point_free( mbedcrypto_ecp_point *pt )
+{
+ if( pt == NULL )
+ return;
+
+ mbedcrypto_mpi_free( &( pt->X ) );
+ mbedcrypto_mpi_free( &( pt->Y ) );
+ mbedcrypto_mpi_free( &( pt->Z ) );
+}
+
+/*
+ * Unallocate (the components of) a group
+ */
+void mbedcrypto_ecp_group_free( mbedcrypto_ecp_group *grp )
+{
+ size_t i;
+
+ if( grp == NULL )
+ return;
+
+ if( grp->h != 1 )
+ {
+ mbedcrypto_mpi_free( &grp->P );
+ mbedcrypto_mpi_free( &grp->A );
+ mbedcrypto_mpi_free( &grp->B );
+ mbedcrypto_ecp_point_free( &grp->G );
+ mbedcrypto_mpi_free( &grp->N );
+ }
+
+ if( grp->T != NULL )
+ {
+ for( i = 0; i < grp->T_size; i++ )
+ mbedcrypto_ecp_point_free( &grp->T[i] );
+ mbedcrypto_free( grp->T );
+ }
+
+ mbedcrypto_platform_zeroize( grp, sizeof( mbedcrypto_ecp_group ) );
+}
+
+/*
+ * Unallocate (the components of) a key pair
+ */
+void mbedcrypto_ecp_keypair_free( mbedcrypto_ecp_keypair *key )
+{
+ if( key == NULL )
+ return;
+
+ mbedcrypto_ecp_group_free( &key->grp );
+ mbedcrypto_mpi_free( &key->d );
+ mbedcrypto_ecp_point_free( &key->Q );
+}
+
+/*
+ * Copy the contents of a point
+ */
+int mbedcrypto_ecp_copy( mbedcrypto_ecp_point *P, const mbedcrypto_ecp_point *Q )
+{
+ int ret;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &P->X, &Q->X ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &P->Y, &Q->Y ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &P->Z, &Q->Z ) );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Copy the contents of a group object
+ */
+int mbedcrypto_ecp_group_copy( mbedcrypto_ecp_group *dst, const mbedcrypto_ecp_group *src )
+{
+ return mbedcrypto_ecp_group_load( dst, src->id );
+}
+
+/*
+ * Set point to zero
+ */
+int mbedcrypto_ecp_set_zero( mbedcrypto_ecp_point *pt )
+{
+ int ret;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &pt->X , 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &pt->Y , 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &pt->Z , 0 ) );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Tell if a point is zero
+ */
+int mbedcrypto_ecp_is_zero( mbedcrypto_ecp_point *pt )
+{
+ return( mbedcrypto_mpi_cmp_int( &pt->Z, 0 ) == 0 );
+}
+
+/*
+ * Compare two points lazyly
+ */
+int mbedcrypto_ecp_point_cmp( const mbedcrypto_ecp_point *P,
+ const mbedcrypto_ecp_point *Q )
+{
+ if( mbedcrypto_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
+ mbedcrypto_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
+ mbedcrypto_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
+ {
+ return( 0 );
+ }
+
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+}
+
+/*
+ * Import a non-zero point from ASCII strings
+ */
+int mbedcrypto_ecp_point_read_string( mbedcrypto_ecp_point *P, int radix,
+ const char *x, const char *y )
+{
+ int ret;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &P->X, radix, x ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &P->Y, radix, y ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &P->Z, 1 ) );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Export a point into unsigned binary data (SEC1 2.3.3)
+ */
+int mbedcrypto_ecp_point_write_binary( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *P,
+ int format, size_t *olen,
+ unsigned char *buf, size_t buflen )
+{
+ int ret = 0;
+ size_t plen;
+
+ if( format != MBEDCRYPTO_ECP_PF_UNCOMPRESSED &&
+ format != MBEDCRYPTO_ECP_PF_COMPRESSED )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ /*
+ * Common case: P == 0
+ */
+ if( mbedcrypto_mpi_cmp_int( &P->Z, 0 ) == 0 )
+ {
+ if( buflen < 1 )
+ return( MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL );
+
+ buf[0] = 0x00;
+ *olen = 1;
+
+ return( 0 );
+ }
+
+ plen = mbedcrypto_mpi_size( &grp->P );
+
+ if( format == MBEDCRYPTO_ECP_PF_UNCOMPRESSED )
+ {
+ *olen = 2 * plen + 1;
+
+ if( buflen < *olen )
+ return( MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL );
+
+ buf[0] = 0x04;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &P->X, buf + 1, plen ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
+ }
+ else if( format == MBEDCRYPTO_ECP_PF_COMPRESSED )
+ {
+ *olen = plen + 1;
+
+ if( buflen < *olen )
+ return( MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL );
+
+ buf[0] = 0x02 + mbedcrypto_mpi_get_bit( &P->Y, 0 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &P->X, buf + 1, plen ) );
+ }
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Import a point from unsigned binary data (SEC1 2.3.4)
+ */
+int mbedcrypto_ecp_point_read_binary( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *pt,
+ const unsigned char *buf, size_t ilen )
+{
+ int ret;
+ size_t plen;
+
+ if( ilen < 1 )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ if( buf[0] == 0x00 )
+ {
+ if( ilen == 1 )
+ return( mbedcrypto_ecp_set_zero( pt ) );
+ else
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+ }
+
+ plen = mbedcrypto_mpi_size( &grp->P );
+
+ if( buf[0] != 0x04 )
+ return( MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE );
+
+ if( ilen != 2 * plen + 1 )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &pt->X, buf + 1, plen ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &pt->Z, 1 ) );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Import a point from a TLS ECPoint record (RFC 4492)
+ * struct {
+ * opaque point <1..2^8-1>;
+ * } ECPoint;
+ */
+int mbedcrypto_ecp_tls_read_point( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *pt,
+ const unsigned char **buf, size_t buf_len )
+{
+ unsigned char data_len;
+ const unsigned char *buf_start;
+
+ /*
+ * We must have at least two bytes (1 for length, at least one for data)
+ */
+ if( buf_len < 2 )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ data_len = *(*buf)++;
+ if( data_len < 1 || data_len > buf_len - 1 )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ /*
+ * Save buffer start for read_binary and update buf
+ */
+ buf_start = *buf;
+ *buf += data_len;
+
+ return mbedcrypto_ecp_point_read_binary( grp, pt, buf_start, data_len );
+}
+
+/*
+ * Export a point as a TLS ECPoint record (RFC 4492)
+ * struct {
+ * opaque point <1..2^8-1>;
+ * } ECPoint;
+ */
+int mbedcrypto_ecp_tls_write_point( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *pt,
+ int format, size_t *olen,
+ unsigned char *buf, size_t blen )
+{
+ int ret;
+
+ /*
+ * buffer length must be at least one, for our length byte
+ */
+ if( blen < 1 )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ if( ( ret = mbedcrypto_ecp_point_write_binary( grp, pt, format,
+ olen, buf + 1, blen - 1) ) != 0 )
+ return( ret );
+
+ /*
+ * write length to the first byte and update total length
+ */
+ buf[0] = (unsigned char) *olen;
+ ++*olen;
+
+ return( 0 );
+}
+
+/*
+ * Set a group from an ECParameters record (RFC 4492)
+ */
+int mbedcrypto_ecp_tls_read_group( mbedcrypto_ecp_group *grp, const unsigned char **buf, size_t len )
+{
+ uint16_t tls_id;
+ const mbedcrypto_ecp_curve_info *curve_info;
+
+ /*
+ * We expect at least three bytes (see below)
+ */
+ if( len < 3 )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ /*
+ * First byte is curve_type; only named_curve is handled
+ */
+ if( *(*buf)++ != MBEDCRYPTO_ECP_TLS_NAMED_CURVE )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ /*
+ * Next two bytes are the namedcurve value
+ */
+ tls_id = *(*buf)++;
+ tls_id <<= 8;
+ tls_id |= *(*buf)++;
+
+ if( ( curve_info = mbedcrypto_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
+ return( MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE );
+
+ return mbedcrypto_ecp_group_load( grp, curve_info->grp_id );
+}
+
+/*
+ * Write the ECParameters record corresponding to a group (RFC 4492)
+ */
+int mbedcrypto_ecp_tls_write_group( const mbedcrypto_ecp_group *grp, size_t *olen,
+ unsigned char *buf, size_t blen )
+{
+ const mbedcrypto_ecp_curve_info *curve_info;
+
+ if( ( curve_info = mbedcrypto_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ /*
+ * We are going to write 3 bytes (see below)
+ */
+ *olen = 3;
+ if( blen < *olen )
+ return( MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL );
+
+ /*
+ * First byte is curve_type, always named_curve
+ */
+ *buf++ = MBEDCRYPTO_ECP_TLS_NAMED_CURVE;
+
+ /*
+ * Next two bytes are the namedcurve value
+ */
+ buf[0] = curve_info->tls_id >> 8;
+ buf[1] = curve_info->tls_id & 0xFF;
+
+ return( 0 );
+}
+
+/*
+ * Wrapper around fast quasi-modp functions, with fall-back to mbedcrypto_mpi_mod_mpi.
+ * See the documentation of struct mbedcrypto_ecp_group.
+ *
+ * This function is in the critial loop for mbedcrypto_ecp_mul, so pay attention to perf.
+ */
+static int ecp_modp( mbedcrypto_mpi *N, const mbedcrypto_ecp_group *grp )
+{
+ int ret;
+
+ if( grp->modp == NULL )
+ return( mbedcrypto_mpi_mod_mpi( N, N, &grp->P ) );
+
+ /* N->s < 0 is a much faster test, which fails only if N is 0 */
+ if( ( N->s < 0 && mbedcrypto_mpi_cmp_int( N, 0 ) != 0 ) ||
+ mbedcrypto_mpi_bitlen( N ) > 2 * grp->pbits )
+ {
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+ }
+
+ MBEDCRYPTO_MPI_CHK( grp->modp( N ) );
+
+ /* N->s < 0 is a much faster test, which fails only if N is 0 */
+ while( N->s < 0 && mbedcrypto_mpi_cmp_int( N, 0 ) != 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( N, N, &grp->P ) );
+
+ while( mbedcrypto_mpi_cmp_mpi( N, &grp->P ) >= 0 )
+ /* we known P, N and the result are positive */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_abs( N, N, &grp->P ) );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Fast mod-p functions expect their argument to be in the 0..p^2 range.
+ *
+ * In order to guarantee that, we need to ensure that operands of
+ * mbedcrypto_mpi_mul_mpi are in the 0..p range. So, after each operation we will
+ * bring the result back to this range.
+ *
+ * The following macros are shortcuts for doing that.
+ */
+
+/*
+ * Reduce a mbedcrypto_mpi mod p in-place, general case, to use after mbedcrypto_mpi_mul_mpi
+ */
+#if defined(MBEDCRYPTO_SELF_TEST)
+#define INC_MUL_COUNT mul_count++;
+#else
+#define INC_MUL_COUNT
+#endif
+
+#define MOD_MUL( N ) do { MBEDCRYPTO_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
+ while( 0 )
+
+/*
+ * Reduce a mbedcrypto_mpi mod p in-place, to use after mbedcrypto_mpi_sub_mpi
+ * N->s < 0 is a very fast test, which fails only if N is 0
+ */
+#define MOD_SUB( N ) \
+ while( N.s < 0 && mbedcrypto_mpi_cmp_int( &N, 0 ) != 0 ) \
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &N, &N, &grp->P ) )
+
+/*
+ * Reduce a mbedcrypto_mpi mod p in-place, to use after mbedcrypto_mpi_add_mpi and mbedcrypto_mpi_mul_int.
+ * We known P, N and the result are positive, so sub_abs is correct, and
+ * a bit faster.
+ */
+#define MOD_ADD( N ) \
+ while( mbedcrypto_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_abs( &N, &N, &grp->P ) )
+
+#if defined(ECP_SHORTWEIERSTRASS)
+/*
+ * For curves in short Weierstrass form, we do all the internal operations in
+ * Jacobian coordinates.
+ *
+ * For multiplication, we'll use a comb method with coutermeasueres against
+ * SPA, hence timing attacks.
+ */
+
+/*
+ * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
+ * Cost: 1N := 1I + 3M + 1S
+ */
+static int ecp_normalize_jac( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *pt )
+{
+ int ret;
+ mbedcrypto_mpi Zi, ZZi;
+
+ if( mbedcrypto_mpi_cmp_int( &pt->Z, 0 ) == 0 )
+ return( 0 );
+
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_JAC_ALT)
+ if ( mbedcrypto_internal_ecp_grp_capable( grp ) )
+ {
+ return mbedcrypto_internal_ecp_normalize_jac( grp, pt );
+ }
+#endif /* MBEDCRYPTO_ECP_NORMALIZE_JAC_ALT */
+ mbedcrypto_mpi_init( &Zi ); mbedcrypto_mpi_init( &ZZi );
+
+ /*
+ * X = X / Z^2 mod p
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X );
+
+ /*
+ * Y = Y / Z^3 mod p
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y );
+
+ /*
+ * Z = 1
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &pt->Z, 1 ) );
+
+cleanup:
+
+ mbedcrypto_mpi_free( &Zi ); mbedcrypto_mpi_free( &ZZi );
+
+ return( ret );
+}
+
+/*
+ * Normalize jacobian coordinates of an array of (pointers to) points,
+ * using Montgomery's trick to perform only one inversion mod P.
+ * (See for example Cohen's "A Course in Computational Algebraic Number
+ * Theory", Algorithm 10.3.4.)
+ *
+ * Warning: fails (returning an error) if one of the points is zero!
+ * This should never happen, see choice of w in ecp_mul_comb().
+ *
+ * Cost: 1N(t) := 1I + (6t - 3)M + 1S
+ */
+static int ecp_normalize_jac_many( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *T[], size_t t_len )
+{
+ int ret;
+ size_t i;
+ mbedcrypto_mpi *c, u, Zi, ZZi;
+
+ if( t_len < 2 )
+ return( ecp_normalize_jac( grp, *T ) );
+
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_JAC_MANY_ALT)
+ if ( mbedcrypto_internal_ecp_grp_capable( grp ) )
+ {
+ return mbedcrypto_internal_ecp_normalize_jac_many(grp, T, t_len);
+ }
+#endif
+
+ if( ( c = mbedcrypto_calloc( t_len, sizeof( mbedcrypto_mpi ) ) ) == NULL )
+ return( MBEDCRYPTO_ERR_ECP_ALLOC_FAILED );
+
+ mbedcrypto_mpi_init( &u ); mbedcrypto_mpi_init( &Zi ); mbedcrypto_mpi_init( &ZZi );
+
+ /*
+ * c[i] = Z_0 * ... * Z_i
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &c[0], &T[0]->Z ) );
+ for( i = 1; i < t_len; i++ )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
+ MOD_MUL( c[i] );
+ }
+
+ /*
+ * u = 1 / (Z_0 * ... * Z_n) mod P
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
+
+ for( i = t_len - 1; ; i-- )
+ {
+ /*
+ * Zi = 1 / Z_i mod p
+ * u = 1 / (Z_0 * ... * Z_i) mod P
+ */
+ if( i == 0 ) {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &Zi, &u ) );
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
+ }
+
+ /*
+ * proceed as in normalize()
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y );
+
+ /*
+ * Post-precessing: reclaim some memory by shrinking coordinates
+ * - not storing Z (always 1)
+ * - shrinking other coordinates, but still keeping the same number of
+ * limbs as P, as otherwise it will too likely be regrown too fast.
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shrink( &T[i]->X, grp->P.n ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shrink( &T[i]->Y, grp->P.n ) );
+ mbedcrypto_mpi_free( &T[i]->Z );
+
+ if( i == 0 )
+ break;
+ }
+
+cleanup:
+
+ mbedcrypto_mpi_free( &u ); mbedcrypto_mpi_free( &Zi ); mbedcrypto_mpi_free( &ZZi );
+ for( i = 0; i < t_len; i++ )
+ mbedcrypto_mpi_free( &c[i] );
+ mbedcrypto_free( c );
+
+ return( ret );
+}
+
+/*
+ * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
+ * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
+ */
+static int ecp_safe_invert_jac( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *Q,
+ unsigned char inv )
+{
+ int ret;
+ unsigned char nonzero;
+ mbedcrypto_mpi mQY;
+
+ mbedcrypto_mpi_init( &mQY );
+
+ /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
+ nonzero = mbedcrypto_mpi_cmp_int( &Q->Y, 0 ) != 0;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
+
+cleanup:
+ mbedcrypto_mpi_free( &mQY );
+
+ return( ret );
+}
+
+/*
+ * Point doubling R = 2 P, Jacobian coordinates
+ *
+ * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 .
+ *
+ * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
+ * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
+ *
+ * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
+ *
+ * Cost: 1D := 3M + 4S (A == 0)
+ * 4M + 4S (A == -3)
+ * 3M + 6S + 1a otherwise
+ */
+static int ecp_double_jac( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+ const mbedcrypto_ecp_point *P )
+{
+ int ret;
+ mbedcrypto_mpi M, S, T, U;
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+ dbl_count++;
+#endif
+
+#if defined(MBEDCRYPTO_ECP_DOUBLE_JAC_ALT)
+ if ( mbedcrypto_internal_ecp_grp_capable( grp ) )
+ {
+ return mbedcrypto_internal_ecp_double_jac( grp, R, P );
+ }
+#endif /* MBEDCRYPTO_ECP_DOUBLE_JAC_ALT */
+
+ mbedcrypto_mpi_init( &M ); mbedcrypto_mpi_init( &S ); mbedcrypto_mpi_init( &T ); mbedcrypto_mpi_init( &U );
+
+ /* Special case for A = -3 */
+ if( grp->A.p == NULL )
+ {
+ /* M = 3(X + Z^2)(X - Z^2) */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
+ }
+ else
+ {
+ /* M = 3.X^2 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
+
+ /* Optimize away for "koblitz" curves with A = 0 */
+ if( mbedcrypto_mpi_cmp_int( &grp->A, 0 ) != 0 )
+ {
+ /* M += A.Z^4 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
+ }
+ }
+
+ /* S = 4.X.Y^2 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
+
+ /* U = 8.Y^4 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
+
+ /* T = M^2 - 2.S */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
+
+ /* S = M(S - T) - U */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
+
+ /* U = 2.Y.Z */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &R->X, &T ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &R->Y, &S ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &R->Z, &U ) );
+
+cleanup:
+ mbedcrypto_mpi_free( &M ); mbedcrypto_mpi_free( &S ); mbedcrypto_mpi_free( &T ); mbedcrypto_mpi_free( &U );
+
+ return( ret );
+}
+
+/*
+ * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
+ *
+ * The coordinates of Q must be normalized (= affine),
+ * but those of P don't need to. R is not normalized.
+ *
+ * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
+ * None of these cases can happen as intermediate step in ecp_mul_comb():
+ * - at each step, P, Q and R are multiples of the base point, the factor
+ * being less than its order, so none of them is zero;
+ * - Q is an odd multiple of the base point, P an even multiple,
+ * due to the choice of precomputed points in the modified comb method.
+ * So branches for these cases do not leak secret information.
+ *
+ * We accept Q->Z being unset (saving memory in tables) as meaning 1.
+ *
+ * Cost: 1A := 8M + 3S
+ */
+static int ecp_add_mixed( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+ const mbedcrypto_ecp_point *P, const mbedcrypto_ecp_point *Q )
+{
+ int ret;
+ mbedcrypto_mpi T1, T2, T3, T4, X, Y, Z;
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+ add_count++;
+#endif
+
+#if defined(MBEDCRYPTO_ECP_ADD_MIXED_ALT)
+ if ( mbedcrypto_internal_ecp_grp_capable( grp ) )
+ {
+ return mbedcrypto_internal_ecp_add_mixed( grp, R, P, Q );
+ }
+#endif /* MBEDCRYPTO_ECP_ADD_MIXED_ALT */
+
+ /*
+ * Trivial cases: P == 0 or Q == 0 (case 1)
+ */
+ if( mbedcrypto_mpi_cmp_int( &P->Z, 0 ) == 0 )
+ return( mbedcrypto_ecp_copy( R, Q ) );
+
+ if( Q->Z.p != NULL && mbedcrypto_mpi_cmp_int( &Q->Z, 0 ) == 0 )
+ return( mbedcrypto_ecp_copy( R, P ) );
+
+ /*
+ * Make sure Q coordinates are normalized
+ */
+ if( Q->Z.p != NULL && mbedcrypto_mpi_cmp_int( &Q->Z, 1 ) != 0 )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ mbedcrypto_mpi_init( &T1 ); mbedcrypto_mpi_init( &T2 ); mbedcrypto_mpi_init( &T3 ); mbedcrypto_mpi_init( &T4 );
+ mbedcrypto_mpi_init( &X ); mbedcrypto_mpi_init( &Y ); mbedcrypto_mpi_init( &Z );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
+
+ /* Special cases (2) and (3) */
+ if( mbedcrypto_mpi_cmp_int( &T1, 0 ) == 0 )
+ {
+ if( mbedcrypto_mpi_cmp_int( &T2, 0 ) == 0 )
+ {
+ ret = ecp_double_jac( grp, R, P );
+ goto cleanup;
+ }
+ else
+ {
+ ret = mbedcrypto_ecp_set_zero( R );
+ goto cleanup;
+ }
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &R->X, &X ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &R->Y, &Y ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &R->Z, &Z ) );
+
+cleanup:
+
+ mbedcrypto_mpi_free( &T1 ); mbedcrypto_mpi_free( &T2 ); mbedcrypto_mpi_free( &T3 ); mbedcrypto_mpi_free( &T4 );
+ mbedcrypto_mpi_free( &X ); mbedcrypto_mpi_free( &Y ); mbedcrypto_mpi_free( &Z );
+
+ return( ret );
+}
+
+/*
+ * Randomize jacobian coordinates:
+ * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
+ * This is sort of the reverse operation of ecp_normalize_jac().
+ *
+ * This countermeasure was first suggested in [2].
+ */
+static int ecp_randomize_jac( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *pt,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ int ret;
+ mbedcrypto_mpi l, ll;
+ size_t p_size;
+ int count = 0;
+
+#if defined(MBEDCRYPTO_ECP_RANDOMIZE_JAC_ALT)
+ if ( mbedcrypto_internal_ecp_grp_capable( grp ) )
+ {
+ return mbedcrypto_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
+ }
+#endif /* MBEDCRYPTO_ECP_RANDOMIZE_JAC_ALT */
+
+ p_size = ( grp->pbits + 7 ) / 8;
+ mbedcrypto_mpi_init( &l ); mbedcrypto_mpi_init( &ll );
+
+ /* Generate l such that 1 < l < p */
+ do
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
+
+ while( mbedcrypto_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &l, 1 ) );
+
+ if( count++ > 10 )
+ return( MBEDCRYPTO_ERR_ECP_RANDOM_FAILED );
+ }
+ while( mbedcrypto_mpi_cmp_int( &l, 1 ) <= 0 );
+
+ /* Z = l * Z */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z );
+
+ /* X = l^2 * X */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X );
+
+ /* Y = l^3 * Y */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y );
+
+cleanup:
+ mbedcrypto_mpi_free( &l ); mbedcrypto_mpi_free( &ll );
+
+ return( ret );
+}
+
+/*
+ * Check and define parameters used by the comb method (see below for details)
+ */
+#if MBEDCRYPTO_ECP_WINDOW_SIZE < 2 || MBEDCRYPTO_ECP_WINDOW_SIZE > 7
+#error "MBEDCRYPTO_ECP_WINDOW_SIZE out of bounds"
+#endif
+
+/* d = ceil( n / w ) */
+#define COMB_MAX_D ( MBEDCRYPTO_ECP_MAX_BITS + 1 ) / 2
+
+/* number of precomputed points */
+#define COMB_MAX_PRE ( 1 << ( MBEDCRYPTO_ECP_WINDOW_SIZE - 1 ) )
+
+/*
+ * Compute the representation of m that will be used with our comb method.
+ *
+ * The basic comb method is described in GECC 3.44 for example. We use a
+ * modified version that provides resistance to SPA by avoiding zero
+ * digits in the representation as in [3]. We modify the method further by
+ * requiring that all K_i be odd, which has the small cost that our
+ * representation uses one more K_i, due to carries.
+ *
+ * Also, for the sake of compactness, only the seven low-order bits of x[i]
+ * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
+ * the paper): it is set if and only if if s_i == -1;
+ *
+ * Calling conventions:
+ * - x is an array of size d + 1
+ * - w is the size, ie number of teeth, of the comb, and must be between
+ * 2 and 7 (in practice, between 2 and MBEDCRYPTO_ECP_WINDOW_SIZE)
+ * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
+ * (the result will be incorrect if these assumptions are not satisfied)
+ */
+static void ecp_comb_fixed( unsigned char x[], size_t d,
+ unsigned char w, const mbedcrypto_mpi *m )
+{
+ size_t i, j;
+ unsigned char c, cc, adjust;
+
+ memset( x, 0, d+1 );
+
+ /* First get the classical comb values (except for x_d = 0) */
+ for( i = 0; i < d; i++ )
+ for( j = 0; j < w; j++ )
+ x[i] |= mbedcrypto_mpi_get_bit( m, i + d * j ) << j;
+
+ /* Now make sure x_1 .. x_d are odd */
+ c = 0;
+ for( i = 1; i <= d; i++ )
+ {
+ /* Add carry and update it */
+ cc = x[i] & c;
+ x[i] = x[i] ^ c;
+ c = cc;
+
+ /* Adjust if needed, avoiding branches */
+ adjust = 1 - ( x[i] & 0x01 );
+ c |= x[i] & ( x[i-1] * adjust );
+ x[i] = x[i] ^ ( x[i-1] * adjust );
+ x[i-1] |= adjust << 7;
+ }
+}
+
+/*
+ * Precompute points for the comb method
+ *
+ * If i = i_{w-1} ... i_1 is the binary representation of i, then
+ * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P
+ *
+ * T must be able to hold 2^{w - 1} elements
+ *
+ * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1)
+ */
+static int ecp_precompute_comb( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point T[], const mbedcrypto_ecp_point *P,
+ unsigned char w, size_t d )
+{
+ int ret;
+ unsigned char i, k;
+ size_t j;
+ mbedcrypto_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
+
+ /*
+ * Set T[0] = P and
+ * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_copy( &T[0], P ) );
+
+ k = 0;
+ for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
+ {
+ cur = T + i;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_copy( cur, T + ( i >> 1 ) ) );
+ for( j = 0; j < d; j++ )
+ MBEDCRYPTO_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
+
+ TT[k++] = cur;
+ }
+
+ MBEDCRYPTO_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+
+ /*
+ * Compute the remaining ones using the minimal number of additions
+ * Be careful to update T[2^l] only after using it!
+ */
+ k = 0;
+ for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
+ {
+ j = i;
+ while( j-- )
+ {
+ MBEDCRYPTO_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
+ TT[k++] = &T[i + j];
+ }
+ }
+
+ MBEDCRYPTO_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+
+cleanup:
+
+ return( ret );
+}
+
+/*
+ * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
+ */
+static int ecp_select_comb( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+ const mbedcrypto_ecp_point T[], unsigned char t_len,
+ unsigned char i )
+{
+ int ret;
+ unsigned char ii, j;
+
+ /* Ignore the "sign" bit and scale down */
+ ii = ( i & 0x7Fu ) >> 1;
+
+ /* Read the whole table to thwart cache-based timing attacks */
+ for( j = 0; j < t_len; j++ )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
+ }
+
+ /* Safely invert result if i is "negative" */
+ MBEDCRYPTO_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Core multiplication algorithm for the (modified) comb method.
+ * This part is actually common with the basic comb method (GECC 3.44)
+ *
+ * Cost: d A + d D + 1 R
+ */
+static int ecp_mul_comb_core( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+ const mbedcrypto_ecp_point T[], unsigned char t_len,
+ const unsigned char x[], size_t d,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ mbedcrypto_ecp_point Txi;
+ size_t i;
+
+ mbedcrypto_ecp_point_init( &Txi );
+
+ /* Start with a non-zero point and randomize its coordinates */
+ i = d;
+ MBEDCRYPTO_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &R->Z, 1 ) );
+ if( f_rng != 0 )
+ MBEDCRYPTO_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
+
+ while( i-- != 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( ecp_double_jac( grp, R, R ) );
+ MBEDCRYPTO_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
+ MBEDCRYPTO_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
+ }
+
+cleanup:
+
+ mbedcrypto_ecp_point_free( &Txi );
+
+ return( ret );
+}
+
+/*
+ * Multiplication using the comb method,
+ * for curves in short Weierstrass form
+ */
+static int ecp_mul_comb( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+ const mbedcrypto_mpi *m, const mbedcrypto_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ unsigned char w, m_is_odd, p_eq_g, pre_len, i;
+ size_t d;
+ unsigned char k[COMB_MAX_D + 1];
+ mbedcrypto_ecp_point *T;
+ mbedcrypto_mpi M, mm;
+
+ mbedcrypto_mpi_init( &M );
+ mbedcrypto_mpi_init( &mm );
+
+ /* we need N to be odd to trnaform m in an odd number, check now */
+ if( mbedcrypto_mpi_get_bit( &grp->N, 0 ) != 1 )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ /*
+ * Minimize the number of multiplications, that is minimize
+ * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
+ * (see costs of the various parts, with 1S = 1M)
+ */
+ w = grp->nbits >= 384 ? 5 : 4;
+
+ /*
+ * If P == G, pre-compute a bit more, since this may be re-used later.
+ * Just adding one avoids upping the cost of the first mul too much,
+ * and the memory cost too.
+ */
+#if MBEDCRYPTO_ECP_FIXED_POINT_OPTIM == 1
+ p_eq_g = ( mbedcrypto_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
+ mbedcrypto_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
+ if( p_eq_g )
+ w++;
+#else
+ p_eq_g = 0;
+#endif
+
+ /*
+ * Make sure w is within bounds.
+ * (The last test is useful only for very small curves in the test suite.)
+ */
+ if( w > MBEDCRYPTO_ECP_WINDOW_SIZE )
+ w = MBEDCRYPTO_ECP_WINDOW_SIZE;
+ if( w >= grp->nbits )
+ w = 2;
+
+ /* Other sizes that depend on w */
+ pre_len = 1U << ( w - 1 );
+ d = ( grp->nbits + w - 1 ) / w;
+
+ /*
+ * Prepare precomputed points: if P == G we want to
+ * use grp->T if already initialized, or initialize it.
+ */
+ T = p_eq_g ? grp->T : NULL;
+
+ if( T == NULL )
+ {
+ T = mbedcrypto_calloc( pre_len, sizeof( mbedcrypto_ecp_point ) );
+ if( T == NULL )
+ {
+ ret = MBEDCRYPTO_ERR_ECP_ALLOC_FAILED;
+ goto cleanup;
+ }
+
+ MBEDCRYPTO_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
+
+ if( p_eq_g )
+ {
+ grp->T = T;
+ grp->T_size = pre_len;
+ }
+ }
+
+ /*
+ * Make sure M is odd (M = m or M = N - m, since N is odd)
+ * using the fact that m * P = - (N - m) * P
+ */
+ m_is_odd = ( mbedcrypto_mpi_get_bit( m, 0 ) == 1 );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &M, m ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &mm, &grp->N, m ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
+
+ /*
+ * Go for comb multiplication, R = M * P
+ */
+ ecp_comb_fixed( k, d, w, &M );
+ MBEDCRYPTO_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) );
+
+ /*
+ * Now get m * P from M * P and normalize it
+ */
+ MBEDCRYPTO_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
+ MBEDCRYPTO_MPI_CHK( ecp_normalize_jac( grp, R ) );
+
+cleanup:
+
+ if( T != NULL && ! p_eq_g )
+ {
+ for( i = 0; i < pre_len; i++ )
+ mbedcrypto_ecp_point_free( &T[i] );
+ mbedcrypto_free( T );
+ }
+
+ mbedcrypto_mpi_free( &M );
+ mbedcrypto_mpi_free( &mm );
+
+ if( ret != 0 )
+ mbedcrypto_ecp_point_free( R );
+
+ return( ret );
+}
+
+#endif /* ECP_SHORTWEIERSTRASS */
+
+#if defined(ECP_MONTGOMERY)
+/*
+ * For Montgomery curves, we do all the internal arithmetic in projective
+ * coordinates. Import/export of points uses only the x coordinates, which is
+ * internaly represented as X / Z.
+ *
+ * For scalar multiplication, we'll use a Montgomery ladder.
+ */
+
+/*
+ * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
+ * Cost: 1M + 1I
+ */
+static int ecp_normalize_mxz( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *P )
+{
+ int ret;
+
+#if defined(MBEDCRYPTO_ECP_NORMALIZE_MXZ_ALT)
+ if ( mbedcrypto_internal_ecp_grp_capable( grp ) )
+ {
+ return mbedcrypto_internal_ecp_normalize_mxz( grp, P );
+ }
+#endif /* MBEDCRYPTO_ECP_NORMALIZE_MXZ_ALT */
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &P->Z, 1 ) );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Randomize projective x/z coordinates:
+ * (X, Z) -> (l X, l Z) for random l
+ * This is sort of the reverse operation of ecp_normalize_mxz().
+ *
+ * This countermeasure was first suggested in [2].
+ * Cost: 2M
+ */
+static int ecp_randomize_mxz( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ int ret;
+ mbedcrypto_mpi l;
+ size_t p_size;
+ int count = 0;
+
+#if defined(MBEDCRYPTO_ECP_RANDOMIZE_MXZ_ALT)
+ if ( mbedcrypto_internal_ecp_grp_capable( grp ) )
+ {
+ return mbedcrypto_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
+ }
+#endif /* MBEDCRYPTO_ECP_RANDOMIZE_MXZ_ALT */
+
+ p_size = ( grp->pbits + 7 ) / 8;
+ mbedcrypto_mpi_init( &l );
+
+ /* Generate l such that 1 < l < p */
+ do
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
+
+ while( mbedcrypto_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &l, 1 ) );
+
+ if( count++ > 10 )
+ return( MBEDCRYPTO_ERR_ECP_RANDOM_FAILED );
+ }
+ while( mbedcrypto_mpi_cmp_int( &l, 1 ) <= 0 );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z );
+
+cleanup:
+ mbedcrypto_mpi_free( &l );
+
+ return( ret );
+}
+
+/*
+ * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
+ * for Montgomery curves in x/z coordinates.
+ *
+ * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
+ * with
+ * d = X1
+ * P = (X2, Z2)
+ * Q = (X3, Z3)
+ * R = (X4, Z4)
+ * S = (X5, Z5)
+ * and eliminating temporary variables tO, ..., t4.
+ *
+ * Cost: 5M + 4S
+ */
+static int ecp_double_add_mxz( const mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *R, mbedcrypto_ecp_point *S,
+ const mbedcrypto_ecp_point *P, const mbedcrypto_ecp_point *Q,
+ const mbedcrypto_mpi *d )
+{
+ int ret;
+ mbedcrypto_mpi A, AA, B, BB, E, C, D, DA, CB;
+
+#if defined(MBEDCRYPTO_ECP_DOUBLE_ADD_MXZ_ALT)
+ if ( mbedcrypto_internal_ecp_grp_capable( grp ) )
+ {
+ return mbedcrypto_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
+ }
+#endif /* MBEDCRYPTO_ECP_DOUBLE_ADD_MXZ_ALT */
+
+ mbedcrypto_mpi_init( &A ); mbedcrypto_mpi_init( &AA ); mbedcrypto_mpi_init( &B );
+ mbedcrypto_mpi_init( &BB ); mbedcrypto_mpi_init( &E ); mbedcrypto_mpi_init( &C );
+ mbedcrypto_mpi_init( &D ); mbedcrypto_mpi_init( &DA ); mbedcrypto_mpi_init( &CB );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z );
+
+cleanup:
+ mbedcrypto_mpi_free( &A ); mbedcrypto_mpi_free( &AA ); mbedcrypto_mpi_free( &B );
+ mbedcrypto_mpi_free( &BB ); mbedcrypto_mpi_free( &E ); mbedcrypto_mpi_free( &C );
+ mbedcrypto_mpi_free( &D ); mbedcrypto_mpi_free( &DA ); mbedcrypto_mpi_free( &CB );
+
+ return( ret );
+}
+
+/*
+ * Multiplication with Montgomery ladder in x/z coordinates,
+ * for curves in Montgomery form
+ */
+static int ecp_mul_mxz( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+ const mbedcrypto_mpi *m, const mbedcrypto_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ size_t i;
+ unsigned char b;
+ mbedcrypto_ecp_point RP;
+ mbedcrypto_mpi PX;
+
+ mbedcrypto_ecp_point_init( &RP ); mbedcrypto_mpi_init( &PX );
+
+ /* Save PX and read from P before writing to R, in case P == R */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &PX, &P->X ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_copy( &RP, P ) );
+
+ /* Set R to zero in modified x/z coordinates */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &R->X, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &R->Z, 0 ) );
+ mbedcrypto_mpi_free( &R->Y );
+
+ /* RP.X might be sligtly larger than P, so reduce it */
+ MOD_ADD( RP.X );
+
+ /* Randomize coordinates of the starting point */
+ if( f_rng != NULL )
+ MBEDCRYPTO_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
+
+ /* Loop invariant: R = result so far, RP = R + P */
+ i = mbedcrypto_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
+ while( i-- > 0 )
+ {
+ b = mbedcrypto_mpi_get_bit( m, i );
+ /*
+ * if (b) R = 2R + P else R = 2R,
+ * which is:
+ * if (b) double_add( RP, R, RP, R )
+ * else double_add( R, RP, R, RP )
+ * but using safe conditional swaps to avoid leaks
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
+ MBEDCRYPTO_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
+ }
+
+ MBEDCRYPTO_MPI_CHK( ecp_normalize_mxz( grp, R ) );
+
+cleanup:
+ mbedcrypto_ecp_point_free( &RP ); mbedcrypto_mpi_free( &PX );
+
+ return( ret );
+}
+
+#endif /* ECP_MONTGOMERY */
+
+/*
+ * Multiplication R = m * P
+ */
+int mbedcrypto_ecp_mul( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+ const mbedcrypto_mpi *m, const mbedcrypto_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ int ret = MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA;
+#if defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+ char is_grp_capable = 0;
+#endif
+
+ /* Common sanity checks */
+ if( mbedcrypto_mpi_cmp_int( &P->Z, 1 ) != 0 )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+ if( ( ret = mbedcrypto_ecp_check_privkey( grp, m ) ) != 0 ||
+ ( ret = mbedcrypto_ecp_check_pubkey( grp, P ) ) != 0 )
+ return( ret );
+
+#if defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+ if ( is_grp_capable = mbedcrypto_internal_ecp_grp_capable( grp ) )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_internal_ecp_init( grp ) );
+ }
+
+#endif /* MBEDCRYPTO_ECP_INTERNAL_ALT */
+#if defined(ECP_MONTGOMERY)
+ if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
+ ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
+
+#endif
+#if defined(ECP_SHORTWEIERSTRASS)
+ if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
+ ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
+
+#endif
+#if defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+cleanup:
+
+ if ( is_grp_capable )
+ {
+ mbedcrypto_internal_ecp_free( grp );
+ }
+
+#endif /* MBEDCRYPTO_ECP_INTERNAL_ALT */
+ return( ret );
+}
+
+#if defined(ECP_SHORTWEIERSTRASS)
+/*
+ * Check that an affine point is valid as a public key,
+ * short weierstrass curves (SEC1 3.2.3.1)
+ */
+static int ecp_check_pubkey_sw( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *pt )
+{
+ int ret;
+ mbedcrypto_mpi YY, RHS;
+
+ /* pt coordinates must be normalized for our checks */
+ if( mbedcrypto_mpi_cmp_int( &pt->X, 0 ) < 0 ||
+ mbedcrypto_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
+ mbedcrypto_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
+ mbedcrypto_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
+ return( MBEDCRYPTO_ERR_ECP_INVALID_KEY );
+
+ mbedcrypto_mpi_init( &YY ); mbedcrypto_mpi_init( &RHS );
+
+ /*
+ * YY = Y^2
+ * RHS = X (X^2 + A) + B = X^3 + A X + B
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
+
+ /* Special case for A = -3 */
+ if( grp->A.p == NULL )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
+
+ if( mbedcrypto_mpi_cmp_mpi( &YY, &RHS ) != 0 )
+ ret = MBEDCRYPTO_ERR_ECP_INVALID_KEY;
+
+cleanup:
+
+ mbedcrypto_mpi_free( &YY ); mbedcrypto_mpi_free( &RHS );
+
+ return( ret );
+}
+#endif /* ECP_SHORTWEIERSTRASS */
+
+/*
+ * R = m * P with shortcuts for m == 1 and m == -1
+ * NOT constant-time - ONLY for short Weierstrass!
+ */
+static int mbedcrypto_ecp_mul_shortcuts( mbedcrypto_ecp_group *grp,
+ mbedcrypto_ecp_point *R,
+ const mbedcrypto_mpi *m,
+ const mbedcrypto_ecp_point *P )
+{
+ int ret;
+
+ if( mbedcrypto_mpi_cmp_int( m, 1 ) == 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_copy( R, P ) );
+ }
+ else if( mbedcrypto_mpi_cmp_int( m, -1 ) == 0 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_copy( R, P ) );
+ if( mbedcrypto_mpi_cmp_int( &R->Y, 0 ) != 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_mul( grp, R, m, P, NULL, NULL ) );
+ }
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Linear combination
+ * NOT constant-time
+ */
+int mbedcrypto_ecp_muladd( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_point *R,
+ const mbedcrypto_mpi *m, const mbedcrypto_ecp_point *P,
+ const mbedcrypto_mpi *n, const mbedcrypto_ecp_point *Q )
+{
+ int ret;
+ mbedcrypto_ecp_point mP;
+#if defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+ char is_grp_capable = 0;
+#endif
+
+ if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
+ return( MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE );
+
+ mbedcrypto_ecp_point_init( &mP );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_mul_shortcuts( grp, &mP, m, P ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_mul_shortcuts( grp, R, n, Q ) );
+
+#if defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+ if ( is_grp_capable = mbedcrypto_internal_ecp_grp_capable( grp ) )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_internal_ecp_init( grp ) );
+ }
+
+#endif /* MBEDCRYPTO_ECP_INTERNAL_ALT */
+ MBEDCRYPTO_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
+ MBEDCRYPTO_MPI_CHK( ecp_normalize_jac( grp, R ) );
+
+cleanup:
+
+#if defined(MBEDCRYPTO_ECP_INTERNAL_ALT)
+ if ( is_grp_capable )
+ {
+ mbedcrypto_internal_ecp_free( grp );
+ }
+
+#endif /* MBEDCRYPTO_ECP_INTERNAL_ALT */
+ mbedcrypto_ecp_point_free( &mP );
+
+ return( ret );
+}
+
+
+#if defined(ECP_MONTGOMERY)
+/*
+ * Check validity of a public key for Montgomery curves with x-only schemes
+ */
+static int ecp_check_pubkey_mx( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *pt )
+{
+ /* [Curve25519 p. 5] Just check X is the correct number of bytes */
+ /* Allow any public value, if it's too big then we'll just reduce it mod p
+ * (RFC 7748 sec. 5 para. 3). */
+ if( mbedcrypto_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
+ return( MBEDCRYPTO_ERR_ECP_INVALID_KEY );
+
+ return( 0 );
+}
+#endif /* ECP_MONTGOMERY */
+
+/*
+ * Check that a point is valid as a public key
+ */
+int mbedcrypto_ecp_check_pubkey( const mbedcrypto_ecp_group *grp, const mbedcrypto_ecp_point *pt )
+{
+ /* Must use affine coordinates */
+ if( mbedcrypto_mpi_cmp_int( &pt->Z, 1 ) != 0 )
+ return( MBEDCRYPTO_ERR_ECP_INVALID_KEY );
+
+#if defined(ECP_MONTGOMERY)
+ if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
+ return( ecp_check_pubkey_mx( grp, pt ) );
+#endif
+#if defined(ECP_SHORTWEIERSTRASS)
+ if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
+ return( ecp_check_pubkey_sw( grp, pt ) );
+#endif
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+}
+
+/*
+ * Check that an mbedcrypto_mpi is valid as a private key
+ */
+int mbedcrypto_ecp_check_privkey( const mbedcrypto_ecp_group *grp, const mbedcrypto_mpi *d )
+{
+#if defined(ECP_MONTGOMERY)
+ if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
+ {
+ /* see RFC 7748 sec. 5 para. 5 */
+ if( mbedcrypto_mpi_get_bit( d, 0 ) != 0 ||
+ mbedcrypto_mpi_get_bit( d, 1 ) != 0 ||
+ mbedcrypto_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedcrypto_mpi_bitlen is one-based! */
+ return( MBEDCRYPTO_ERR_ECP_INVALID_KEY );
+ else
+
+ /* see [Curve25519] page 5 */
+ if( grp->nbits == 254 && mbedcrypto_mpi_get_bit( d, 2 ) != 0 )
+ return( MBEDCRYPTO_ERR_ECP_INVALID_KEY );
+
+ return( 0 );
+ }
+#endif /* ECP_MONTGOMERY */
+#if defined(ECP_SHORTWEIERSTRASS)
+ if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
+ {
+ /* see SEC1 3.2 */
+ if( mbedcrypto_mpi_cmp_int( d, 1 ) < 0 ||
+ mbedcrypto_mpi_cmp_mpi( d, &grp->N ) >= 0 )
+ return( MBEDCRYPTO_ERR_ECP_INVALID_KEY );
+ else
+ return( 0 );
+ }
+#endif /* ECP_SHORTWEIERSTRASS */
+
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+}
+
+/*
+ * Generate a keypair with configurable base point
+ */
+int mbedcrypto_ecp_gen_keypair_base( mbedcrypto_ecp_group *grp,
+ const mbedcrypto_ecp_point *G,
+ mbedcrypto_mpi *d, mbedcrypto_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+ size_t n_size = ( grp->nbits + 7 ) / 8;
+
+#if defined(ECP_MONTGOMERY)
+ if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
+ {
+ /* [M225] page 5 */
+ size_t b;
+
+ do {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( d, n_size, f_rng, p_rng ) );
+ } while( mbedcrypto_mpi_bitlen( d ) == 0);
+
+ /* Make sure the most significant bit is nbits */
+ b = mbedcrypto_mpi_bitlen( d ) - 1; /* mbedcrypto_mpi_bitlen is one-based */
+ if( b > grp->nbits )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( d, b - grp->nbits ) );
+ else
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_set_bit( d, grp->nbits, 1 ) );
+
+ /* Make sure the last two bits are unset for Curve448, three bits for
+ Curve25519 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_set_bit( d, 0, 0 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_set_bit( d, 1, 0 ) );
+ if( grp->nbits == 254 )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_set_bit( d, 2, 0 ) );
+ }
+ }
+ else
+#endif /* ECP_MONTGOMERY */
+#if defined(ECP_SHORTWEIERSTRASS)
+ if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
+ {
+ /* SEC1 3.2.1: Generate d such that 1 <= n < N */
+ int count = 0;
+
+ /*
+ * Match the procedure given in RFC 6979 (deterministic ECDSA):
+ * - use the same byte ordering;
+ * - keep the leftmost nbits bits of the generated octet string;
+ * - try until result is in the desired range.
+ * This also avoids any biais, which is especially important for ECDSA.
+ */
+ do
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( d, n_size, f_rng, p_rng ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
+
+ /*
+ * Each try has at worst a probability 1/2 of failing (the msb has
+ * a probability 1/2 of being 0, and then the result will be < N),
+ * so after 30 tries failure probability is a most 2**(-30).
+ *
+ * For most curves, 1 try is enough with overwhelming probability,
+ * since N starts with a lot of 1s in binary, but some curves
+ * such as secp224k1 are actually very close to the worst case.
+ */
+ if( ++count > 30 )
+ return( MBEDCRYPTO_ERR_ECP_RANDOM_FAILED );
+ }
+ while( mbedcrypto_mpi_cmp_int( d, 1 ) < 0 ||
+ mbedcrypto_mpi_cmp_mpi( d, &grp->N ) >= 0 );
+ }
+ else
+#endif /* ECP_SHORTWEIERSTRASS */
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+
+cleanup:
+ if( ret != 0 )
+ return( ret );
+
+ return( mbedcrypto_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
+}
+
+/*
+ * Generate key pair, wrapper for conventional base point
+ */
+int mbedcrypto_ecp_gen_keypair( mbedcrypto_ecp_group *grp,
+ mbedcrypto_mpi *d, mbedcrypto_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ return( mbedcrypto_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
+}
+
+/*
+ * Generate a keypair, prettier wrapper
+ */
+int mbedcrypto_ecp_gen_key( mbedcrypto_ecp_group_id grp_id, mbedcrypto_ecp_keypair *key,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ int ret;
+
+ if( ( ret = mbedcrypto_ecp_group_load( &key->grp, grp_id ) ) != 0 )
+ return( ret );
+
+ return( mbedcrypto_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
+}
+
+/*
+ * Check a public-private key pair
+ */
+int mbedcrypto_ecp_check_pub_priv( const mbedcrypto_ecp_keypair *pub, const mbedcrypto_ecp_keypair *prv )
+{
+ int ret;
+ mbedcrypto_ecp_point Q;
+ mbedcrypto_ecp_group grp;
+
+ if( pub->grp.id == MBEDCRYPTO_ECP_DP_NONE ||
+ pub->grp.id != prv->grp.id ||
+ mbedcrypto_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
+ mbedcrypto_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
+ mbedcrypto_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
+ {
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+ }
+
+ mbedcrypto_ecp_point_init( &Q );
+ mbedcrypto_ecp_group_init( &grp );
+
+ /* mbedcrypto_ecp_mul() needs a non-const group... */
+ mbedcrypto_ecp_group_copy( &grp, &prv->grp );
+
+ /* Also checks d is valid */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
+
+ if( mbedcrypto_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
+ mbedcrypto_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
+ mbedcrypto_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
+ {
+ ret = MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+cleanup:
+ mbedcrypto_ecp_point_free( &Q );
+ mbedcrypto_ecp_group_free( &grp );
+
+ return( ret );
+}
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_ecp_self_test( int verbose )
+{
+ int ret;
+ size_t i;
+ mbedcrypto_ecp_group grp;
+ mbedcrypto_ecp_point R, P;
+ mbedcrypto_mpi m;
+ unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
+ /* exponents especially adapted for secp192r1 */
+ const char *exponents[] =
+ {
+ "000000000000000000000000000000000000000000000001", /* one */
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
+ "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
+ "400000000000000000000000000000000000000000000000", /* one and zeros */
+ "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
+ "555555555555555555555555555555555555555555555555", /* 101010... */
+ };
+
+ mbedcrypto_ecp_group_init( &grp );
+ mbedcrypto_ecp_point_init( &R );
+ mbedcrypto_ecp_point_init( &P );
+ mbedcrypto_mpi_init( &m );
+
+ /* Use secp192r1 if available, or any available curve */
+#if defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED)
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_group_load( &grp, MBEDCRYPTO_ECP_DP_SECP192R1 ) );
+#else
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_group_load( &grp, mbedcrypto_ecp_curve_list()->grp_id ) );
+#endif
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " ECP test #1 (constant op_count, base point G): " );
+
+ /* Do a dummy multiplication first to trigger precomputation */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &m, 2 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
+
+ add_count = 0;
+ dbl_count = 0;
+ mul_count = 0;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &m, 16, exponents[0] ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
+
+ for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
+ {
+ add_c_prev = add_count;
+ dbl_c_prev = dbl_count;
+ mul_c_prev = mul_count;
+ add_count = 0;
+ dbl_count = 0;
+ mul_count = 0;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &m, 16, exponents[i] ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
+
+ if( add_count != add_c_prev ||
+ dbl_count != dbl_c_prev ||
+ mul_count != mul_c_prev )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed (%u)\n", (unsigned int) i );
+
+ ret = 1;
+ goto cleanup;
+ }
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " ECP test #2 (constant op_count, other point): " );
+ /* We computed P = 2G last time, use it */
+
+ add_count = 0;
+ dbl_count = 0;
+ mul_count = 0;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &m, 16, exponents[0] ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
+
+ for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
+ {
+ add_c_prev = add_count;
+ dbl_c_prev = dbl_count;
+ mul_c_prev = mul_count;
+ add_count = 0;
+ dbl_count = 0;
+ mul_count = 0;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &m, 16, exponents[i] ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
+
+ if( add_count != add_c_prev ||
+ dbl_count != dbl_c_prev ||
+ mul_count != mul_c_prev )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed (%u)\n", (unsigned int) i );
+
+ ret = 1;
+ goto cleanup;
+ }
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+cleanup:
+
+ if( ret < 0 && verbose != 0 )
+ mbedcrypto_printf( "Unexpected error, return code = %08X\n", ret );
+
+ mbedcrypto_ecp_group_free( &grp );
+ mbedcrypto_ecp_point_free( &R );
+ mbedcrypto_ecp_point_free( &P );
+ mbedcrypto_mpi_free( &m );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* !MBEDCRYPTO_ECP_ALT */
+
+#endif /* MBEDCRYPTO_ECP_C */
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
new file mode 100644
index 0000000..70157b2
--- /dev/null
+++ b/library/ecp_curves.c
@@ -0,0 +1,1460 @@
+/*
+ * Elliptic curves over GF(p): curve-specific data and functions
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_ECP_C)
+
+#include "mbedcrypto/ecp.h"
+
+#include <string.h>
+
+#if !defined(MBEDCRYPTO_ECP_ALT)
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+/*
+ * Conversion macros for embedded constants:
+ * build lists of mbedcrypto_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2
+ */
+#if defined(MBEDCRYPTO_HAVE_INT32)
+
+#define BYTES_TO_T_UINT_4( a, b, c, d ) \
+ ( (mbedcrypto_mpi_uint) a << 0 ) | \
+ ( (mbedcrypto_mpi_uint) b << 8 ) | \
+ ( (mbedcrypto_mpi_uint) c << 16 ) | \
+ ( (mbedcrypto_mpi_uint) d << 24 )
+
+#define BYTES_TO_T_UINT_2( a, b ) \
+ BYTES_TO_T_UINT_4( a, b, 0, 0 )
+
+#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+ BYTES_TO_T_UINT_4( a, b, c, d ), \
+ BYTES_TO_T_UINT_4( e, f, g, h )
+
+#else /* 64-bits */
+
+#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+ ( (mbedcrypto_mpi_uint) a << 0 ) | \
+ ( (mbedcrypto_mpi_uint) b << 8 ) | \
+ ( (mbedcrypto_mpi_uint) c << 16 ) | \
+ ( (mbedcrypto_mpi_uint) d << 24 ) | \
+ ( (mbedcrypto_mpi_uint) e << 32 ) | \
+ ( (mbedcrypto_mpi_uint) f << 40 ) | \
+ ( (mbedcrypto_mpi_uint) g << 48 ) | \
+ ( (mbedcrypto_mpi_uint) h << 56 )
+
+#define BYTES_TO_T_UINT_4( a, b, c, d ) \
+ BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 )
+
+#define BYTES_TO_T_UINT_2( a, b ) \
+ BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 )
+
+#endif /* bits in mbedcrypto_mpi_uint */
+
+/*
+ * Note: the constants are in little-endian order
+ * to be directly usable in MPIs
+ */
+
+/*
+ * Domain parameters for secp192r1
+ */
+#if defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED)
+static const mbedcrypto_mpi_uint secp192r1_p[] = {
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const mbedcrypto_mpi_uint secp192r1_b[] = {
+ BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ),
+ BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ),
+ BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ),
+};
+static const mbedcrypto_mpi_uint secp192r1_gx[] = {
+ BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ),
+ BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ),
+ BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ),
+};
+static const mbedcrypto_mpi_uint secp192r1_gy[] = {
+ BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ),
+ BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ),
+ BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ),
+};
+static const mbedcrypto_mpi_uint secp192r1_n[] = {
+ BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ),
+ BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED */
+
+/*
+ * Domain parameters for secp224r1
+ */
+#if defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED)
+static const mbedcrypto_mpi_uint secp224r1_p[] = {
+ BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+ BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+};
+static const mbedcrypto_mpi_uint secp224r1_b[] = {
+ BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ),
+ BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ),
+ BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ),
+ BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ),
+};
+static const mbedcrypto_mpi_uint secp224r1_gx[] = {
+ BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ),
+ BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ),
+ BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ),
+ BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ),
+};
+static const mbedcrypto_mpi_uint secp224r1_gy[] = {
+ BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ),
+ BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ),
+ BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ),
+ BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ),
+};
+static const mbedcrypto_mpi_uint secp224r1_n[] = {
+ BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ),
+ BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED */
+
+/*
+ * Domain parameters for secp256r1
+ */
+#if defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED)
+static const mbedcrypto_mpi_uint secp256r1_p[] = {
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+ BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+ BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const mbedcrypto_mpi_uint secp256r1_b[] = {
+ BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ),
+ BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ),
+ BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ),
+ BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ),
+};
+static const mbedcrypto_mpi_uint secp256r1_gx[] = {
+ BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ),
+ BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ),
+ BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ),
+ BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ),
+};
+static const mbedcrypto_mpi_uint secp256r1_gy[] = {
+ BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ),
+ BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ),
+ BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ),
+ BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ),
+};
+static const mbedcrypto_mpi_uint secp256r1_n[] = {
+ BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ),
+ BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED */
+
+/*
+ * Domain parameters for secp384r1
+ */
+#if defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED)
+static const mbedcrypto_mpi_uint secp384r1_p[] = {
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+ BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const mbedcrypto_mpi_uint secp384r1_b[] = {
+ BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ),
+ BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ),
+ BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ),
+ BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ),
+ BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ),
+ BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ),
+};
+static const mbedcrypto_mpi_uint secp384r1_gx[] = {
+ BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ),
+ BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ),
+ BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ),
+ BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ),
+ BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ),
+ BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ),
+};
+static const mbedcrypto_mpi_uint secp384r1_gy[] = {
+ BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ),
+ BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ),
+ BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ),
+ BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ),
+ BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ),
+ BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ),
+};
+static const mbedcrypto_mpi_uint secp384r1_n[] = {
+ BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ),
+ BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ),
+ BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED */
+
+/*
+ * Domain parameters for secp521r1
+ */
+#if defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED)
+static const mbedcrypto_mpi_uint secp521r1_p[] = {
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
+};
+static const mbedcrypto_mpi_uint secp521r1_b[] = {
+ BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ),
+ BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ),
+ BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ),
+ BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ),
+ BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ),
+ BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ),
+ BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ),
+ BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ),
+ BYTES_TO_T_UINT_2( 0x51, 0x00 ),
+};
+static const mbedcrypto_mpi_uint secp521r1_gx[] = {
+ BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ),
+ BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ),
+ BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ),
+ BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ),
+ BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ),
+ BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ),
+ BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ),
+ BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ),
+ BYTES_TO_T_UINT_2( 0xC6, 0x00 ),
+};
+static const mbedcrypto_mpi_uint secp521r1_gy[] = {
+ BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ),
+ BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ),
+ BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ),
+ BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ),
+ BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ),
+ BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ),
+ BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ),
+ BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ),
+ BYTES_TO_T_UINT_2( 0x18, 0x01 ),
+};
+static const mbedcrypto_mpi_uint secp521r1_n[] = {
+ BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ),
+ BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ),
+ BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ),
+ BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ),
+ BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED)
+static const mbedcrypto_mpi_uint secp192k1_p[] = {
+ BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const mbedcrypto_mpi_uint secp192k1_a[] = {
+ BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+};
+static const mbedcrypto_mpi_uint secp192k1_b[] = {
+ BYTES_TO_T_UINT_2( 0x03, 0x00 ),
+};
+static const mbedcrypto_mpi_uint secp192k1_gx[] = {
+ BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ),
+ BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ),
+ BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ),
+};
+static const mbedcrypto_mpi_uint secp192k1_gy[] = {
+ BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ),
+ BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ),
+ BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ),
+};
+static const mbedcrypto_mpi_uint secp192k1_n[] = {
+ BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ),
+ BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED)
+static const mbedcrypto_mpi_uint secp224k1_p[] = {
+ BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const mbedcrypto_mpi_uint secp224k1_a[] = {
+ BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+};
+static const mbedcrypto_mpi_uint secp224k1_b[] = {
+ BYTES_TO_T_UINT_2( 0x05, 0x00 ),
+};
+static const mbedcrypto_mpi_uint secp224k1_gx[] = {
+ BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ),
+ BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ),
+ BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ),
+ BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ),
+};
+static const mbedcrypto_mpi_uint secp224k1_gy[] = {
+ BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ),
+ BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ),
+ BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ),
+ BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ),
+};
+static const mbedcrypto_mpi_uint secp224k1_n[] = {
+ BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ),
+ BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ),
+ BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
+ BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED)
+static const mbedcrypto_mpi_uint secp256k1_p[] = {
+ BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+static const mbedcrypto_mpi_uint secp256k1_a[] = {
+ BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+};
+static const mbedcrypto_mpi_uint secp256k1_b[] = {
+ BYTES_TO_T_UINT_2( 0x07, 0x00 ),
+};
+static const mbedcrypto_mpi_uint secp256k1_gx[] = {
+ BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ),
+ BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ),
+ BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ),
+ BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ),
+};
+static const mbedcrypto_mpi_uint secp256k1_gy[] = {
+ BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ),
+ BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ),
+ BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ),
+ BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ),
+};
+static const mbedcrypto_mpi_uint secp256k1_n[] = {
+ BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ),
+ BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ),
+ BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+ BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)
+ */
+#if defined(MBEDCRYPTO_ECP_DP_BP256R1_ENABLED)
+static const mbedcrypto_mpi_uint brainpoolP256r1_p[] = {
+ BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ),
+ BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ),
+ BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
+ BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
+};
+static const mbedcrypto_mpi_uint brainpoolP256r1_a[] = {
+ BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ),
+ BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ),
+ BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ),
+ BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ),
+};
+static const mbedcrypto_mpi_uint brainpoolP256r1_b[] = {
+ BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ),
+ BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ),
+ BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ),
+ BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ),
+};
+static const mbedcrypto_mpi_uint brainpoolP256r1_gx[] = {
+ BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ),
+ BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ),
+ BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ),
+ BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ),
+};
+static const mbedcrypto_mpi_uint brainpoolP256r1_gy[] = {
+ BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ),
+ BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ),
+ BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ),
+ BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ),
+};
+static const mbedcrypto_mpi_uint brainpoolP256r1_n[] = {
+ BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ),
+ BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ),
+ BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
+ BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_BP256R1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)
+ */
+#if defined(MBEDCRYPTO_ECP_DP_BP384R1_ENABLED)
+static const mbedcrypto_mpi_uint brainpoolP384r1_p[] = {
+ BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ),
+ BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ),
+ BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ),
+ BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
+ BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
+ BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
+};
+static const mbedcrypto_mpi_uint brainpoolP384r1_a[] = {
+ BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
+ BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ),
+ BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ),
+ BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ),
+ BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ),
+ BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ),
+};
+static const mbedcrypto_mpi_uint brainpoolP384r1_b[] = {
+ BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ),
+ BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ),
+ BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ),
+ BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ),
+ BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ),
+ BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
+};
+static const mbedcrypto_mpi_uint brainpoolP384r1_gx[] = {
+ BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ),
+ BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ),
+ BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ),
+ BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ),
+ BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ),
+ BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ),
+};
+static const mbedcrypto_mpi_uint brainpoolP384r1_gy[] = {
+ BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ),
+ BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ),
+ BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ),
+ BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ),
+ BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ),
+ BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ),
+};
+static const mbedcrypto_mpi_uint brainpoolP384r1_n[] = {
+ BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ),
+ BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ),
+ BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ),
+ BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
+ BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
+ BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_BP384R1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)
+ */
+#if defined(MBEDCRYPTO_ECP_DP_BP512R1_ENABLED)
+static const mbedcrypto_mpi_uint brainpoolP512r1_p[] = {
+ BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ),
+ BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ),
+ BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ),
+ BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ),
+ BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
+ BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
+ BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
+ BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
+};
+static const mbedcrypto_mpi_uint brainpoolP512r1_a[] = {
+ BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ),
+ BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ),
+ BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ),
+ BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ),
+ BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ),
+ BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ),
+ BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ),
+ BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ),
+};
+static const mbedcrypto_mpi_uint brainpoolP512r1_b[] = {
+ BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ),
+ BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ),
+ BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ),
+ BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ),
+ BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ),
+ BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ),
+ BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ),
+ BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ),
+};
+static const mbedcrypto_mpi_uint brainpoolP512r1_gx[] = {
+ BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ),
+ BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ),
+ BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ),
+ BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ),
+ BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ),
+ BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ),
+ BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ),
+ BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ),
+};
+static const mbedcrypto_mpi_uint brainpoolP512r1_gy[] = {
+ BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ),
+ BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ),
+ BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ),
+ BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ),
+ BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ),
+ BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ),
+ BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ),
+ BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ),
+};
+static const mbedcrypto_mpi_uint brainpoolP512r1_n[] = {
+ BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ),
+ BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ),
+ BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ),
+ BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ),
+ BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
+ BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
+ BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
+ BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
+};
+#endif /* MBEDCRYPTO_ECP_DP_BP512R1_ENABLED */
+
+/*
+ * Create an MPI from embedded constants
+ * (assumes len is an exact multiple of sizeof mbedcrypto_mpi_uint)
+ */
+static inline void ecp_mpi_load( mbedcrypto_mpi *X, const mbedcrypto_mpi_uint *p, size_t len )
+{
+ X->s = 1;
+ X->n = len / sizeof( mbedcrypto_mpi_uint );
+ X->p = (mbedcrypto_mpi_uint *) p;
+}
+
+/*
+ * Set an MPI to static value 1
+ */
+static inline void ecp_mpi_set1( mbedcrypto_mpi *X )
+{
+ static mbedcrypto_mpi_uint one[] = { 1 };
+ X->s = 1;
+ X->n = 1;
+ X->p = one;
+}
+
+/*
+ * Make group available from embedded constants
+ */
+static int ecp_group_load( mbedcrypto_ecp_group *grp,
+ const mbedcrypto_mpi_uint *p, size_t plen,
+ const mbedcrypto_mpi_uint *a, size_t alen,
+ const mbedcrypto_mpi_uint *b, size_t blen,
+ const mbedcrypto_mpi_uint *gx, size_t gxlen,
+ const mbedcrypto_mpi_uint *gy, size_t gylen,
+ const mbedcrypto_mpi_uint *n, size_t nlen)
+{
+ ecp_mpi_load( &grp->P, p, plen );
+ if( a != NULL )
+ ecp_mpi_load( &grp->A, a, alen );
+ ecp_mpi_load( &grp->B, b, blen );
+ ecp_mpi_load( &grp->N, n, nlen );
+
+ ecp_mpi_load( &grp->G.X, gx, gxlen );
+ ecp_mpi_load( &grp->G.Y, gy, gylen );
+ ecp_mpi_set1( &grp->G.Z );
+
+ grp->pbits = mbedcrypto_mpi_bitlen( &grp->P );
+ grp->nbits = mbedcrypto_mpi_bitlen( &grp->N );
+
+ grp->h = 1;
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_ECP_NIST_OPTIM)
+/* Forward declarations */
+#if defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED)
+static int ecp_mod_p192( mbedcrypto_mpi * );
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED)
+static int ecp_mod_p224( mbedcrypto_mpi * );
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED)
+static int ecp_mod_p256( mbedcrypto_mpi * );
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED)
+static int ecp_mod_p384( mbedcrypto_mpi * );
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED)
+static int ecp_mod_p521( mbedcrypto_mpi * );
+#endif
+
+#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P;
+#else
+#define NIST_MODP( P )
+#endif /* MBEDCRYPTO_ECP_NIST_OPTIM */
+
+/* Additional forward declarations */
+#if defined(MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED)
+static int ecp_mod_p255( mbedcrypto_mpi * );
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_CURVE448_ENABLED)
+static int ecp_mod_p448( mbedcrypto_mpi * );
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED)
+static int ecp_mod_p192k1( mbedcrypto_mpi * );
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED)
+static int ecp_mod_p224k1( mbedcrypto_mpi * );
+#endif
+#if defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED)
+static int ecp_mod_p256k1( mbedcrypto_mpi * );
+#endif
+
+#define LOAD_GROUP_A( G ) ecp_group_load( grp, \
+ G ## _p, sizeof( G ## _p ), \
+ G ## _a, sizeof( G ## _a ), \
+ G ## _b, sizeof( G ## _b ), \
+ G ## _gx, sizeof( G ## _gx ), \
+ G ## _gy, sizeof( G ## _gy ), \
+ G ## _n, sizeof( G ## _n ) )
+
+#define LOAD_GROUP( G ) ecp_group_load( grp, \
+ G ## _p, sizeof( G ## _p ), \
+ NULL, 0, \
+ G ## _b, sizeof( G ## _b ), \
+ G ## _gx, sizeof( G ## _gx ), \
+ G ## _gy, sizeof( G ## _gy ), \
+ G ## _n, sizeof( G ## _n ) )
+
+#if defined(MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED)
+/*
+ * Specialized function for creating the Curve25519 group
+ */
+static int ecp_use_curve25519( mbedcrypto_ecp_group *grp )
+{
+ int ret;
+
+ /* Actually ( A + 2 ) / 4 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &grp->A, 16, "01DB42" ) );
+
+ /* P = 2^255 - 19 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &grp->P, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &grp->P, 255 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &grp->P, &grp->P, 19 ) );
+ grp->pbits = mbedcrypto_mpi_bitlen( &grp->P );
+
+ /* N = 2^252 + 27742317777372353535851937790883648493 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &grp->N, 16,
+ "14DEF9DEA2F79CD65812631A5CF5D3ED" ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_set_bit( &grp->N, 252, 1 ) );
+
+ /* Y intentionally not set, since we use x/z coordinates.
+ * This is used as a marker to identify Montgomery curves! */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &grp->G.X, 9 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &grp->G.Z, 1 ) );
+ mbedcrypto_mpi_free( &grp->G.Y );
+
+ /* Actually, the required msb for private keys */
+ grp->nbits = 254;
+
+cleanup:
+ if( ret != 0 )
+ mbedcrypto_ecp_group_free( grp );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_CURVE448_ENABLED)
+/*
+ * Specialized function for creating the Curve448 group
+ */
+static int ecp_use_curve448( mbedcrypto_ecp_group *grp )
+{
+ mbedcrypto_mpi Ns;
+ int ret;
+
+ mbedcrypto_mpi_init( &Ns );
+
+ /* Actually ( A + 2 ) / 4 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &grp->A, 16, "98AA" ) );
+
+ /* P = 2^448 - 2^224 - 1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &grp->P, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &grp->P, 224 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &grp->P, &grp->P, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &grp->P, 224 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &grp->P, &grp->P, 1 ) );
+ grp->pbits = mbedcrypto_mpi_bitlen( &grp->P );
+
+ /* Y intentionally not set, since we use x/z coordinates.
+ * This is used as a marker to identify Montgomery curves! */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &grp->G.X, 5 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &grp->G.Z, 1 ) );
+ mbedcrypto_mpi_free( &grp->G.Y );
+
+ /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_set_bit( &grp->N, 446, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &Ns, 16,
+ "8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D" ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) );
+
+ /* Actually, the required msb for private keys */
+ grp->nbits = 447;
+
+cleanup:
+ mbedcrypto_mpi_free( &Ns );
+ if( ret != 0 )
+ mbedcrypto_ecp_group_free( grp );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECP_DP_CURVE448_ENABLED */
+
+/*
+ * Set a group using well-known domain parameters
+ */
+int mbedcrypto_ecp_group_load( mbedcrypto_ecp_group *grp, mbedcrypto_ecp_group_id id )
+{
+ mbedcrypto_ecp_group_free( grp );
+
+ grp->id = id;
+
+ switch( id )
+ {
+#if defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_SECP192R1:
+ NIST_MODP( p192 );
+ return( LOAD_GROUP( secp192r1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_SECP224R1:
+ NIST_MODP( p224 );
+ return( LOAD_GROUP( secp224r1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_SECP256R1:
+ NIST_MODP( p256 );
+ return( LOAD_GROUP( secp256r1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_SECP384R1:
+ NIST_MODP( p384 );
+ return( LOAD_GROUP( secp384r1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_SECP521R1:
+ NIST_MODP( p521 );
+ return( LOAD_GROUP( secp521r1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_SECP192K1:
+ grp->modp = ecp_mod_p192k1;
+ return( LOAD_GROUP_A( secp192k1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_SECP224K1:
+ grp->modp = ecp_mod_p224k1;
+ return( LOAD_GROUP_A( secp224k1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_SECP256K1:
+ grp->modp = ecp_mod_p256k1;
+ return( LOAD_GROUP_A( secp256k1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_BP256R1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_BP256R1:
+ return( LOAD_GROUP_A( brainpoolP256r1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_BP256R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_BP384R1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_BP384R1:
+ return( LOAD_GROUP_A( brainpoolP384r1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_BP384R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_BP512R1_ENABLED)
+ case MBEDCRYPTO_ECP_DP_BP512R1:
+ return( LOAD_GROUP_A( brainpoolP512r1 ) );
+#endif /* MBEDCRYPTO_ECP_DP_BP512R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED)
+ case MBEDCRYPTO_ECP_DP_CURVE25519:
+ grp->modp = ecp_mod_p255;
+ return( ecp_use_curve25519( grp ) );
+#endif /* MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_CURVE448_ENABLED)
+ case MBEDCRYPTO_ECP_DP_CURVE448:
+ grp->modp = ecp_mod_p448;
+ return( ecp_use_curve448( grp ) );
+#endif /* MBEDCRYPTO_ECP_DP_CURVE448_ENABLED */
+
+ default:
+ mbedcrypto_ecp_group_free( grp );
+ return( MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE );
+ }
+}
+
+#if defined(MBEDCRYPTO_ECP_NIST_OPTIM)
+/*
+ * Fast reduction modulo the primes used by the NIST curves.
+ *
+ * These functions are critical for speed, but not needed for correct
+ * operations. So, we make the choice to heavily rely on the internals of our
+ * bignum library, which creates a tight coupling between these functions and
+ * our MPI implementation. However, the coupling between the ECP module and
+ * MPI remains loose, since these functions can be deactivated at will.
+ */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED)
+/*
+ * Compared to the way things are presented in FIPS 186-3 D.2,
+ * we proceed in columns, from right (least significant chunk) to left,
+ * adding chunks to N in place, and keeping a carry for the next chunk.
+ * This avoids moving things around in memory, and uselessly adding zeros,
+ * compared to the more straightforward, line-oriented approach.
+ *
+ * For this prime we need to handle data in chunks of 64 bits.
+ * Since this is always a multiple of our basic mbedcrypto_mpi_uint, we can
+ * use a mbedcrypto_mpi_uint * to designate such a chunk, and small loops to handle it.
+ */
+
+/* Add 64-bit chunks (dst += src) and update carry */
+static inline void add64( mbedcrypto_mpi_uint *dst, mbedcrypto_mpi_uint *src, mbedcrypto_mpi_uint *carry )
+{
+ unsigned char i;
+ mbedcrypto_mpi_uint c = 0;
+ for( i = 0; i < 8 / sizeof( mbedcrypto_mpi_uint ); i++, dst++, src++ )
+ {
+ *dst += c; c = ( *dst < c );
+ *dst += *src; c += ( *dst < *src );
+ }
+ *carry += c;
+}
+
+/* Add carry to a 64-bit chunk and update carry */
+static inline void carry64( mbedcrypto_mpi_uint *dst, mbedcrypto_mpi_uint *carry )
+{
+ unsigned char i;
+ for( i = 0; i < 8 / sizeof( mbedcrypto_mpi_uint ); i++, dst++ )
+ {
+ *dst += *carry;
+ *carry = ( *dst < *carry );
+ }
+}
+
+#define WIDTH 8 / sizeof( mbedcrypto_mpi_uint )
+#define A( i ) N->p + i * WIDTH
+#define ADD( i ) add64( p, A( i ), &c )
+#define NEXT p += WIDTH; carry64( p, &c )
+#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0
+
+/*
+ * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
+ */
+static int ecp_mod_p192( mbedcrypto_mpi *N )
+{
+ int ret;
+ mbedcrypto_mpi_uint c = 0;
+ mbedcrypto_mpi_uint *p, *end;
+
+ /* Make sure we have enough blocks so that A(5) is legal */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( N, 6 * WIDTH ) );
+
+ p = N->p;
+ end = p + N->n;
+
+ ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5
+ ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5
+ ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5
+
+cleanup:
+ return( ret );
+}
+
+#undef WIDTH
+#undef A
+#undef ADD
+#undef NEXT
+#undef LAST
+#endif /* MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED)
+/*
+ * The reader is advised to first understand ecp_mod_p192() since the same
+ * general structure is used here, but with additional complications:
+ * (1) chunks of 32 bits, and (2) subtractions.
+ */
+
+/*
+ * For these primes, we need to handle data in chunks of 32 bits.
+ * This makes it more complicated if we use 64 bits limbs in MPI,
+ * which prevents us from using a uniform access method as for p192.
+ *
+ * So, we define a mini abstraction layer to access 32 bit chunks,
+ * load them in 'cur' for work, and store them back from 'cur' when done.
+ *
+ * While at it, also define the size of N in terms of 32-bit chunks.
+ */
+#define LOAD32 cur = A( i );
+
+#if defined(MBEDCRYPTO_HAVE_INT32) /* 32 bit */
+
+#define MAX32 N->n
+#define A( j ) N->p[j]
+#define STORE32 N->p[i] = cur;
+
+#else /* 64-bit */
+
+#define MAX32 N->n * 2
+#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] )
+#define STORE32 \
+ if( i % 2 ) { \
+ N->p[i/2] &= 0x00000000FFFFFFFF; \
+ N->p[i/2] |= ((mbedcrypto_mpi_uint) cur) << 32; \
+ } else { \
+ N->p[i/2] &= 0xFFFFFFFF00000000; \
+ N->p[i/2] |= (mbedcrypto_mpi_uint) cur; \
+ }
+
+#endif /* sizeof( mbedcrypto_mpi_uint ) */
+
+/*
+ * Helpers for addition and subtraction of chunks, with signed carry.
+ */
+static inline void add32( uint32_t *dst, uint32_t src, signed char *carry )
+{
+ *dst += src;
+ *carry += ( *dst < src );
+}
+
+static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
+{
+ *carry -= ( *dst < src );
+ *dst -= src;
+}
+
+#define ADD( j ) add32( &cur, A( j ), &c );
+#define SUB( j ) sub32( &cur, A( j ), &c );
+
+/*
+ * Helpers for the main 'loop'
+ * (see fix_negative for the motivation of C)
+ */
+#define INIT( b ) \
+ int ret; \
+ signed char c = 0, cc; \
+ uint32_t cur; \
+ size_t i = 0, bits = b; \
+ mbedcrypto_mpi C; \
+ mbedcrypto_mpi_uint Cp[ b / 8 / sizeof( mbedcrypto_mpi_uint) + 1 ]; \
+ \
+ C.s = 1; \
+ C.n = b / 8 / sizeof( mbedcrypto_mpi_uint) + 1; \
+ C.p = Cp; \
+ memset( Cp, 0, C.n * sizeof( mbedcrypto_mpi_uint ) ); \
+ \
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_grow( N, b * 2 / 8 / sizeof( mbedcrypto_mpi_uint ) ) ); \
+ LOAD32;
+
+#define NEXT \
+ STORE32; i++; LOAD32; \
+ cc = c; c = 0; \
+ if( cc < 0 ) \
+ sub32( &cur, -cc, &c ); \
+ else \
+ add32( &cur, cc, &c ); \
+
+#define LAST \
+ STORE32; i++; \
+ cur = c > 0 ? c : 0; STORE32; \
+ cur = 0; while( ++i < MAX32 ) { STORE32; } \
+ if( c < 0 ) fix_negative( N, c, &C, bits );
+
+/*
+ * If the result is negative, we get it in the form
+ * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
+ */
+static inline int fix_negative( mbedcrypto_mpi *N, signed char c, mbedcrypto_mpi *C, size_t bits )
+{
+ int ret;
+
+ /* C = - c * 2^(bits + 32) */
+#if !defined(MBEDCRYPTO_HAVE_INT64)
+ ((void) bits);
+#else
+ if( bits == 224 )
+ C->p[ C->n - 1 ] = ((mbedcrypto_mpi_uint) -c) << 32;
+ else
+#endif
+ C->p[ C->n - 1 ] = (mbedcrypto_mpi_uint) -c;
+
+ /* N = - ( C - N ) */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_abs( N, C, N ) );
+ N->s = -1;
+
+cleanup:
+
+ return( ret );
+}
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
+ */
+static int ecp_mod_p224( mbedcrypto_mpi *N )
+{
+ INIT( 224 );
+
+ SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11
+ SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12
+ SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13
+ SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11
+ SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12
+ SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13
+ SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10
+
+cleanup:
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
+ */
+static int ecp_mod_p256( mbedcrypto_mpi *N )
+{
+ INIT( 256 );
+
+ ADD( 8 ); ADD( 9 );
+ SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0
+
+ ADD( 9 ); ADD( 10 );
+ SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1
+
+ ADD( 10 ); ADD( 11 );
+ SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2
+
+ ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 );
+ SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3
+
+ ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 );
+ SUB( 9 ); SUB( 10 ); NEXT; // A4
+
+ ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 );
+ SUB( 10 ); SUB( 11 ); NEXT; // A5
+
+ ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 );
+ SUB( 8 ); SUB( 9 ); NEXT; // A6
+
+ ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 );
+ SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7
+
+cleanup:
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
+ */
+static int ecp_mod_p384( mbedcrypto_mpi *N )
+{
+ INIT( 384 );
+
+ ADD( 12 ); ADD( 21 ); ADD( 20 );
+ SUB( 23 ); NEXT; // A0
+
+ ADD( 13 ); ADD( 22 ); ADD( 23 );
+ SUB( 12 ); SUB( 20 ); NEXT; // A2
+
+ ADD( 14 ); ADD( 23 );
+ SUB( 13 ); SUB( 21 ); NEXT; // A2
+
+ ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 );
+ SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3
+
+ ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 );
+ SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4
+
+ ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 );
+ SUB( 16 ); NEXT; // A5
+
+ ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 );
+ SUB( 17 ); NEXT; // A6
+
+ ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 );
+ SUB( 18 ); NEXT; // A7
+
+ ADD( 20 ); ADD( 17 ); ADD( 16 );
+ SUB( 19 ); NEXT; // A8
+
+ ADD( 21 ); ADD( 18 ); ADD( 17 );
+ SUB( 20 ); NEXT; // A9
+
+ ADD( 22 ); ADD( 19 ); ADD( 18 );
+ SUB( 21 ); NEXT; // A10
+
+ ADD( 23 ); ADD( 20 ); ADD( 19 );
+ SUB( 22 ); LAST; // A11
+
+cleanup:
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED */
+
+#undef A
+#undef LOAD32
+#undef STORE32
+#undef MAX32
+#undef INIT
+#undef NEXT
+#undef LAST
+
+#endif /* MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED ||
+ MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED ||
+ MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED)
+/*
+ * Here we have an actual Mersenne prime, so things are more straightforward.
+ * However, chunks are aligned on a 'weird' boundary (521 bits).
+ */
+
+/* Size of p521 in terms of mbedcrypto_mpi_uint */
+#define P521_WIDTH ( 521 / 8 / sizeof( mbedcrypto_mpi_uint ) + 1 )
+
+/* Bits to keep in the most significant mbedcrypto_mpi_uint */
+#define P521_MASK 0x01FF
+
+/*
+ * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
+ * Write N as A1 + 2^521 A0, return A0 + A1
+ */
+static int ecp_mod_p521( mbedcrypto_mpi *N )
+{
+ int ret;
+ size_t i;
+ mbedcrypto_mpi M;
+ mbedcrypto_mpi_uint Mp[P521_WIDTH + 1];
+ /* Worst case for the size of M is when mbedcrypto_mpi_uint is 16 bits:
+ * we need to hold bits 513 to 1056, which is 34 limbs, that is
+ * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */
+
+ if( N->n < P521_WIDTH )
+ return( 0 );
+
+ /* M = A1 */
+ M.s = 1;
+ M.n = N->n - ( P521_WIDTH - 1 );
+ if( M.n > P521_WIDTH + 1 )
+ M.n = P521_WIDTH + 1;
+ M.p = Mp;
+ memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedcrypto_mpi_uint ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedcrypto_mpi_uint ) ) ) );
+
+ /* N = A0 */
+ N->p[P521_WIDTH - 1] &= P521_MASK;
+ for( i = P521_WIDTH; i < N->n; i++ )
+ N->p[i] = 0;
+
+ /* N = A0 + A1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_abs( N, N, &M ) );
+
+cleanup:
+ return( ret );
+}
+
+#undef P521_WIDTH
+#undef P521_MASK
+#endif /* MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED */
+
+#endif /* MBEDCRYPTO_ECP_NIST_OPTIM */
+
+#if defined(MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED)
+
+/* Size of p255 in terms of mbedcrypto_mpi_uint */
+#define P255_WIDTH ( 255 / 8 / sizeof( mbedcrypto_mpi_uint ) + 1 )
+
+/*
+ * Fast quasi-reduction modulo p255 = 2^255 - 19
+ * Write N as A0 + 2^255 A1, return A0 + 19 * A1
+ */
+static int ecp_mod_p255( mbedcrypto_mpi *N )
+{
+ int ret;
+ size_t i;
+ mbedcrypto_mpi M;
+ mbedcrypto_mpi_uint Mp[P255_WIDTH + 2];
+
+ if( N->n < P255_WIDTH )
+ return( 0 );
+
+ /* M = A1 */
+ M.s = 1;
+ M.n = N->n - ( P255_WIDTH - 1 );
+ if( M.n > P255_WIDTH + 1 )
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+ M.p = Mp;
+ memset( Mp, 0, sizeof Mp );
+ memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedcrypto_mpi_uint ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedcrypto_mpi_uint ) ) ) );
+ M.n++; /* Make room for multiplication by 19 */
+
+ /* N = A0 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_set_bit( N, 255, 0 ) );
+ for( i = P255_WIDTH; i < N->n; i++ )
+ N->p[i] = 0;
+
+ /* N = A0 + 19 * A1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_int( &M, &M, 19 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_abs( N, N, &M ) );
+
+cleanup:
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECP_DP_CURVE25519_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_CURVE448_ENABLED)
+
+/* Size of p448 in terms of mbedcrypto_mpi_uint */
+#define P448_WIDTH ( 448 / 8 / sizeof( mbedcrypto_mpi_uint ) )
+
+/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */
+#define DIV_ROUND_UP( X, Y ) ( ( ( X ) + ( Y ) - 1 ) / ( Y ) )
+#define P224_WIDTH_MIN ( 28 / sizeof( mbedcrypto_mpi_uint ) )
+#define P224_WIDTH_MAX DIV_ROUND_UP( 28, sizeof( mbedcrypto_mpi_uint ) )
+#define P224_UNUSED_BITS ( ( P224_WIDTH_MAX * sizeof( mbedcrypto_mpi_uint ) * 8 ) - 224 )
+
+/*
+ * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1
+ * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return
+ * A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference
+ * implementation of Curve448, which uses its own special 56-bit limbs rather
+ * than a generic bignum library. We could squeeze some extra speed out on
+ * 32-bit machines by splitting N up into 32-bit limbs and doing the
+ * arithmetic using the limbs directly as we do for the NIST primes above,
+ * but for 64-bit targets it should use half the number of operations if we do
+ * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds.
+ */
+static int ecp_mod_p448( mbedcrypto_mpi *N )
+{
+ int ret;
+ size_t i;
+ mbedcrypto_mpi M, Q;
+ mbedcrypto_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH];
+
+ if( N->n <= P448_WIDTH )
+ return( 0 );
+
+ /* M = A1 */
+ M.s = 1;
+ M.n = N->n - ( P448_WIDTH );
+ if( M.n > P448_WIDTH )
+ /* Shouldn't be called with N larger than 2^896! */
+ return( MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA );
+ M.p = Mp;
+ memset( Mp, 0, sizeof( Mp ) );
+ memcpy( Mp, N->p + P448_WIDTH, M.n * sizeof( mbedcrypto_mpi_uint ) );
+
+ /* N = A0 */
+ for( i = P448_WIDTH; i < N->n; i++ )
+ N->p[i] = 0;
+
+ /* N += A1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( N, N, &M ) );
+
+ /* Q = B1, N += B1 */
+ Q = M;
+ Q.p = Qp;
+ memcpy( Qp, Mp, sizeof( Qp ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &Q, 224 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( N, N, &Q ) );
+
+ /* M = (B0 + B1) * 2^224, N += M */
+ if( sizeof( mbedcrypto_mpi_uint ) > 4 )
+ Mp[P224_WIDTH_MIN] &= ( (mbedcrypto_mpi_uint)-1 ) >> ( P224_UNUSED_BITS );
+ for( i = P224_WIDTH_MAX; i < M.n; ++i )
+ Mp[i] = 0;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &M, &M, &Q ) );
+ M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_l( &M, 224 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( N, N, &M ) );
+
+cleanup:
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECP_DP_CURVE448_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED) || \
+ defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo P = 2^s - R,
+ * with R about 33 bits, used by the Koblitz curves.
+ *
+ * Write N as A0 + 2^224 A1, return A0 + R * A1.
+ * Actually do two passes, since R is big.
+ */
+#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedcrypto_mpi_uint ) ) // Max limbs in P
+#define P_KOBLITZ_R ( 8 / sizeof( mbedcrypto_mpi_uint ) ) // Limbs in R
+static inline int ecp_mod_koblitz( mbedcrypto_mpi *N, mbedcrypto_mpi_uint *Rp, size_t p_limbs,
+ size_t adjust, size_t shift, mbedcrypto_mpi_uint mask )
+{
+ int ret;
+ size_t i;
+ mbedcrypto_mpi M, R;
+ mbedcrypto_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1];
+
+ if( N->n < p_limbs )
+ return( 0 );
+
+ /* Init R */
+ R.s = 1;
+ R.p = Rp;
+ R.n = P_KOBLITZ_R;
+
+ /* Common setup for M */
+ M.s = 1;
+ M.p = Mp;
+
+ /* M = A1 */
+ M.n = N->n - ( p_limbs - adjust );
+ if( M.n > p_limbs + adjust )
+ M.n = p_limbs + adjust;
+ memset( Mp, 0, sizeof Mp );
+ memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedcrypto_mpi_uint ) );
+ if( shift != 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &M, shift ) );
+ M.n += R.n; /* Make room for multiplication by R */
+
+ /* N = A0 */
+ if( mask != 0 )
+ N->p[p_limbs - 1] &= mask;
+ for( i = p_limbs; i < N->n; i++ )
+ N->p[i] = 0;
+
+ /* N = A0 + R * A1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &M, &M, &R ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_abs( N, N, &M ) );
+
+ /* Second pass */
+
+ /* M = A1 */
+ M.n = N->n - ( p_limbs - adjust );
+ if( M.n > p_limbs + adjust )
+ M.n = p_limbs + adjust;
+ memset( Mp, 0, sizeof Mp );
+ memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedcrypto_mpi_uint ) );
+ if( shift != 0 )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &M, shift ) );
+ M.n += R.n; /* Make room for multiplication by R */
+
+ /* N = A0 */
+ if( mask != 0 )
+ N->p[p_limbs - 1] &= mask;
+ for( i = p_limbs; i < N->n; i++ )
+ N->p[i] = 0;
+
+ /* N = A0 + R * A1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &M, &M, &R ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_abs( N, N, &M ) );
+
+cleanup:
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED) ||
+ MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED) ||
+ MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED) */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p192k1 = 2^192 - R,
+ * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119
+ */
+static int ecp_mod_p192k1( mbedcrypto_mpi *N )
+{
+ static mbedcrypto_mpi_uint Rp[] = {
+ BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+
+ return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedcrypto_mpi_uint ), 0, 0, 0 ) );
+}
+#endif /* MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p224k1 = 2^224 - R,
+ * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93
+ */
+static int ecp_mod_p224k1( mbedcrypto_mpi *N )
+{
+ static mbedcrypto_mpi_uint Rp[] = {
+ BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+
+#if defined(MBEDCRYPTO_HAVE_INT64)
+ return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) );
+#else
+ return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedcrypto_mpi_uint ), 0, 0, 0 ) );
+#endif
+}
+
+#endif /* MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p256k1 = 2^256 - R,
+ * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1
+ */
+static int ecp_mod_p256k1( mbedcrypto_mpi *N )
+{
+ static mbedcrypto_mpi_uint Rp[] = {
+ BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+ return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedcrypto_mpi_uint ), 0, 0, 0 ) );
+}
+#endif /* MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED */
+
+#endif /* !MBEDCRYPTO_ECP_ALT */
+
+#endif /* MBEDCRYPTO_ECP_C */
diff --git a/library/entropy.c b/library/entropy.c
new file mode 100644
index 0000000..239d999
--- /dev/null
+++ b/library/entropy.c
@@ -0,0 +1,721 @@
+/*
+ * Entropy accumulator implementation
+ *
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_ENTROPY_C)
+
+#if defined(MBEDCRYPTO_TEST_NULL_ENTROPY)
+#warning "**** WARNING! MBEDCRYPTO_TEST_NULL_ENTROPY defined! "
+#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES "
+#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE "
+#endif
+
+#include "mbedcrypto/entropy.h"
+#include "mbedcrypto/entropy_poll.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+#include "mbedcrypto/platform.h"
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if defined(MBEDCRYPTO_HAVEGE_C)
+#include "mbedcrypto/havege.h"
+#endif
+
+#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
+
+void mbedcrypto_entropy_init( mbedcrypto_entropy_context *ctx )
+{
+ ctx->source_count = 0;
+ memset( ctx->source, 0, sizeof( ctx->source ) );
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_mutex_init( &ctx->mutex );
+#endif
+
+ ctx->accumulator_started = 0;
+#if defined(MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR)
+ mbedcrypto_sha512_init( &ctx->accumulator );
+#else
+ mbedcrypto_sha256_init( &ctx->accumulator );
+#endif
+#if defined(MBEDCRYPTO_HAVEGE_C)
+ mbedcrypto_havege_init( &ctx->havege_data );
+#endif
+
+ /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
+ * when adding more strong entropy sources here. */
+
+#if defined(MBEDCRYPTO_TEST_NULL_ENTROPY)
+ mbedcrypto_entropy_add_source( ctx, mbedcrypto_null_entropy_poll, NULL,
+ 1, MBEDCRYPTO_ENTROPY_SOURCE_STRONG );
+#endif
+
+#if !defined(MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES)
+#if !defined(MBEDCRYPTO_NO_PLATFORM_ENTROPY)
+ mbedcrypto_entropy_add_source( ctx, mbedcrypto_platform_entropy_poll, NULL,
+ MBEDCRYPTO_ENTROPY_MIN_PLATFORM,
+ MBEDCRYPTO_ENTROPY_SOURCE_STRONG );
+#endif
+#if defined(MBEDCRYPTO_TIMING_C)
+ mbedcrypto_entropy_add_source( ctx, mbedcrypto_hardclock_poll, NULL,
+ MBEDCRYPTO_ENTROPY_MIN_HARDCLOCK,
+ MBEDCRYPTO_ENTROPY_SOURCE_WEAK );
+#endif
+#if defined(MBEDCRYPTO_HAVEGE_C)
+ mbedcrypto_entropy_add_source( ctx, mbedcrypto_havege_poll, &ctx->havege_data,
+ MBEDCRYPTO_ENTROPY_MIN_HAVEGE,
+ MBEDCRYPTO_ENTROPY_SOURCE_STRONG );
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_HARDWARE_ALT)
+ mbedcrypto_entropy_add_source( ctx, mbedcrypto_hardware_poll, NULL,
+ MBEDCRYPTO_ENTROPY_MIN_HARDWARE,
+ MBEDCRYPTO_ENTROPY_SOURCE_STRONG );
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+ mbedcrypto_entropy_add_source( ctx, mbedcrypto_nv_seed_poll, NULL,
+ MBEDCRYPTO_ENTROPY_BLOCK_SIZE,
+ MBEDCRYPTO_ENTROPY_SOURCE_STRONG );
+ ctx->initial_entropy_run = 0;
+#endif
+#endif /* MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES */
+}
+
+void mbedcrypto_entropy_free( mbedcrypto_entropy_context *ctx )
+{
+#if defined(MBEDCRYPTO_HAVEGE_C)
+ mbedcrypto_havege_free( &ctx->havege_data );
+#endif
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_mutex_free( &ctx->mutex );
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR)
+ mbedcrypto_sha512_free( &ctx->accumulator );
+#else
+ mbedcrypto_sha256_free( &ctx->accumulator );
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+ ctx->initial_entropy_run = 0;
+#endif
+ ctx->source_count = 0;
+ mbedcrypto_platform_zeroize( ctx->source, sizeof( ctx->source ) );
+ ctx->accumulator_started = 0;
+}
+
+int mbedcrypto_entropy_add_source( mbedcrypto_entropy_context *ctx,
+ mbedcrypto_entropy_f_source_ptr f_source, void *p_source,
+ size_t threshold, int strong )
+{
+ int idx, ret = 0;
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( ( ret = mbedcrypto_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ idx = ctx->source_count;
+ if( idx >= MBEDCRYPTO_ENTROPY_MAX_SOURCES )
+ {
+ ret = MBEDCRYPTO_ERR_ENTROPY_MAX_SOURCES;
+ goto exit;
+ }
+
+ ctx->source[idx].f_source = f_source;
+ ctx->source[idx].p_source = p_source;
+ ctx->source[idx].threshold = threshold;
+ ctx->source[idx].strong = strong;
+
+ ctx->source_count++;
+
+exit:
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( mbedcrypto_mutex_unlock( &ctx->mutex ) != 0 )
+ return( MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+ return( ret );
+}
+
+/*
+ * Entropy accumulator update
+ */
+static int entropy_update( mbedcrypto_entropy_context *ctx, unsigned char source_id,
+ const unsigned char *data, size_t len )
+{
+ unsigned char header[2];
+ unsigned char tmp[MBEDCRYPTO_ENTROPY_BLOCK_SIZE];
+ size_t use_len = len;
+ const unsigned char *p = data;
+ int ret = 0;
+
+ if( use_len > MBEDCRYPTO_ENTROPY_BLOCK_SIZE )
+ {
+#if defined(MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR)
+ if( ( ret = mbedcrypto_sha512_ret( data, len, tmp, 0 ) ) != 0 )
+ goto cleanup;
+#else
+ if( ( ret = mbedcrypto_sha256_ret( data, len, tmp, 0 ) ) != 0 )
+ goto cleanup;
+#endif
+ p = tmp;
+ use_len = MBEDCRYPTO_ENTROPY_BLOCK_SIZE;
+ }
+
+ header[0] = source_id;
+ header[1] = use_len & 0xFF;
+
+ /*
+ * Start the accumulator if this has not already happened. Note that
+ * it is sufficient to start the accumulator here only because all calls to
+ * gather entropy eventually execute this code.
+ */
+#if defined(MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR)
+ if( ctx->accumulator_started == 0 &&
+ ( ret = mbedcrypto_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
+ goto cleanup;
+ else
+ ctx->accumulator_started = 1;
+ if( ( ret = mbedcrypto_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
+ goto cleanup;
+ ret = mbedcrypto_sha512_update_ret( &ctx->accumulator, p, use_len );
+#else
+ if( ctx->accumulator_started == 0 &&
+ ( ret = mbedcrypto_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
+ goto cleanup;
+ else
+ ctx->accumulator_started = 1;
+ if( ( ret = mbedcrypto_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
+ goto cleanup;
+ ret = mbedcrypto_sha256_update_ret( &ctx->accumulator, p, use_len );
+#endif
+
+cleanup:
+ mbedcrypto_platform_zeroize( tmp, sizeof( tmp ) );
+
+ return( ret );
+}
+
+int mbedcrypto_entropy_update_manual( mbedcrypto_entropy_context *ctx,
+ const unsigned char *data, size_t len )
+{
+ int ret;
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( ( ret = mbedcrypto_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ ret = entropy_update( ctx, MBEDCRYPTO_ENTROPY_SOURCE_MANUAL, data, len );
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( mbedcrypto_mutex_unlock( &ctx->mutex ) != 0 )
+ return( MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+ return( ret );
+}
+
+/*
+ * Run through the different sources to add entropy to our accumulator
+ */
+static int entropy_gather_internal( mbedcrypto_entropy_context *ctx )
+{
+ int ret, i, have_one_strong = 0;
+ unsigned char buf[MBEDCRYPTO_ENTROPY_MAX_GATHER];
+ size_t olen;
+
+ if( ctx->source_count == 0 )
+ return( MBEDCRYPTO_ERR_ENTROPY_NO_SOURCES_DEFINED );
+
+ /*
+ * Run through our entropy sources
+ */
+ for( i = 0; i < ctx->source_count; i++ )
+ {
+ if( ctx->source[i].strong == MBEDCRYPTO_ENTROPY_SOURCE_STRONG )
+ have_one_strong = 1;
+
+ olen = 0;
+ if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
+ buf, MBEDCRYPTO_ENTROPY_MAX_GATHER, &olen ) ) != 0 )
+ {
+ goto cleanup;
+ }
+
+ /*
+ * Add if we actually gathered something
+ */
+ if( olen > 0 )
+ {
+ if( ( ret = entropy_update( ctx, (unsigned char) i,
+ buf, olen ) ) != 0 )
+ return( ret );
+ ctx->source[i].size += olen;
+ }
+ }
+
+ if( have_one_strong == 0 )
+ ret = MBEDCRYPTO_ERR_ENTROPY_NO_STRONG_SOURCE;
+
+cleanup:
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+
+ return( ret );
+}
+
+/*
+ * Thread-safe wrapper for entropy_gather_internal()
+ */
+int mbedcrypto_entropy_gather( mbedcrypto_entropy_context *ctx )
+{
+ int ret;
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( ( ret = mbedcrypto_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ ret = entropy_gather_internal( ctx );
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( mbedcrypto_mutex_unlock( &ctx->mutex ) != 0 )
+ return( MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+ return( ret );
+}
+
+int mbedcrypto_entropy_func( void *data, unsigned char *output, size_t len )
+{
+ int ret, count = 0, i, done;
+ mbedcrypto_entropy_context *ctx = (mbedcrypto_entropy_context *) data;
+ unsigned char buf[MBEDCRYPTO_ENTROPY_BLOCK_SIZE];
+
+ if( len > MBEDCRYPTO_ENTROPY_BLOCK_SIZE )
+ return( MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED );
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+ /* Update the NV entropy seed before generating any entropy for outside
+ * use.
+ */
+ if( ctx->initial_entropy_run == 0 )
+ {
+ ctx->initial_entropy_run = 1;
+ if( ( ret = mbedcrypto_entropy_update_nv_seed( ctx ) ) != 0 )
+ return( ret );
+ }
+#endif
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( ( ret = mbedcrypto_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ /*
+ * Always gather extra entropy before a call
+ */
+ do
+ {
+ if( count++ > ENTROPY_MAX_LOOP )
+ {
+ ret = MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED;
+ goto exit;
+ }
+
+ if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
+ goto exit;
+
+ done = 1;
+ for( i = 0; i < ctx->source_count; i++ )
+ if( ctx->source[i].size < ctx->source[i].threshold )
+ done = 0;
+ }
+ while( ! done );
+
+ memset( buf, 0, MBEDCRYPTO_ENTROPY_BLOCK_SIZE );
+
+#if defined(MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR)
+ /*
+ * Note that at this stage it is assumed that the accumulator was started
+ * in a previous call to entropy_update(). If this is not guaranteed, the
+ * code below will fail.
+ */
+ if( ( ret = mbedcrypto_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 )
+ goto exit;
+
+ /*
+ * Reset accumulator and counters and recycle existing entropy
+ */
+ mbedcrypto_sha512_free( &ctx->accumulator );
+ mbedcrypto_sha512_init( &ctx->accumulator );
+ if( ( ret = mbedcrypto_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_sha512_update_ret( &ctx->accumulator, buf,
+ MBEDCRYPTO_ENTROPY_BLOCK_SIZE ) ) != 0 )
+ goto exit;
+
+ /*
+ * Perform second SHA-512 on entropy
+ */
+ if( ( ret = mbedcrypto_sha512_ret( buf, MBEDCRYPTO_ENTROPY_BLOCK_SIZE,
+ buf, 0 ) ) != 0 )
+ goto exit;
+#else /* MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR */
+ if( ( ret = mbedcrypto_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 )
+ goto exit;
+
+ /*
+ * Reset accumulator and counters and recycle existing entropy
+ */
+ mbedcrypto_sha256_free( &ctx->accumulator );
+ mbedcrypto_sha256_init( &ctx->accumulator );
+ if( ( ret = mbedcrypto_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_sha256_update_ret( &ctx->accumulator, buf,
+ MBEDCRYPTO_ENTROPY_BLOCK_SIZE ) ) != 0 )
+ goto exit;
+
+ /*
+ * Perform second SHA-256 on entropy
+ */
+ if( ( ret = mbedcrypto_sha256_ret( buf, MBEDCRYPTO_ENTROPY_BLOCK_SIZE,
+ buf, 0 ) ) != 0 )
+ goto exit;
+#endif /* MBEDCRYPTO_ENTROPY_SHA512_ACCUMULATOR */
+
+ for( i = 0; i < ctx->source_count; i++ )
+ ctx->source[i].size = 0;
+
+ memcpy( output, buf, len );
+
+ ret = 0;
+
+exit:
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( mbedcrypto_mutex_unlock( &ctx->mutex ) != 0 )
+ return( MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+ return( ret );
+}
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+int mbedcrypto_entropy_update_nv_seed( mbedcrypto_entropy_context *ctx )
+{
+ int ret = MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR;
+ unsigned char buf[MBEDCRYPTO_ENTROPY_BLOCK_SIZE];
+
+ /* Read new seed and write it to NV */
+ if( ( ret = mbedcrypto_entropy_func( ctx, buf, MBEDCRYPTO_ENTROPY_BLOCK_SIZE ) ) != 0 )
+ return( ret );
+
+ if( mbedcrypto_nv_seed_write( buf, MBEDCRYPTO_ENTROPY_BLOCK_SIZE ) < 0 )
+ return( MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR );
+
+ /* Manually update the remaining stream with a separator value to diverge */
+ memset( buf, 0, MBEDCRYPTO_ENTROPY_BLOCK_SIZE );
+ ret = mbedcrypto_entropy_update_manual( ctx, buf, MBEDCRYPTO_ENTROPY_BLOCK_SIZE );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ENTROPY_NV_SEED */
+
+#if defined(MBEDCRYPTO_FS_IO)
+int mbedcrypto_entropy_write_seed_file( mbedcrypto_entropy_context *ctx, const char *path )
+{
+ int ret = MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR;
+ FILE *f;
+ unsigned char buf[MBEDCRYPTO_ENTROPY_BLOCK_SIZE];
+
+ if( ( f = fopen( path, "wb" ) ) == NULL )
+ return( MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR );
+
+ if( ( ret = mbedcrypto_entropy_func( ctx, buf, MBEDCRYPTO_ENTROPY_BLOCK_SIZE ) ) != 0 )
+ goto exit;
+
+ if( fwrite( buf, 1, MBEDCRYPTO_ENTROPY_BLOCK_SIZE, f ) != MBEDCRYPTO_ENTROPY_BLOCK_SIZE )
+ {
+ ret = MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR;
+ goto exit;
+ }
+
+ ret = 0;
+
+exit:
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+
+ fclose( f );
+ return( ret );
+}
+
+int mbedcrypto_entropy_update_seed_file( mbedcrypto_entropy_context *ctx, const char *path )
+{
+ int ret = 0;
+ FILE *f;
+ size_t n;
+ unsigned char buf[ MBEDCRYPTO_ENTROPY_MAX_SEED_SIZE ];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR );
+
+ fseek( f, 0, SEEK_END );
+ n = (size_t) ftell( f );
+ fseek( f, 0, SEEK_SET );
+
+ if( n > MBEDCRYPTO_ENTROPY_MAX_SEED_SIZE )
+ n = MBEDCRYPTO_ENTROPY_MAX_SEED_SIZE;
+
+ if( fread( buf, 1, n, f ) != n )
+ ret = MBEDCRYPTO_ERR_ENTROPY_FILE_IO_ERROR;
+ else
+ ret = mbedcrypto_entropy_update_manual( ctx, buf, n );
+
+ fclose( f );
+
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+
+ if( ret != 0 )
+ return( ret );
+
+ return( mbedcrypto_entropy_write_seed_file( ctx, path ) );
+}
+#endif /* MBEDCRYPTO_FS_IO */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if !defined(MBEDCRYPTO_TEST_NULL_ENTROPY)
+/*
+ * Dummy source function
+ */
+static int entropy_dummy_source( void *data, unsigned char *output,
+ size_t len, size_t *olen )
+{
+ ((void) data);
+
+ memset( output, 0x2a, len );
+ *olen = len;
+
+ return( 0 );
+}
+#endif /* !MBEDCRYPTO_TEST_NULL_ENTROPY */
+
+#if defined(MBEDCRYPTO_ENTROPY_HARDWARE_ALT)
+
+static int mbedcrypto_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len )
+{
+ int ret = 0;
+ size_t entropy_len = 0;
+ size_t olen = 0;
+ size_t attempts = buf_len;
+
+ while( attempts > 0 && entropy_len < buf_len )
+ {
+ if( ( ret = mbedcrypto_hardware_poll( NULL, buf + entropy_len,
+ buf_len - entropy_len, &olen ) ) != 0 )
+ return( ret );
+
+ entropy_len += olen;
+ attempts--;
+ }
+
+ if( entropy_len < buf_len )
+ {
+ ret = 1;
+ }
+
+ return( ret );
+}
+
+
+static int mbedcrypto_entropy_source_self_test_check_bits( const unsigned char *buf,
+ size_t buf_len )
+{
+ unsigned char set= 0xFF;
+ unsigned char unset = 0x00;
+ size_t i;
+
+ for( i = 0; i < buf_len; i++ )
+ {
+ set &= buf[i];
+ unset |= buf[i];
+ }
+
+ return( set == 0xFF || unset == 0x00 );
+}
+
+/*
+ * A test to ensure hat the entropy sources are functioning correctly
+ * and there is no obvious failure. The test performs the following checks:
+ * - The entropy source is not providing only 0s (all bits unset) or 1s (all
+ * bits set).
+ * - The entropy source is not providing values in a pattern. Because the
+ * hardware could be providing data in an arbitrary length, this check polls
+ * the hardware entropy source twice and compares the result to ensure they
+ * are not equal.
+ * - The error code returned by the entropy source is not an error.
+ */
+int mbedcrypto_entropy_source_self_test( int verbose )
+{
+ int ret = 0;
+ unsigned char buf0[2 * sizeof( unsigned long long int )];
+ unsigned char buf1[2 * sizeof( unsigned long long int )];
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " ENTROPY_BIAS test: " );
+
+ memset( buf0, 0x00, sizeof( buf0 ) );
+ memset( buf1, 0x00, sizeof( buf1 ) );
+
+ if( ( ret = mbedcrypto_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 )
+ goto cleanup;
+ if( ( ret = mbedcrypto_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 )
+ goto cleanup;
+
+ /* Make sure that the returned values are not all 0 or 1 */
+ if( ( ret = mbedcrypto_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 )
+ goto cleanup;
+ if( ( ret = mbedcrypto_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 )
+ goto cleanup;
+
+ /* Make sure that the entropy source is not returning values in a
+ * pattern */
+ ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0;
+
+cleanup:
+ if( verbose != 0 )
+ {
+ if( ret != 0 )
+ mbedcrypto_printf( "failed\n" );
+ else
+ mbedcrypto_printf( "passed\n" );
+
+ mbedcrypto_printf( "\n" );
+ }
+
+ return( ret != 0 );
+}
+
+#endif /* MBEDCRYPTO_ENTROPY_HARDWARE_ALT */
+
+/*
+ * The actual entropy quality is hard to test, but we can at least
+ * test that the functions don't cause errors and write the correct
+ * amount of data to buffers.
+ */
+int mbedcrypto_entropy_self_test( int verbose )
+{
+ int ret = 1;
+#if !defined(MBEDCRYPTO_TEST_NULL_ENTROPY)
+ mbedcrypto_entropy_context ctx;
+ unsigned char buf[MBEDCRYPTO_ENTROPY_BLOCK_SIZE] = { 0 };
+ unsigned char acc[MBEDCRYPTO_ENTROPY_BLOCK_SIZE] = { 0 };
+ size_t i, j;
+#endif /* !MBEDCRYPTO_TEST_NULL_ENTROPY */
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " ENTROPY test: " );
+
+#if !defined(MBEDCRYPTO_TEST_NULL_ENTROPY)
+ mbedcrypto_entropy_init( &ctx );
+
+ /* First do a gather to make sure we have default sources */
+ if( ( ret = mbedcrypto_entropy_gather( &ctx ) ) != 0 )
+ goto cleanup;
+
+ ret = mbedcrypto_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16,
+ MBEDCRYPTO_ENTROPY_SOURCE_WEAK );
+ if( ret != 0 )
+ goto cleanup;
+
+ if( ( ret = mbedcrypto_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
+ goto cleanup;
+
+ /*
+ * To test that mbedcrypto_entropy_func writes correct number of bytes:
+ * - use the whole buffer and rely on ASan to detect overruns
+ * - collect entropy 8 times and OR the result in an accumulator:
+ * any byte should then be 0 with probably 2^(-64), so requiring
+ * each of the 32 or 64 bytes to be non-zero has a false failure rate
+ * of at most 2^(-58) which is acceptable.
+ */
+ for( i = 0; i < 8; i++ )
+ {
+ if( ( ret = mbedcrypto_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
+ goto cleanup;
+
+ for( j = 0; j < sizeof( buf ); j++ )
+ acc[j] |= buf[j];
+ }
+
+ for( j = 0; j < sizeof( buf ); j++ )
+ {
+ if( acc[j] == 0 )
+ {
+ ret = 1;
+ goto cleanup;
+ }
+ }
+
+#if defined(MBEDCRYPTO_ENTROPY_HARDWARE_ALT)
+ if( ( ret = mbedcrypto_entropy_source_self_test( 0 ) ) != 0 )
+ goto cleanup;
+#endif
+
+cleanup:
+ mbedcrypto_entropy_free( &ctx );
+#endif /* !MBEDCRYPTO_TEST_NULL_ENTROPY */
+
+ if( verbose != 0 )
+ {
+ if( ret != 0 )
+ mbedcrypto_printf( "failed\n" );
+ else
+ mbedcrypto_printf( "passed\n" );
+
+ mbedcrypto_printf( "\n" );
+ }
+
+ return( ret != 0 );
+}
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_ENTROPY_C */
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
new file mode 100644
index 0000000..4c9f61f
--- /dev/null
+++ b/library/entropy_poll.c
@@ -0,0 +1,269 @@
+/*
+ * Platform-specific and custom entropy polling functions
+ *
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_ENTROPY_C)
+
+#include "mbedcrypto/entropy.h"
+#include "mbedcrypto/entropy_poll.h"
+
+#if defined(MBEDCRYPTO_TIMING_C)
+#include "mbedcrypto/timing.h"
+#endif
+#if defined(MBEDCRYPTO_HAVEGE_C)
+#include "mbedcrypto/havege.h"
+#endif
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+#include "mbedcrypto/platform.h"
+#endif
+
+#if !defined(MBEDCRYPTO_NO_PLATFORM_ENTROPY)
+
+#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
+ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
+#error "Platform entropy sources only work on Unix and Windows, see MBEDCRYPTO_NO_PLATFORM_ENTROPY in config.h"
+#endif
+
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+
+#if !defined(_WIN32_WINNT)
+#define _WIN32_WINNT 0x0400
+#endif
+#include <windows.h>
+#include <wincrypt.h>
+
+int mbedcrypto_platform_entropy_poll( void *data, unsigned char *output, size_t len,
+ size_t *olen )
+{
+ HCRYPTPROV provider;
+ ((void) data);
+ *olen = 0;
+
+ if( CryptAcquireContext( &provider, NULL, NULL,
+ PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
+ {
+ return( MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED );
+ }
+
+ if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
+ {
+ CryptReleaseContext( provider, 0 );
+ return( MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED );
+ }
+
+ CryptReleaseContext( provider, 0 );
+ *olen = len;
+
+ return( 0 );
+}
+#else /* _WIN32 && !EFIX64 && !EFI32 */
+
+/*
+ * Test for Linux getrandom() support.
+ * Since there is no wrapper in the libc yet, use the generic syscall wrapper
+ * available in GNU libc and compatible libc's (eg uClibc).
+ */
+#if defined(__linux__) && defined(__GLIBC__)
+#include <unistd.h>
+#include <sys/syscall.h>
+#if defined(SYS_getrandom)
+#define HAVE_GETRANDOM
+
+static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
+{
+ /* MemSan cannot understand that the syscall writes to the buffer */
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+ memset( buf, 0, buflen );
+#endif
+#endif
+
+ return( syscall( SYS_getrandom, buf, buflen, flags ) );
+}
+
+#include <sys/utsname.h>
+/* Check if version is at least 3.17.0 */
+static int check_version_3_17_plus( void )
+{
+ int minor;
+ struct utsname un;
+ const char *ver;
+
+ /* Get version information */
+ uname(&un);
+ ver = un.release;
+
+ /* Check major version; assume a single digit */
+ if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' )
+ return( -1 );
+
+ if( ver[0] - '0' > 3 )
+ return( 0 );
+
+ /* Ok, so now we know major == 3, check minor.
+ * Assume 1 or 2 digits. */
+ if( ver[2] < '0' || ver[2] > '9' )
+ return( -1 );
+
+ minor = ver[2] - '0';
+
+ if( ver[3] >= '0' && ver[3] <= '9' )
+ minor = 10 * minor + ver[3] - '0';
+ else if( ver [3] != '.' )
+ return( -1 );
+
+ if( minor < 17 )
+ return( -1 );
+
+ return( 0 );
+}
+static int has_getrandom = -1;
+#endif /* SYS_getrandom */
+#endif /* __linux__ */
+
+#include <stdio.h>
+
+int mbedcrypto_platform_entropy_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ FILE *file;
+ size_t read_len;
+ ((void) data);
+
+#if defined(HAVE_GETRANDOM)
+ if( has_getrandom == -1 )
+ has_getrandom = ( check_version_3_17_plus() == 0 );
+
+ if( has_getrandom )
+ {
+ int ret;
+
+ if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
+ return( MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED );
+
+ *olen = ret;
+ return( 0 );
+ }
+#endif /* HAVE_GETRANDOM */
+
+ *olen = 0;
+
+ file = fopen( "/dev/urandom", "rb" );
+ if( file == NULL )
+ return( MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED );
+
+ read_len = fread( output, 1, len, file );
+ if( read_len != len )
+ {
+ fclose( file );
+ return( MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED );
+ }
+
+ fclose( file );
+ *olen = len;
+
+ return( 0 );
+}
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+#endif /* !MBEDCRYPTO_NO_PLATFORM_ENTROPY */
+
+#if defined(MBEDCRYPTO_TEST_NULL_ENTROPY)
+int mbedcrypto_null_entropy_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ ((void) data);
+ ((void) output);
+ *olen = 0;
+
+ if( len < sizeof(unsigned char) )
+ return( 0 );
+
+ *olen = sizeof(unsigned char);
+
+ return( 0 );
+}
+#endif
+
+#if defined(MBEDCRYPTO_TIMING_C)
+int mbedcrypto_hardclock_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ unsigned long timer = mbedcrypto_timing_hardclock();
+ ((void) data);
+ *olen = 0;
+
+ if( len < sizeof(unsigned long) )
+ return( 0 );
+
+ memcpy( output, &timer, sizeof(unsigned long) );
+ *olen = sizeof(unsigned long);
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_TIMING_C */
+
+#if defined(MBEDCRYPTO_HAVEGE_C)
+int mbedcrypto_havege_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ mbedcrypto_havege_state *hs = (mbedcrypto_havege_state *) data;
+ *olen = 0;
+
+ if( mbedcrypto_havege_random( hs, output, len ) != 0 )
+ return( MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED );
+
+ *olen = len;
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_HAVEGE_C */
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+int mbedcrypto_nv_seed_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ unsigned char buf[MBEDCRYPTO_ENTROPY_BLOCK_SIZE];
+ size_t use_len = MBEDCRYPTO_ENTROPY_BLOCK_SIZE;
+ ((void) data);
+
+ memset( buf, 0, MBEDCRYPTO_ENTROPY_BLOCK_SIZE );
+
+ if( mbedcrypto_nv_seed_read( buf, MBEDCRYPTO_ENTROPY_BLOCK_SIZE ) < 0 )
+ return( MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED );
+
+ if( len < use_len )
+ use_len = len;
+
+ memcpy( output, buf, use_len );
+ *olen = use_len;
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_ENTROPY_NV_SEED */
+
+#endif /* MBEDCRYPTO_ENTROPY_C */
diff --git a/library/gcm.c b/library/gcm.c
new file mode 100644
index 0000000..3481c9f
--- /dev/null
+++ b/library/gcm.c
@@ -0,0 +1,954 @@
+/*
+ * NIST SP800-38D compliant GCM implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
+ *
+ * See also:
+ * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
+ *
+ * We use the algorithm described as Shoup's method with 4-bit tables in
+ * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_GCM_C)
+
+#include "mbedcrypto/gcm.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_AESNI_C)
+#include "mbedcrypto/aesni.h"
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST) && defined(MBEDCRYPTO_AES_C)
+#include "mbedcrypto/aes.h"
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST && MBEDCRYPTO_AES_C */
+
+#if !defined(MBEDCRYPTO_GCM_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+/*
+ * Initialize a context
+ */
+void mbedcrypto_gcm_init( mbedcrypto_gcm_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_gcm_context ) );
+}
+
+/*
+ * Precompute small multiples of H, that is set
+ * HH[i] || HL[i] = H times i,
+ * where i is seen as a field element as in [MGV], ie high-order bits
+ * correspond to low powers of P. The result is stored in the same way, that
+ * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
+ * corresponds to P^127.
+ */
+static int gcm_gen_table( mbedcrypto_gcm_context *ctx )
+{
+ int ret, i, j;
+ uint64_t hi, lo;
+ uint64_t vl, vh;
+ unsigned char h[16];
+ size_t olen = 0;
+
+ memset( h, 0, 16 );
+ if( ( ret = mbedcrypto_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
+ return( ret );
+
+ /* pack h as two 64-bits ints, big-endian */
+ GET_UINT32_BE( hi, h, 0 );
+ GET_UINT32_BE( lo, h, 4 );
+ vh = (uint64_t) hi << 32 | lo;
+
+ GET_UINT32_BE( hi, h, 8 );
+ GET_UINT32_BE( lo, h, 12 );
+ vl = (uint64_t) hi << 32 | lo;
+
+ /* 8 = 1000 corresponds to 1 in GF(2^128) */
+ ctx->HL[8] = vl;
+ ctx->HH[8] = vh;
+
+#if defined(MBEDCRYPTO_AESNI_C) && defined(MBEDCRYPTO_HAVE_X86_64)
+ /* With CLMUL support, we need only h, not the rest of the table */
+ if( mbedcrypto_aesni_has_support( MBEDCRYPTO_AESNI_CLMUL ) )
+ return( 0 );
+#endif
+
+ /* 0 corresponds to 0 in GF(2^128) */
+ ctx->HH[0] = 0;
+ ctx->HL[0] = 0;
+
+ for( i = 4; i > 0; i >>= 1 )
+ {
+ uint32_t T = ( vl & 1 ) * 0xe1000000U;
+ vl = ( vh << 63 ) | ( vl >> 1 );
+ vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
+
+ ctx->HL[i] = vl;
+ ctx->HH[i] = vh;
+ }
+
+ for( i = 2; i <= 8; i *= 2 )
+ {
+ uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
+ vh = *HiH;
+ vl = *HiL;
+ for( j = 1; j < i; j++ )
+ {
+ HiH[j] = vh ^ ctx->HH[j];
+ HiL[j] = vl ^ ctx->HL[j];
+ }
+ }
+
+ return( 0 );
+}
+
+int mbedcrypto_gcm_setkey( mbedcrypto_gcm_context *ctx,
+ mbedcrypto_cipher_id_t cipher,
+ const unsigned char *key,
+ unsigned int keybits )
+{
+ int ret;
+ const mbedcrypto_cipher_info_t *cipher_info;
+
+ cipher_info = mbedcrypto_cipher_info_from_values( cipher, keybits, MBEDCRYPTO_MODE_ECB );
+ if( cipher_info == NULL )
+ return( MBEDCRYPTO_ERR_GCM_BAD_INPUT );
+
+ if( cipher_info->block_size != 16 )
+ return( MBEDCRYPTO_ERR_GCM_BAD_INPUT );
+
+ mbedcrypto_cipher_free( &ctx->cipher_ctx );
+
+ if( ( ret = mbedcrypto_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_cipher_setkey( &ctx->cipher_ctx, key, keybits,
+ MBEDCRYPTO_ENCRYPT ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = gcm_gen_table( ctx ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+}
+
+/*
+ * Shoup's method for multiplication use this table with
+ * last4[x] = x times P^128
+ * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
+ */
+static const uint64_t last4[16] =
+{
+ 0x0000, 0x1c20, 0x3840, 0x2460,
+ 0x7080, 0x6ca0, 0x48c0, 0x54e0,
+ 0xe100, 0xfd20, 0xd940, 0xc560,
+ 0x9180, 0x8da0, 0xa9c0, 0xb5e0
+};
+
+/*
+ * Sets output to x times H using the precomputed tables.
+ * x and output are seen as elements of GF(2^128) as in [MGV].
+ */
+static void gcm_mult( mbedcrypto_gcm_context *ctx, const unsigned char x[16],
+ unsigned char output[16] )
+{
+ int i = 0;
+ unsigned char lo, hi, rem;
+ uint64_t zh, zl;
+
+#if defined(MBEDCRYPTO_AESNI_C) && defined(MBEDCRYPTO_HAVE_X86_64)
+ if( mbedcrypto_aesni_has_support( MBEDCRYPTO_AESNI_CLMUL ) ) {
+ unsigned char h[16];
+
+ PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
+ PUT_UINT32_BE( ctx->HH[8], h, 4 );
+ PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
+ PUT_UINT32_BE( ctx->HL[8], h, 12 );
+
+ mbedcrypto_aesni_gcm_mult( output, x, h );
+ return;
+ }
+#endif /* MBEDCRYPTO_AESNI_C && MBEDCRYPTO_HAVE_X86_64 */
+
+ lo = x[15] & 0xf;
+
+ zh = ctx->HH[lo];
+ zl = ctx->HL[lo];
+
+ for( i = 15; i >= 0; i-- )
+ {
+ lo = x[i] & 0xf;
+ hi = x[i] >> 4;
+
+ if( i != 15 )
+ {
+ rem = (unsigned char) zl & 0xf;
+ zl = ( zh << 60 ) | ( zl >> 4 );
+ zh = ( zh >> 4 );
+ zh ^= (uint64_t) last4[rem] << 48;
+ zh ^= ctx->HH[lo];
+ zl ^= ctx->HL[lo];
+
+ }
+
+ rem = (unsigned char) zl & 0xf;
+ zl = ( zh << 60 ) | ( zl >> 4 );
+ zh = ( zh >> 4 );
+ zh ^= (uint64_t) last4[rem] << 48;
+ zh ^= ctx->HH[hi];
+ zl ^= ctx->HL[hi];
+ }
+
+ PUT_UINT32_BE( zh >> 32, output, 0 );
+ PUT_UINT32_BE( zh, output, 4 );
+ PUT_UINT32_BE( zl >> 32, output, 8 );
+ PUT_UINT32_BE( zl, output, 12 );
+}
+
+int mbedcrypto_gcm_starts( mbedcrypto_gcm_context *ctx,
+ int mode,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len )
+{
+ int ret;
+ unsigned char work_buf[16];
+ size_t i;
+ const unsigned char *p;
+ size_t use_len, olen = 0;
+
+ /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
+ /* IV is not allowed to be zero length */
+ if( iv_len == 0 ||
+ ( (uint64_t) iv_len ) >> 61 != 0 ||
+ ( (uint64_t) add_len ) >> 61 != 0 )
+ {
+ return( MBEDCRYPTO_ERR_GCM_BAD_INPUT );
+ }
+
+ memset( ctx->y, 0x00, sizeof(ctx->y) );
+ memset( ctx->buf, 0x00, sizeof(ctx->buf) );
+
+ ctx->mode = mode;
+ ctx->len = 0;
+ ctx->add_len = 0;
+
+ if( iv_len == 12 )
+ {
+ memcpy( ctx->y, iv, iv_len );
+ ctx->y[15] = 1;
+ }
+ else
+ {
+ memset( work_buf, 0x00, 16 );
+ PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
+
+ p = iv;
+ while( iv_len > 0 )
+ {
+ use_len = ( iv_len < 16 ) ? iv_len : 16;
+
+ for( i = 0; i < use_len; i++ )
+ ctx->y[i] ^= p[i];
+
+ gcm_mult( ctx, ctx->y, ctx->y );
+
+ iv_len -= use_len;
+ p += use_len;
+ }
+
+ for( i = 0; i < 16; i++ )
+ ctx->y[i] ^= work_buf[i];
+
+ gcm_mult( ctx, ctx->y, ctx->y );
+ }
+
+ if( ( ret = mbedcrypto_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
+ &olen ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ ctx->add_len = add_len;
+ p = add;
+ while( add_len > 0 )
+ {
+ use_len = ( add_len < 16 ) ? add_len : 16;
+
+ for( i = 0; i < use_len; i++ )
+ ctx->buf[i] ^= p[i];
+
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+
+ add_len -= use_len;
+ p += use_len;
+ }
+
+ return( 0 );
+}
+
+int mbedcrypto_gcm_update( mbedcrypto_gcm_context *ctx,
+ size_t length,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ unsigned char ectr[16];
+ size_t i;
+ const unsigned char *p;
+ unsigned char *out_p = output;
+ size_t use_len, olen = 0;
+
+ if( output > input && (size_t) ( output - input ) < length )
+ return( MBEDCRYPTO_ERR_GCM_BAD_INPUT );
+
+ /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
+ * Also check for possible overflow */
+ if( ctx->len + length < ctx->len ||
+ (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
+ {
+ return( MBEDCRYPTO_ERR_GCM_BAD_INPUT );
+ }
+
+ ctx->len += length;
+
+ p = input;
+ while( length > 0 )
+ {
+ use_len = ( length < 16 ) ? length : 16;
+
+ for( i = 16; i > 12; i-- )
+ if( ++ctx->y[i - 1] != 0 )
+ break;
+
+ if( ( ret = mbedcrypto_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
+ &olen ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ for( i = 0; i < use_len; i++ )
+ {
+ if( ctx->mode == MBEDCRYPTO_GCM_DECRYPT )
+ ctx->buf[i] ^= p[i];
+ out_p[i] = ectr[i] ^ p[i];
+ if( ctx->mode == MBEDCRYPTO_GCM_ENCRYPT )
+ ctx->buf[i] ^= out_p[i];
+ }
+
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+
+ length -= use_len;
+ p += use_len;
+ out_p += use_len;
+ }
+
+ return( 0 );
+}
+
+int mbedcrypto_gcm_finish( mbedcrypto_gcm_context *ctx,
+ unsigned char *tag,
+ size_t tag_len )
+{
+ unsigned char work_buf[16];
+ size_t i;
+ uint64_t orig_len = ctx->len * 8;
+ uint64_t orig_add_len = ctx->add_len * 8;
+
+ if( tag_len > 16 || tag_len < 4 )
+ return( MBEDCRYPTO_ERR_GCM_BAD_INPUT );
+
+ memcpy( tag, ctx->base_ectr, tag_len );
+
+ if( orig_len || orig_add_len )
+ {
+ memset( work_buf, 0x00, 16 );
+
+ PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
+ PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
+ PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
+ PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
+
+ for( i = 0; i < 16; i++ )
+ ctx->buf[i] ^= work_buf[i];
+
+ gcm_mult( ctx, ctx->buf, ctx->buf );
+
+ for( i = 0; i < tag_len; i++ )
+ tag[i] ^= ctx->buf[i];
+ }
+
+ return( 0 );
+}
+
+int mbedcrypto_gcm_crypt_and_tag( mbedcrypto_gcm_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t tag_len,
+ unsigned char *tag )
+{
+ int ret;
+
+ if( ( ret = mbedcrypto_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_gcm_update( ctx, length, input, output ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_gcm_finish( ctx, tag, tag_len ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+}
+
+int mbedcrypto_gcm_auth_decrypt( mbedcrypto_gcm_context *ctx,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *tag,
+ size_t tag_len,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ unsigned char check_tag[16];
+ size_t i;
+ int diff;
+
+ if( ( ret = mbedcrypto_gcm_crypt_and_tag( ctx, MBEDCRYPTO_GCM_DECRYPT, length,
+ iv, iv_len, add, add_len,
+ input, output, tag_len, check_tag ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* Check tag in "constant-time" */
+ for( diff = 0, i = 0; i < tag_len; i++ )
+ diff |= tag[i] ^ check_tag[i];
+
+ if( diff != 0 )
+ {
+ mbedcrypto_platform_zeroize( output, length );
+ return( MBEDCRYPTO_ERR_GCM_AUTH_FAILED );
+ }
+
+ return( 0 );
+}
+
+void mbedcrypto_gcm_free( mbedcrypto_gcm_context *ctx )
+{
+ mbedcrypto_cipher_free( &ctx->cipher_ctx );
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_gcm_context ) );
+}
+
+#endif /* !MBEDCRYPTO_GCM_ALT */
+
+#if defined(MBEDCRYPTO_SELF_TEST) && defined(MBEDCRYPTO_AES_C)
+/*
+ * AES-GCM test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
+ */
+#define MAX_TESTS 6
+
+static const int key_index[MAX_TESTS] =
+ { 0, 0, 1, 1, 1, 1 };
+
+static const unsigned char key[MAX_TESTS][32] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+};
+
+static const size_t iv_len[MAX_TESTS] =
+ { 12, 12, 12, 12, 8, 60 };
+
+static const int iv_index[MAX_TESTS] =
+ { 0, 0, 1, 1, 1, 2 };
+
+static const unsigned char iv[MAX_TESTS][64] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
+ 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
+ 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
+ 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
+ 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
+ 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
+ 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
+ 0xa6, 0x37, 0xb3, 0x9b },
+};
+
+static const size_t add_len[MAX_TESTS] =
+ { 0, 0, 0, 20, 20, 20 };
+
+static const int add_index[MAX_TESTS] =
+ { 0, 0, 0, 1, 1, 1 };
+
+static const unsigned char additional[MAX_TESTS][64] =
+{
+ { 0x00 },
+ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xab, 0xad, 0xda, 0xd2 },
+};
+
+static const size_t pt_len[MAX_TESTS] =
+ { 0, 16, 64, 60, 60, 60 };
+
+static const int pt_index[MAX_TESTS] =
+ { 0, 0, 1, 1, 1, 1 };
+
+static const unsigned char pt[MAX_TESTS][64] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+};
+
+static const unsigned char ct[MAX_TESTS * 3][64] =
+{
+ { 0x00 },
+ { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
+ 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
+ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
+ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91 },
+ { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
+ 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
+ 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
+ 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
+ 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
+ 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
+ 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
+ 0xc2, 0x3f, 0x45, 0x98 },
+ { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
+ 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
+ 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
+ 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
+ 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
+ 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
+ 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
+ 0x4c, 0x34, 0xae, 0xe5 },
+ { 0x00 },
+ { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
+ 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
+ { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
+ { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
+ 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
+ 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
+ 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
+ 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
+ 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
+ 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
+ 0xcc, 0xda, 0x27, 0x10 },
+ { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
+ 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
+ 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
+ 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
+ 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
+ 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
+ 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
+ 0xa0, 0xf0, 0x62, 0xf7 },
+ { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
+ 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
+ 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
+ 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
+ 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
+ 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
+ 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
+ 0xe9, 0xb7, 0x37, 0x3b },
+ { 0x00 },
+ { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
+ 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
+ { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
+ { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
+ 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
+ 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
+ 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
+ 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
+ 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
+ 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
+ 0xbc, 0xc9, 0xf6, 0x62 },
+ { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
+ 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
+ 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
+ 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
+ 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
+ 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
+ 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
+ 0xf4, 0x7c, 0x9b, 0x1f },
+ { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
+ 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
+ 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
+ 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
+ 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
+ 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
+ 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
+ 0x44, 0xae, 0x7e, 0x3f },
+};
+
+static const unsigned char tag[MAX_TESTS * 3][16] =
+{
+ { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
+ 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
+ { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
+ 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
+ { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+ 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
+ { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
+ 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
+ { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
+ 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
+ { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
+ 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
+ { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
+ 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
+ { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
+ 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
+ { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
+ 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
+ { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
+ 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
+ { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
+ 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
+ { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
+ 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
+ { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
+ 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
+ { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
+ 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
+ { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
+ 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
+ { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
+ 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
+ { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
+ 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
+ { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
+ 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
+};
+
+int mbedcrypto_gcm_self_test( int verbose )
+{
+ mbedcrypto_gcm_context ctx;
+ unsigned char buf[64];
+ unsigned char tag_buf[16];
+ int i, j, ret;
+ mbedcrypto_cipher_id_t cipher = MBEDCRYPTO_CIPHER_ID_AES;
+
+ for( j = 0; j < 3; j++ )
+ {
+ int key_len = 128 + 64 * j;
+
+ for( i = 0; i < MAX_TESTS; i++ )
+ {
+ mbedcrypto_gcm_init( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " AES-GCM-%3d #%d (%s): ",
+ key_len, i, "enc" );
+
+ ret = mbedcrypto_gcm_setkey( &ctx, cipher, key[key_index[i]],
+ key_len );
+ /*
+ * AES-192 is an optional feature that may be unavailable when
+ * there is an alternative underlying implementation i.e. when
+ * MBEDCRYPTO_AES_ALT is defined.
+ */
+ if( ret == MBEDCRYPTO_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 )
+ {
+ mbedcrypto_printf( "skipped\n" );
+ break;
+ }
+ else if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ ret = mbedcrypto_gcm_crypt_and_tag( &ctx, MBEDCRYPTO_GCM_ENCRYPT,
+ pt_len[i],
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i],
+ pt[pt_index[i]], buf, 16, tag_buf );
+ if( ret != 0 )
+ goto exit;
+
+ if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
+ memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ mbedcrypto_gcm_free( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ mbedcrypto_gcm_init( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " AES-GCM-%3d #%d (%s): ",
+ key_len, i, "dec" );
+
+ ret = mbedcrypto_gcm_setkey( &ctx, cipher, key[key_index[i]],
+ key_len );
+ if( ret != 0 )
+ goto exit;
+
+ ret = mbedcrypto_gcm_crypt_and_tag( &ctx, MBEDCRYPTO_GCM_DECRYPT,
+ pt_len[i],
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i],
+ ct[j * 6 + i], buf, 16, tag_buf );
+
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
+ memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ mbedcrypto_gcm_free( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ mbedcrypto_gcm_init( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " AES-GCM-%3d #%d split (%s): ",
+ key_len, i, "enc" );
+
+ ret = mbedcrypto_gcm_setkey( &ctx, cipher, key[key_index[i]],
+ key_len );
+ if( ret != 0 )
+ goto exit;
+
+ ret = mbedcrypto_gcm_starts( &ctx, MBEDCRYPTO_GCM_ENCRYPT,
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i] );
+ if( ret != 0 )
+ goto exit;
+
+ if( pt_len[i] > 32 )
+ {
+ size_t rest_len = pt_len[i] - 32;
+ ret = mbedcrypto_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
+ if( ret != 0 )
+ goto exit;
+
+ ret = mbedcrypto_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
+ buf + 32 );
+ if( ret != 0 )
+ goto exit;
+ }
+ else
+ {
+ ret = mbedcrypto_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
+ if( ret != 0 )
+ goto exit;
+ }
+
+ ret = mbedcrypto_gcm_finish( &ctx, tag_buf, 16 );
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
+ memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ mbedcrypto_gcm_free( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ mbedcrypto_gcm_init( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " AES-GCM-%3d #%d split (%s): ",
+ key_len, i, "dec" );
+
+ ret = mbedcrypto_gcm_setkey( &ctx, cipher, key[key_index[i]],
+ key_len );
+ if( ret != 0 )
+ goto exit;
+
+ ret = mbedcrypto_gcm_starts( &ctx, MBEDCRYPTO_GCM_DECRYPT,
+ iv[iv_index[i]], iv_len[i],
+ additional[add_index[i]], add_len[i] );
+ if( ret != 0 )
+ goto exit;
+
+ if( pt_len[i] > 32 )
+ {
+ size_t rest_len = pt_len[i] - 32;
+ ret = mbedcrypto_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
+ if( ret != 0 )
+ goto exit;
+
+ ret = mbedcrypto_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
+ buf + 32 );
+ if( ret != 0 )
+ goto exit;
+ }
+ else
+ {
+ ret = mbedcrypto_gcm_update( &ctx, pt_len[i], ct[j * 6 + i],
+ buf );
+ if( ret != 0 )
+ goto exit;
+ }
+
+ ret = mbedcrypto_gcm_finish( &ctx, tag_buf, 16 );
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
+ memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ mbedcrypto_gcm_free( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ ret = 0;
+
+exit:
+ if( ret != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+ mbedcrypto_gcm_free( &ctx );
+ }
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST && MBEDCRYPTO_AES_C */
+
+#endif /* MBEDCRYPTO_GCM_C */
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
new file mode 100644
index 0000000..aff2cdb
--- /dev/null
+++ b/library/hmac_drbg.c
@@ -0,0 +1,530 @@
+/*
+ * HMAC_DRBG implementation (NIST SP 800-90)
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * The NIST SP 800-90A DRBGs are described in the following publication.
+ * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
+ * References below are based on rev. 1 (January 2012).
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_HMAC_DRBG_C)
+
+#include "mbedcrypto/hmac_drbg.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_SELF_TEST */
+#endif /* MBEDCRYPTO_PLATFORM_C */
+
+/*
+ * HMAC_DRBG context initialization
+ */
+void mbedcrypto_hmac_drbg_init( mbedcrypto_hmac_drbg_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_hmac_drbg_context ) );
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_mutex_init( &ctx->mutex );
+#endif
+}
+
+/*
+ * HMAC_DRBG update, using optional additional data (10.1.2.2)
+ */
+void mbedcrypto_hmac_drbg_update( mbedcrypto_hmac_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len )
+{
+ size_t md_len = mbedcrypto_md_get_size( ctx->md_ctx.md_info );
+ unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
+ unsigned char sep[1];
+ unsigned char K[MBEDCRYPTO_MD_MAX_SIZE];
+
+ for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
+ {
+ /* Step 1 or 4 */
+ mbedcrypto_md_hmac_reset( &ctx->md_ctx );
+ mbedcrypto_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+ mbedcrypto_md_hmac_update( &ctx->md_ctx, sep, 1 );
+ if( rounds == 2 )
+ mbedcrypto_md_hmac_update( &ctx->md_ctx, additional, add_len );
+ mbedcrypto_md_hmac_finish( &ctx->md_ctx, K );
+
+ /* Step 2 or 5 */
+ mbedcrypto_md_hmac_starts( &ctx->md_ctx, K, md_len );
+ mbedcrypto_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+ mbedcrypto_md_hmac_finish( &ctx->md_ctx, ctx->V );
+ }
+}
+
+/*
+ * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
+ */
+int mbedcrypto_hmac_drbg_seed_buf( mbedcrypto_hmac_drbg_context *ctx,
+ const mbedcrypto_md_info_t * md_info,
+ const unsigned char *data, size_t data_len )
+{
+ int ret;
+
+ if( ( ret = mbedcrypto_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
+ return( ret );
+
+ /*
+ * Set initial working state.
+ * Use the V memory location, which is currently all 0, to initialize the
+ * MD context with an all-zero key. Then set V to its initial value.
+ */
+ mbedcrypto_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedcrypto_md_get_size( md_info ) );
+ memset( ctx->V, 0x01, mbedcrypto_md_get_size( md_info ) );
+
+ mbedcrypto_hmac_drbg_update( ctx, data, data_len );
+
+ return( 0 );
+}
+
+/*
+ * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
+ */
+int mbedcrypto_hmac_drbg_reseed( mbedcrypto_hmac_drbg_context *ctx,
+ const unsigned char *additional, size_t len )
+{
+ unsigned char seed[MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT];
+ size_t seedlen;
+
+ /* III. Check input length */
+ if( len > MBEDCRYPTO_HMAC_DRBG_MAX_INPUT ||
+ ctx->entropy_len + len > MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT )
+ {
+ return( MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+ }
+
+ memset( seed, 0, MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT );
+
+ /* IV. Gather entropy_len bytes of entropy for the seed */
+ if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
+ return( MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
+
+ seedlen = ctx->entropy_len;
+
+ /* 1. Concatenate entropy and additional data if any */
+ if( additional != NULL && len != 0 )
+ {
+ memcpy( seed + seedlen, additional, len );
+ seedlen += len;
+ }
+
+ /* 2. Update state */
+ mbedcrypto_hmac_drbg_update( ctx, seed, seedlen );
+
+ /* 3. Reset reseed_counter */
+ ctx->reseed_counter = 1;
+
+ /* 4. Done */
+ return( 0 );
+}
+
+/*
+ * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
+ */
+int mbedcrypto_hmac_drbg_seed( mbedcrypto_hmac_drbg_context *ctx,
+ const mbedcrypto_md_info_t * md_info,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len )
+{
+ int ret;
+ size_t entropy_len, md_size;
+
+ if( ( ret = mbedcrypto_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
+ return( ret );
+
+ md_size = mbedcrypto_md_get_size( md_info );
+
+ /*
+ * Set initial working state.
+ * Use the V memory location, which is currently all 0, to initialize the
+ * MD context with an all-zero key. Then set V to its initial value.
+ */
+ mbedcrypto_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
+ memset( ctx->V, 0x01, md_size );
+
+ ctx->f_entropy = f_entropy;
+ ctx->p_entropy = p_entropy;
+
+ ctx->reseed_interval = MBEDCRYPTO_HMAC_DRBG_RESEED_INTERVAL;
+
+ /*
+ * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
+ * each hash function, then according to SP800-90A rev1 10.1 table 2,
+ * min_entropy_len (in bits) is security_strength.
+ *
+ * (This also matches the sizes used in the NIST test vectors.)
+ */
+ entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
+ md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
+ 32; /* better (256+) -> 256 bits */
+
+ /*
+ * For initialisation, use more entropy to emulate a nonce
+ * (Again, matches test vectors.)
+ */
+ ctx->entropy_len = entropy_len * 3 / 2;
+
+ if( ( ret = mbedcrypto_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
+ return( ret );
+
+ ctx->entropy_len = entropy_len;
+
+ return( 0 );
+}
+
+/*
+ * Set prediction resistance
+ */
+void mbedcrypto_hmac_drbg_set_prediction_resistance( mbedcrypto_hmac_drbg_context *ctx,
+ int resistance )
+{
+ ctx->prediction_resistance = resistance;
+}
+
+/*
+ * Set entropy length grabbed for reseeds
+ */
+void mbedcrypto_hmac_drbg_set_entropy_len( mbedcrypto_hmac_drbg_context *ctx, size_t len )
+{
+ ctx->entropy_len = len;
+}
+
+/*
+ * Set reseed interval
+ */
+void mbedcrypto_hmac_drbg_set_reseed_interval( mbedcrypto_hmac_drbg_context *ctx, int interval )
+{
+ ctx->reseed_interval = interval;
+}
+
+/*
+ * HMAC_DRBG random function with optional additional data:
+ * 10.1.2.5 (arabic) + 9.3 (Roman)
+ */
+int mbedcrypto_hmac_drbg_random_with_add( void *p_rng,
+ unsigned char *output, size_t out_len,
+ const unsigned char *additional, size_t add_len )
+{
+ int ret;
+ mbedcrypto_hmac_drbg_context *ctx = (mbedcrypto_hmac_drbg_context *) p_rng;
+ size_t md_len = mbedcrypto_md_get_size( ctx->md_ctx.md_info );
+ size_t left = out_len;
+ unsigned char *out = output;
+
+ /* II. Check request length */
+ if( out_len > MBEDCRYPTO_HMAC_DRBG_MAX_REQUEST )
+ return( MBEDCRYPTO_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
+
+ /* III. Check input length */
+ if( add_len > MBEDCRYPTO_HMAC_DRBG_MAX_INPUT )
+ return( MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+
+ /* 1. (aka VII and IX) Check reseed counter and PR */
+ if( ctx->f_entropy != NULL && /* For no-reseeding instances */
+ ( ctx->prediction_resistance == MBEDCRYPTO_HMAC_DRBG_PR_ON ||
+ ctx->reseed_counter > ctx->reseed_interval ) )
+ {
+ if( ( ret = mbedcrypto_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
+ return( ret );
+
+ add_len = 0; /* VII.4 */
+ }
+
+ /* 2. Use additional data if any */
+ if( additional != NULL && add_len != 0 )
+ mbedcrypto_hmac_drbg_update( ctx, additional, add_len );
+
+ /* 3, 4, 5. Generate bytes */
+ while( left != 0 )
+ {
+ size_t use_len = left > md_len ? md_len : left;
+
+ mbedcrypto_md_hmac_reset( &ctx->md_ctx );
+ mbedcrypto_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+ mbedcrypto_md_hmac_finish( &ctx->md_ctx, ctx->V );
+
+ memcpy( out, ctx->V, use_len );
+ out += use_len;
+ left -= use_len;
+ }
+
+ /* 6. Update */
+ mbedcrypto_hmac_drbg_update( ctx, additional, add_len );
+
+ /* 7. Update reseed counter */
+ ctx->reseed_counter++;
+
+ /* 8. Done */
+ return( 0 );
+}
+
+/*
+ * HMAC_DRBG random function
+ */
+int mbedcrypto_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
+{
+ int ret;
+ mbedcrypto_hmac_drbg_context *ctx = (mbedcrypto_hmac_drbg_context *) p_rng;
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( ( ret = mbedcrypto_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ ret = mbedcrypto_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( mbedcrypto_mutex_unlock( &ctx->mutex ) != 0 )
+ return( MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+ return( ret );
+}
+
+/*
+ * Free an HMAC_DRBG context
+ */
+void mbedcrypto_hmac_drbg_free( mbedcrypto_hmac_drbg_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_mutex_free( &ctx->mutex );
+#endif
+ mbedcrypto_md_free( &ctx->md_ctx );
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_hmac_drbg_context ) );
+}
+
+#if defined(MBEDCRYPTO_FS_IO)
+int mbedcrypto_hmac_drbg_write_seed_file( mbedcrypto_hmac_drbg_context *ctx, const char *path )
+{
+ int ret;
+ FILE *f;
+ unsigned char buf[ MBEDCRYPTO_HMAC_DRBG_MAX_INPUT ];
+
+ if( ( f = fopen( path, "wb" ) ) == NULL )
+ return( MBEDCRYPTO_ERR_HMAC_DRBG_FILE_IO_ERROR );
+
+ if( ( ret = mbedcrypto_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
+ goto exit;
+
+ if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
+ {
+ ret = MBEDCRYPTO_ERR_HMAC_DRBG_FILE_IO_ERROR;
+ goto exit;
+ }
+
+ ret = 0;
+
+exit:
+ fclose( f );
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+
+ return( ret );
+}
+
+int mbedcrypto_hmac_drbg_update_seed_file( mbedcrypto_hmac_drbg_context *ctx, const char *path )
+{
+ int ret = 0;
+ FILE *f;
+ size_t n;
+ unsigned char buf[ MBEDCRYPTO_HMAC_DRBG_MAX_INPUT ];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( MBEDCRYPTO_ERR_HMAC_DRBG_FILE_IO_ERROR );
+
+ fseek( f, 0, SEEK_END );
+ n = (size_t) ftell( f );
+ fseek( f, 0, SEEK_SET );
+
+ if( n > MBEDCRYPTO_HMAC_DRBG_MAX_INPUT )
+ {
+ fclose( f );
+ return( MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+ }
+
+ if( fread( buf, 1, n, f ) != n )
+ ret = MBEDCRYPTO_ERR_HMAC_DRBG_FILE_IO_ERROR;
+ else
+ mbedcrypto_hmac_drbg_update( ctx, buf, n );
+
+ fclose( f );
+
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+
+ if( ret != 0 )
+ return( ret );
+
+ return( mbedcrypto_hmac_drbg_write_seed_file( ctx, path ) );
+}
+#endif /* MBEDCRYPTO_FS_IO */
+
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+#if !defined(MBEDCRYPTO_SHA1_C)
+/* Dummy checkup routine */
+int mbedcrypto_hmac_drbg_self_test( int verbose )
+{
+ (void) verbose;
+ return( 0 );
+}
+#else
+
+#define OUTPUT_LEN 80
+
+/* From a NIST PR=true test vector */
+static const unsigned char entropy_pr[] = {
+ 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
+ 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
+ 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
+ 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
+ 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
+static const unsigned char result_pr[OUTPUT_LEN] = {
+ 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
+ 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
+ 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
+ 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
+ 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
+ 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
+ 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
+
+/* From a NIST PR=false test vector */
+static const unsigned char entropy_nopr[] = {
+ 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
+ 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
+ 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
+ 0xe9, 0x9d, 0xfe, 0xdf };
+static const unsigned char result_nopr[OUTPUT_LEN] = {
+ 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
+ 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
+ 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
+ 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
+ 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
+ 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
+ 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
+
+/* "Entropy" from buffer */
+static size_t test_offset;
+static int hmac_drbg_self_test_entropy( void *data,
+ unsigned char *buf, size_t len )
+{
+ const unsigned char *p = data;
+ memcpy( buf, p + test_offset, len );
+ test_offset += len;
+ return( 0 );
+}
+
+#define CHK( c ) if( (c) != 0 ) \
+ { \
+ if( verbose != 0 ) \
+ mbedcrypto_printf( "failed\n" ); \
+ return( 1 ); \
+ }
+
+/*
+ * Checkup routine for HMAC_DRBG with SHA-1
+ */
+int mbedcrypto_hmac_drbg_self_test( int verbose )
+{
+ mbedcrypto_hmac_drbg_context ctx;
+ unsigned char buf[OUTPUT_LEN];
+ const mbedcrypto_md_info_t *md_info = mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_SHA1 );
+
+ mbedcrypto_hmac_drbg_init( &ctx );
+
+ /*
+ * PR = True
+ */
+ if( verbose != 0 )
+ mbedcrypto_printf( " HMAC_DRBG (PR = True) : " );
+
+ test_offset = 0;
+ CHK( mbedcrypto_hmac_drbg_seed( &ctx, md_info,
+ hmac_drbg_self_test_entropy, (void *) entropy_pr,
+ NULL, 0 ) );
+ mbedcrypto_hmac_drbg_set_prediction_resistance( &ctx, MBEDCRYPTO_HMAC_DRBG_PR_ON );
+ CHK( mbedcrypto_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+ CHK( mbedcrypto_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+ CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
+ mbedcrypto_hmac_drbg_free( &ctx );
+
+ mbedcrypto_hmac_drbg_free( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ /*
+ * PR = False
+ */
+ if( verbose != 0 )
+ mbedcrypto_printf( " HMAC_DRBG (PR = False) : " );
+
+ mbedcrypto_hmac_drbg_init( &ctx );
+
+ test_offset = 0;
+ CHK( mbedcrypto_hmac_drbg_seed( &ctx, md_info,
+ hmac_drbg_self_test_entropy, (void *) entropy_nopr,
+ NULL, 0 ) );
+ CHK( mbedcrypto_hmac_drbg_reseed( &ctx, NULL, 0 ) );
+ CHK( mbedcrypto_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+ CHK( mbedcrypto_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+ CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
+ mbedcrypto_hmac_drbg_free( &ctx );
+
+ mbedcrypto_hmac_drbg_free( &ctx );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_SHA1_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_HMAC_DRBG_C */
diff --git a/library/md.c b/library/md.c
new file mode 100644
index 0000000..143efa5
--- /dev/null
+++ b/library/md.c
@@ -0,0 +1,475 @@
+/**
+ * \file mbedcrypto_md.c
+ *
+ * \brief Generic message digest wrapper for Mbed Crypto
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_MD_C)
+
+#include "mbedcrypto/md.h"
+#include "mbedcrypto/md_internal.h"
+#include "mbedcrypto/platform_util.h"
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_FS_IO)
+#include <stdio.h>
+#endif
+
+/*
+ * Reminder: update profiles in x509_crt.c when adding a new hash!
+ */
+static const int supported_digests[] = {
+
+#if defined(MBEDCRYPTO_SHA512_C)
+ MBEDCRYPTO_MD_SHA512,
+ MBEDCRYPTO_MD_SHA384,
+#endif
+
+#if defined(MBEDCRYPTO_SHA256_C)
+ MBEDCRYPTO_MD_SHA256,
+ MBEDCRYPTO_MD_SHA224,
+#endif
+
+#if defined(MBEDCRYPTO_SHA1_C)
+ MBEDCRYPTO_MD_SHA1,
+#endif
+
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+ MBEDCRYPTO_MD_RIPEMD160,
+#endif
+
+#if defined(MBEDCRYPTO_MD5_C)
+ MBEDCRYPTO_MD_MD5,
+#endif
+
+#if defined(MBEDCRYPTO_MD4_C)
+ MBEDCRYPTO_MD_MD4,
+#endif
+
+#if defined(MBEDCRYPTO_MD2_C)
+ MBEDCRYPTO_MD_MD2,
+#endif
+
+ MBEDCRYPTO_MD_NONE
+};
+
+const int *mbedcrypto_md_list( void )
+{
+ return( supported_digests );
+}
+
+const mbedcrypto_md_info_t *mbedcrypto_md_info_from_string( const char *md_name )
+{
+ if( NULL == md_name )
+ return( NULL );
+
+ /* Get the appropriate digest information */
+#if defined(MBEDCRYPTO_MD2_C)
+ if( !strcmp( "MD2", md_name ) )
+ return mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_MD2 );
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+ if( !strcmp( "MD4", md_name ) )
+ return mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_MD4 );
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+ if( !strcmp( "MD5", md_name ) )
+ return mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_MD5 );
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+ if( !strcmp( "RIPEMD160", md_name ) )
+ return mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_RIPEMD160 );
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+ if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) )
+ return mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_SHA1 );
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+ if( !strcmp( "SHA224", md_name ) )
+ return mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_SHA224 );
+ if( !strcmp( "SHA256", md_name ) )
+ return mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_SHA256 );
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+ if( !strcmp( "SHA384", md_name ) )
+ return mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_SHA384 );
+ if( !strcmp( "SHA512", md_name ) )
+ return mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_SHA512 );
+#endif
+ return( NULL );
+}
+
+const mbedcrypto_md_info_t *mbedcrypto_md_info_from_type( mbedcrypto_md_type_t md_type )
+{
+ switch( md_type )
+ {
+#if defined(MBEDCRYPTO_MD2_C)
+ case MBEDCRYPTO_MD_MD2:
+ return( &mbedcrypto_md2_info );
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+ case MBEDCRYPTO_MD_MD4:
+ return( &mbedcrypto_md4_info );
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+ case MBEDCRYPTO_MD_MD5:
+ return( &mbedcrypto_md5_info );
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+ case MBEDCRYPTO_MD_RIPEMD160:
+ return( &mbedcrypto_ripemd160_info );
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+ case MBEDCRYPTO_MD_SHA1:
+ return( &mbedcrypto_sha1_info );
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+ case MBEDCRYPTO_MD_SHA224:
+ return( &mbedcrypto_sha224_info );
+ case MBEDCRYPTO_MD_SHA256:
+ return( &mbedcrypto_sha256_info );
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+ case MBEDCRYPTO_MD_SHA384:
+ return( &mbedcrypto_sha384_info );
+ case MBEDCRYPTO_MD_SHA512:
+ return( &mbedcrypto_sha512_info );
+#endif
+ default:
+ return( NULL );
+ }
+}
+
+void mbedcrypto_md_init( mbedcrypto_md_context_t *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_md_context_t ) );
+}
+
+void mbedcrypto_md_free( mbedcrypto_md_context_t *ctx )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return;
+
+ if( ctx->md_ctx != NULL )
+ ctx->md_info->ctx_free_func( ctx->md_ctx );
+
+ if( ctx->hmac_ctx != NULL )
+ {
+ mbedcrypto_platform_zeroize( ctx->hmac_ctx,
+ 2 * ctx->md_info->block_size );
+ mbedcrypto_free( ctx->hmac_ctx );
+ }
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_md_context_t ) );
+}
+
+int mbedcrypto_md_clone( mbedcrypto_md_context_t *dst,
+ const mbedcrypto_md_context_t *src )
+{
+ if( dst == NULL || dst->md_info == NULL ||
+ src == NULL || src->md_info == NULL ||
+ dst->md_info != src->md_info )
+ {
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+ }
+
+ dst->md_info->clone_func( dst->md_ctx, src->md_ctx );
+
+ return( 0 );
+}
+
+#if ! defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+int mbedcrypto_md_init_ctx( mbedcrypto_md_context_t *ctx, const mbedcrypto_md_info_t *md_info )
+{
+ return mbedcrypto_md_setup( ctx, md_info, 1 );
+}
+#endif
+
+int mbedcrypto_md_setup( mbedcrypto_md_context_t *ctx, const mbedcrypto_md_info_t *md_info, int hmac )
+{
+ if( md_info == NULL || ctx == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
+ return( MBEDCRYPTO_ERR_MD_ALLOC_FAILED );
+
+ if( hmac != 0 )
+ {
+ ctx->hmac_ctx = mbedcrypto_calloc( 2, md_info->block_size );
+ if( ctx->hmac_ctx == NULL )
+ {
+ md_info->ctx_free_func( ctx->md_ctx );
+ return( MBEDCRYPTO_ERR_MD_ALLOC_FAILED );
+ }
+ }
+
+ ctx->md_info = md_info;
+
+ return( 0 );
+}
+
+int mbedcrypto_md_starts( mbedcrypto_md_context_t *ctx )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ return( ctx->md_info->starts_func( ctx->md_ctx ) );
+}
+
+int mbedcrypto_md_update( mbedcrypto_md_context_t *ctx, const unsigned char *input, size_t ilen )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
+}
+
+int mbedcrypto_md_finish( mbedcrypto_md_context_t *ctx, unsigned char *output )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
+}
+
+int mbedcrypto_md( const mbedcrypto_md_info_t *md_info, const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ return( md_info->digest_func( input, ilen, output ) );
+}
+
+#if defined(MBEDCRYPTO_FS_IO)
+int mbedcrypto_md_file( const mbedcrypto_md_info_t *md_info, const char *path, unsigned char *output )
+{
+ int ret;
+ FILE *f;
+ size_t n;
+ mbedcrypto_md_context_t ctx;
+ unsigned char buf[1024];
+
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( MBEDCRYPTO_ERR_MD_FILE_IO_ERROR );
+
+ mbedcrypto_md_init( &ctx );
+
+ if( ( ret = mbedcrypto_md_setup( &ctx, md_info, 0 ) ) != 0 )
+ goto cleanup;
+
+ if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 )
+ goto cleanup;
+
+ while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+ if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 )
+ goto cleanup;
+
+ if( ferror( f ) != 0 )
+ ret = MBEDCRYPTO_ERR_MD_FILE_IO_ERROR;
+ else
+ ret = md_info->finish_func( ctx.md_ctx, output );
+
+cleanup:
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+ fclose( f );
+ mbedcrypto_md_free( &ctx );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_FS_IO */
+
+int mbedcrypto_md_hmac_starts( mbedcrypto_md_context_t *ctx, const unsigned char *key, size_t keylen )
+{
+ int ret;
+ unsigned char sum[MBEDCRYPTO_MD_MAX_SIZE];
+ unsigned char *ipad, *opad;
+ size_t i;
+
+ if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ if( keylen > (size_t) ctx->md_info->block_size )
+ {
+ if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+ goto cleanup;
+ if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 )
+ goto cleanup;
+ if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 )
+ goto cleanup;
+
+ keylen = ctx->md_info->size;
+ key = sum;
+ }
+
+ ipad = (unsigned char *) ctx->hmac_ctx;
+ opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
+
+ memset( ipad, 0x36, ctx->md_info->block_size );
+ memset( opad, 0x5C, ctx->md_info->block_size );
+
+ for( i = 0; i < keylen; i++ )
+ {
+ ipad[i] = (unsigned char)( ipad[i] ^ key[i] );
+ opad[i] = (unsigned char)( opad[i] ^ key[i] );
+ }
+
+ if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+ goto cleanup;
+ if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad,
+ ctx->md_info->block_size ) ) != 0 )
+ goto cleanup;
+
+cleanup:
+ mbedcrypto_platform_zeroize( sum, sizeof( sum ) );
+
+ return( ret );
+}
+
+int mbedcrypto_md_hmac_update( mbedcrypto_md_context_t *ctx, const unsigned char *input, size_t ilen )
+{
+ if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
+}
+
+int mbedcrypto_md_hmac_finish( mbedcrypto_md_context_t *ctx, unsigned char *output )
+{
+ int ret;
+ unsigned char tmp[MBEDCRYPTO_MD_MAX_SIZE];
+ unsigned char *opad;
+
+ if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
+
+ if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 )
+ return( ret );
+ if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+ return( ret );
+ if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad,
+ ctx->md_info->block_size ) ) != 0 )
+ return( ret );
+ if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp,
+ ctx->md_info->size ) ) != 0 )
+ return( ret );
+ return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
+}
+
+int mbedcrypto_md_hmac_reset( mbedcrypto_md_context_t *ctx )
+{
+ int ret;
+ unsigned char *ipad;
+
+ if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ ipad = (unsigned char *) ctx->hmac_ctx;
+
+ if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+ return( ret );
+ return( ctx->md_info->update_func( ctx->md_ctx, ipad,
+ ctx->md_info->block_size ) );
+}
+
+int mbedcrypto_md_hmac( const mbedcrypto_md_info_t *md_info,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ mbedcrypto_md_context_t ctx;
+ int ret;
+
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ mbedcrypto_md_init( &ctx );
+
+ if( ( ret = mbedcrypto_md_setup( &ctx, md_info, 1 ) ) != 0 )
+ goto cleanup;
+
+ if( ( ret = mbedcrypto_md_hmac_starts( &ctx, key, keylen ) ) != 0 )
+ goto cleanup;
+ if( ( ret = mbedcrypto_md_hmac_update( &ctx, input, ilen ) ) != 0 )
+ goto cleanup;
+ if( ( ret = mbedcrypto_md_hmac_finish( &ctx, output ) ) != 0 )
+ goto cleanup;
+
+cleanup:
+ mbedcrypto_md_free( &ctx );
+
+ return( ret );
+}
+
+int mbedcrypto_md_process( mbedcrypto_md_context_t *ctx, const unsigned char *data )
+{
+ if( ctx == NULL || ctx->md_info == NULL )
+ return( MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA );
+
+ return( ctx->md_info->process_func( ctx->md_ctx, data ) );
+}
+
+unsigned char mbedcrypto_md_get_size( const mbedcrypto_md_info_t *md_info )
+{
+ if( md_info == NULL )
+ return( 0 );
+
+ return md_info->size;
+}
+
+mbedcrypto_md_type_t mbedcrypto_md_get_type( const mbedcrypto_md_info_t *md_info )
+{
+ if( md_info == NULL )
+ return( MBEDCRYPTO_MD_NONE );
+
+ return md_info->type;
+}
+
+const char *mbedcrypto_md_get_name( const mbedcrypto_md_info_t *md_info )
+{
+ if( md_info == NULL )
+ return( NULL );
+
+ return md_info->name;
+}
+
+#endif /* MBEDCRYPTO_MD_C */
diff --git a/library/md2.c b/library/md2.c
new file mode 100644
index 0000000..ffccd0b
--- /dev/null
+++ b/library/md2.c
@@ -0,0 +1,363 @@
+/*
+ * RFC 1115/1319 compliant MD2 implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The MD2 algorithm was designed by Ron Rivest in 1989.
+ *
+ * http://www.ietf.org/rfc/rfc1115.txt
+ * http://www.ietf.org/rfc/rfc1319.txt
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_MD2_C)
+
+#include "mbedcrypto/md2.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_MD2_ALT)
+
+static const unsigned char PI_SUBST[256] =
+{
+ 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
+ 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
+ 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
+ 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
+ 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
+ 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
+ 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
+ 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
+ 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
+ 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
+ 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
+ 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
+ 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
+ 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
+ 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
+ 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
+ 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
+ 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
+ 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
+ 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
+ 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
+ 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
+ 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
+ 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
+ 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
+ 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
+};
+
+void mbedcrypto_md2_init( mbedcrypto_md2_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_md2_context ) );
+}
+
+void mbedcrypto_md2_free( mbedcrypto_md2_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_md2_context ) );
+}
+
+void mbedcrypto_md2_clone( mbedcrypto_md2_context *dst,
+ const mbedcrypto_md2_context *src )
+{
+ *dst = *src;
+}
+
+/*
+ * MD2 context setup
+ */
+int mbedcrypto_md2_starts_ret( mbedcrypto_md2_context *ctx )
+{
+ memset( ctx->cksum, 0, 16 );
+ memset( ctx->state, 0, 46 );
+ memset( ctx->buffer, 0, 16 );
+ ctx->left = 0;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md2_starts( mbedcrypto_md2_context *ctx )
+{
+ mbedcrypto_md2_starts_ret( ctx );
+}
+#endif
+
+#if !defined(MBEDCRYPTO_MD2_PROCESS_ALT)
+int mbedcrypto_internal_md2_process( mbedcrypto_md2_context *ctx )
+{
+ int i, j;
+ unsigned char t = 0;
+
+ for( i = 0; i < 16; i++ )
+ {
+ ctx->state[i + 16] = ctx->buffer[i];
+ ctx->state[i + 32] =
+ (unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
+ }
+
+ for( i = 0; i < 18; i++ )
+ {
+ for( j = 0; j < 48; j++ )
+ {
+ ctx->state[j] = (unsigned char)
+ ( ctx->state[j] ^ PI_SUBST[t] );
+ t = ctx->state[j];
+ }
+
+ t = (unsigned char)( t + i );
+ }
+
+ t = ctx->cksum[15];
+
+ for( i = 0; i < 16; i++ )
+ {
+ ctx->cksum[i] = (unsigned char)
+ ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
+ t = ctx->cksum[i];
+ }
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md2_process( mbedcrypto_md2_context *ctx )
+{
+ mbedcrypto_internal_md2_process( ctx );
+}
+#endif
+#endif /* !MBEDCRYPTO_MD2_PROCESS_ALT */
+
+/*
+ * MD2 process buffer
+ */
+int mbedcrypto_md2_update_ret( mbedcrypto_md2_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ int ret;
+ size_t fill;
+
+ while( ilen > 0 )
+ {
+ if( ilen > 16 - ctx->left )
+ fill = 16 - ctx->left;
+ else
+ fill = ilen;
+
+ memcpy( ctx->buffer + ctx->left, input, fill );
+
+ ctx->left += fill;
+ input += fill;
+ ilen -= fill;
+
+ if( ctx->left == 16 )
+ {
+ ctx->left = 0;
+ if( ( ret = mbedcrypto_internal_md2_process( ctx ) ) != 0 )
+ return( ret );
+ }
+ }
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md2_update( mbedcrypto_md2_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ mbedcrypto_md2_update_ret( ctx, input, ilen );
+}
+#endif
+
+/*
+ * MD2 final digest
+ */
+int mbedcrypto_md2_finish_ret( mbedcrypto_md2_context *ctx,
+ unsigned char output[16] )
+{
+ int ret;
+ size_t i;
+ unsigned char x;
+
+ x = (unsigned char)( 16 - ctx->left );
+
+ for( i = ctx->left; i < 16; i++ )
+ ctx->buffer[i] = x;
+
+ if( ( ret = mbedcrypto_internal_md2_process( ctx ) ) != 0 )
+ return( ret );
+
+ memcpy( ctx->buffer, ctx->cksum, 16 );
+ if( ( ret = mbedcrypto_internal_md2_process( ctx ) ) != 0 )
+ return( ret );
+
+ memcpy( output, ctx->state, 16 );
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md2_finish( mbedcrypto_md2_context *ctx,
+ unsigned char output[16] )
+{
+ mbedcrypto_md2_finish_ret( ctx, output );
+}
+#endif
+
+#endif /* !MBEDCRYPTO_MD2_ALT */
+
+/*
+ * output = MD2( input buffer )
+ */
+int mbedcrypto_md2_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] )
+{
+ int ret;
+ mbedcrypto_md2_context ctx;
+
+ mbedcrypto_md2_init( &ctx );
+
+ if( ( ret = mbedcrypto_md2_starts_ret( &ctx ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_md2_update_ret( &ctx, input, ilen ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_md2_finish_ret( &ctx, output ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedcrypto_md2_free( &ctx );
+
+ return( ret );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md2( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] )
+{
+ mbedcrypto_md2_ret( input, ilen, output );
+}
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+/*
+ * RFC 1319 test vectors
+ */
+static const unsigned char md2_test_str[7][81] =
+{
+ { "" },
+ { "a" },
+ { "abc" },
+ { "message digest" },
+ { "abcdefghijklmnopqrstuvwxyz" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+ { "12345678901234567890123456789012345678901234567890123456789012"
+ "345678901234567890" }
+};
+
+static const size_t md2_test_strlen[7] =
+{
+ 0, 1, 3, 14, 26, 62, 80
+};
+
+static const unsigned char md2_test_sum[7][16] =
+{
+ { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
+ 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
+ { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
+ 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
+ { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
+ 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
+ { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
+ 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
+ { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
+ 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
+ { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
+ 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
+ { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
+ 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_md2_self_test( int verbose )
+{
+ int i, ret = 0;
+ unsigned char md2sum[16];
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " MD2 test #%d: ", i + 1 );
+
+ ret = mbedcrypto_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum );
+ if( ret != 0 )
+ goto fail;
+
+ if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
+ {
+ ret = 1;
+ goto fail;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ return( 0 );
+
+fail:
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_MD2_C */
diff --git a/library/md4.c b/library/md4.c
new file mode 100644
index 0000000..6fb9d68
--- /dev/null
+++ b/library/md4.c
@@ -0,0 +1,468 @@
+/*
+ * RFC 1186/1320 compliant MD4 implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The MD4 algorithm was designed by Ron Rivest in 1990.
+ *
+ * http://www.ietf.org/rfc/rfc1186.txt
+ * http://www.ietf.org/rfc/rfc1320.txt
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_MD4_C)
+
+#include "mbedcrypto/md4.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_MD4_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
+ (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
+ (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
+ (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
+}
+#endif
+
+void mbedcrypto_md4_init( mbedcrypto_md4_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_md4_context ) );
+}
+
+void mbedcrypto_md4_free( mbedcrypto_md4_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_md4_context ) );
+}
+
+void mbedcrypto_md4_clone( mbedcrypto_md4_context *dst,
+ const mbedcrypto_md4_context *src )
+{
+ *dst = *src;
+}
+
+/*
+ * MD4 context setup
+ */
+int mbedcrypto_md4_starts_ret( mbedcrypto_md4_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md4_starts( mbedcrypto_md4_context *ctx )
+{
+ mbedcrypto_md4_starts_ret( ctx );
+}
+#endif
+
+#if !defined(MBEDCRYPTO_MD4_PROCESS_ALT)
+int mbedcrypto_internal_md4_process( mbedcrypto_md4_context *ctx,
+ const unsigned char data[64] )
+{
+ uint32_t X[16], A, B, C, D;
+
+ GET_UINT32_LE( X[ 0], data, 0 );
+ GET_UINT32_LE( X[ 1], data, 4 );
+ GET_UINT32_LE( X[ 2], data, 8 );
+ GET_UINT32_LE( X[ 3], data, 12 );
+ GET_UINT32_LE( X[ 4], data, 16 );
+ GET_UINT32_LE( X[ 5], data, 20 );
+ GET_UINT32_LE( X[ 6], data, 24 );
+ GET_UINT32_LE( X[ 7], data, 28 );
+ GET_UINT32_LE( X[ 8], data, 32 );
+ GET_UINT32_LE( X[ 9], data, 36 );
+ GET_UINT32_LE( X[10], data, 40 );
+ GET_UINT32_LE( X[11], data, 44 );
+ GET_UINT32_LE( X[12], data, 48 );
+ GET_UINT32_LE( X[13], data, 52 );
+ GET_UINT32_LE( X[14], data, 56 );
+ GET_UINT32_LE( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+
+#define F(x, y, z) ((x & y) | ((~x) & z))
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); }
+
+ P( A, B, C, D, X[ 0], 3 );
+ P( D, A, B, C, X[ 1], 7 );
+ P( C, D, A, B, X[ 2], 11 );
+ P( B, C, D, A, X[ 3], 19 );
+ P( A, B, C, D, X[ 4], 3 );
+ P( D, A, B, C, X[ 5], 7 );
+ P( C, D, A, B, X[ 6], 11 );
+ P( B, C, D, A, X[ 7], 19 );
+ P( A, B, C, D, X[ 8], 3 );
+ P( D, A, B, C, X[ 9], 7 );
+ P( C, D, A, B, X[10], 11 );
+ P( B, C, D, A, X[11], 19 );
+ P( A, B, C, D, X[12], 3 );
+ P( D, A, B, C, X[13], 7 );
+ P( C, D, A, B, X[14], 11 );
+ P( B, C, D, A, X[15], 19 );
+
+#undef P
+#undef F
+
+#define F(x,y,z) ((x & y) | (x & z) | (y & z))
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); }
+
+ P( A, B, C, D, X[ 0], 3 );
+ P( D, A, B, C, X[ 4], 5 );
+ P( C, D, A, B, X[ 8], 9 );
+ P( B, C, D, A, X[12], 13 );
+ P( A, B, C, D, X[ 1], 3 );
+ P( D, A, B, C, X[ 5], 5 );
+ P( C, D, A, B, X[ 9], 9 );
+ P( B, C, D, A, X[13], 13 );
+ P( A, B, C, D, X[ 2], 3 );
+ P( D, A, B, C, X[ 6], 5 );
+ P( C, D, A, B, X[10], 9 );
+ P( B, C, D, A, X[14], 13 );
+ P( A, B, C, D, X[ 3], 3 );
+ P( D, A, B, C, X[ 7], 5 );
+ P( C, D, A, B, X[11], 9 );
+ P( B, C, D, A, X[15], 13 );
+
+#undef P
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); }
+
+ P( A, B, C, D, X[ 0], 3 );
+ P( D, A, B, C, X[ 8], 9 );
+ P( C, D, A, B, X[ 4], 11 );
+ P( B, C, D, A, X[12], 15 );
+ P( A, B, C, D, X[ 2], 3 );
+ P( D, A, B, C, X[10], 9 );
+ P( C, D, A, B, X[ 6], 11 );
+ P( B, C, D, A, X[14], 15 );
+ P( A, B, C, D, X[ 1], 3 );
+ P( D, A, B, C, X[ 9], 9 );
+ P( C, D, A, B, X[ 5], 11 );
+ P( B, C, D, A, X[13], 15 );
+ P( A, B, C, D, X[ 3], 3 );
+ P( D, A, B, C, X[11], 9 );
+ P( C, D, A, B, X[ 7], 11 );
+ P( B, C, D, A, X[15], 15 );
+
+#undef F
+#undef P
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md4_process( mbedcrypto_md4_context *ctx,
+ const unsigned char data[64] )
+{
+ mbedcrypto_internal_md4_process( ctx, data );
+}
+#endif
+#endif /* !MBEDCRYPTO_MD4_PROCESS_ALT */
+
+/*
+ * MD4 process buffer
+ */
+int mbedcrypto_md4_update_ret( mbedcrypto_md4_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ int ret;
+ size_t fill;
+ uint32_t left;
+
+ if( ilen == 0 )
+ return( 0 );
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, fill );
+
+ if( ( ret = mbedcrypto_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ if( ( ret = mbedcrypto_internal_md4_process( ctx, input ) ) != 0 )
+ return( ret );
+
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left),
+ (void *) input, ilen );
+ }
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md4_update( mbedcrypto_md4_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ mbedcrypto_md4_update_ret( ctx, input, ilen );
+}
+#endif
+
+static const unsigned char md4_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD4 final digest
+ */
+int mbedcrypto_md4_finish_ret( mbedcrypto_md4_context *ctx,
+ unsigned char output[16] )
+{
+ int ret;
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_LE( low, msglen, 0 );
+ PUT_UINT32_LE( high, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ ret = mbedcrypto_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
+ if( ret != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
+ return( ret );
+
+
+ PUT_UINT32_LE( ctx->state[0], output, 0 );
+ PUT_UINT32_LE( ctx->state[1], output, 4 );
+ PUT_UINT32_LE( ctx->state[2], output, 8 );
+ PUT_UINT32_LE( ctx->state[3], output, 12 );
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md4_finish( mbedcrypto_md4_context *ctx,
+ unsigned char output[16] )
+{
+ mbedcrypto_md4_finish_ret( ctx, output );
+}
+#endif
+
+#endif /* !MBEDCRYPTO_MD4_ALT */
+
+/*
+ * output = MD4( input buffer )
+ */
+int mbedcrypto_md4_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] )
+{
+ int ret;
+ mbedcrypto_md4_context ctx;
+
+ mbedcrypto_md4_init( &ctx );
+
+ if( ( ret = mbedcrypto_md4_starts_ret( &ctx ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_md4_update_ret( &ctx, input, ilen ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_md4_finish_ret( &ctx, output ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedcrypto_md4_free( &ctx );
+
+ return( ret );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md4( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] )
+{
+ mbedcrypto_md4_ret( input, ilen, output );
+}
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+/*
+ * RFC 1320 test vectors
+ */
+static const unsigned char md4_test_str[7][81] =
+{
+ { "" },
+ { "a" },
+ { "abc" },
+ { "message digest" },
+ { "abcdefghijklmnopqrstuvwxyz" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+ { "12345678901234567890123456789012345678901234567890123456789012"
+ "345678901234567890" }
+};
+
+static const size_t md4_test_strlen[7] =
+{
+ 0, 1, 3, 14, 26, 62, 80
+};
+
+static const unsigned char md4_test_sum[7][16] =
+{
+ { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
+ 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
+ { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
+ 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
+ { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
+ 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
+ { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
+ 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
+ { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
+ 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
+ { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
+ 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
+ { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
+ 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_md4_self_test( int verbose )
+{
+ int i, ret = 0;
+ unsigned char md4sum[16];
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " MD4 test #%d: ", i + 1 );
+
+ ret = mbedcrypto_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
+ if( ret != 0 )
+ goto fail;
+
+ if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
+ {
+ ret = 1;
+ goto fail;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ return( 0 );
+
+fail:
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_MD4_C */
diff --git a/library/md5.c b/library/md5.c
new file mode 100644
index 0000000..b6a54c9
--- /dev/null
+++ b/library/md5.c
@@ -0,0 +1,481 @@
+/*
+ * RFC 1321 compliant MD5 implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The MD5 algorithm was designed by Ron Rivest in 1991.
+ *
+ * http://www.ietf.org/rfc/rfc1321.txt
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_MD5_C)
+
+#include "mbedcrypto/md5.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_MD5_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
+ (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
+ (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
+ (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
+}
+#endif
+
+void mbedcrypto_md5_init( mbedcrypto_md5_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_md5_context ) );
+}
+
+void mbedcrypto_md5_free( mbedcrypto_md5_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_md5_context ) );
+}
+
+void mbedcrypto_md5_clone( mbedcrypto_md5_context *dst,
+ const mbedcrypto_md5_context *src )
+{
+ *dst = *src;
+}
+
+/*
+ * MD5 context setup
+ */
+int mbedcrypto_md5_starts_ret( mbedcrypto_md5_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md5_starts( mbedcrypto_md5_context *ctx )
+{
+ mbedcrypto_md5_starts_ret( ctx );
+}
+#endif
+
+#if !defined(MBEDCRYPTO_MD5_PROCESS_ALT)
+int mbedcrypto_internal_md5_process( mbedcrypto_md5_context *ctx,
+ const unsigned char data[64] )
+{
+ uint32_t X[16], A, B, C, D;
+
+ GET_UINT32_LE( X[ 0], data, 0 );
+ GET_UINT32_LE( X[ 1], data, 4 );
+ GET_UINT32_LE( X[ 2], data, 8 );
+ GET_UINT32_LE( X[ 3], data, 12 );
+ GET_UINT32_LE( X[ 4], data, 16 );
+ GET_UINT32_LE( X[ 5], data, 20 );
+ GET_UINT32_LE( X[ 6], data, 24 );
+ GET_UINT32_LE( X[ 7], data, 28 );
+ GET_UINT32_LE( X[ 8], data, 32 );
+ GET_UINT32_LE( X[ 9], data, 36 );
+ GET_UINT32_LE( X[10], data, 40 );
+ GET_UINT32_LE( X[11], data, 44 );
+ GET_UINT32_LE( X[12], data, 48 );
+ GET_UINT32_LE( X[13], data, 52 );
+ GET_UINT32_LE( X[14], data, 56 );
+ GET_UINT32_LE( X[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define P(a,b,c,d,k,s,t) \
+{ \
+ a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+ P( A, B, C, D, 0, 7, 0xD76AA478 );
+ P( D, A, B, C, 1, 12, 0xE8C7B756 );
+ P( C, D, A, B, 2, 17, 0x242070DB );
+ P( B, C, D, A, 3, 22, 0xC1BDCEEE );
+ P( A, B, C, D, 4, 7, 0xF57C0FAF );
+ P( D, A, B, C, 5, 12, 0x4787C62A );
+ P( C, D, A, B, 6, 17, 0xA8304613 );
+ P( B, C, D, A, 7, 22, 0xFD469501 );
+ P( A, B, C, D, 8, 7, 0x698098D8 );
+ P( D, A, B, C, 9, 12, 0x8B44F7AF );
+ P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
+ P( B, C, D, A, 11, 22, 0x895CD7BE );
+ P( A, B, C, D, 12, 7, 0x6B901122 );
+ P( D, A, B, C, 13, 12, 0xFD987193 );
+ P( C, D, A, B, 14, 17, 0xA679438E );
+ P( B, C, D, A, 15, 22, 0x49B40821 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+ P( A, B, C, D, 1, 5, 0xF61E2562 );
+ P( D, A, B, C, 6, 9, 0xC040B340 );
+ P( C, D, A, B, 11, 14, 0x265E5A51 );
+ P( B, C, D, A, 0, 20, 0xE9B6C7AA );
+ P( A, B, C, D, 5, 5, 0xD62F105D );
+ P( D, A, B, C, 10, 9, 0x02441453 );
+ P( C, D, A, B, 15, 14, 0xD8A1E681 );
+ P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
+ P( A, B, C, D, 9, 5, 0x21E1CDE6 );
+ P( D, A, B, C, 14, 9, 0xC33707D6 );
+ P( C, D, A, B, 3, 14, 0xF4D50D87 );
+ P( B, C, D, A, 8, 20, 0x455A14ED );
+ P( A, B, C, D, 13, 5, 0xA9E3E905 );
+ P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
+ P( C, D, A, B, 7, 14, 0x676F02D9 );
+ P( B, C, D, A, 12, 20, 0x8D2A4C8A );
+
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+
+ P( A, B, C, D, 5, 4, 0xFFFA3942 );
+ P( D, A, B, C, 8, 11, 0x8771F681 );
+ P( C, D, A, B, 11, 16, 0x6D9D6122 );
+ P( B, C, D, A, 14, 23, 0xFDE5380C );
+ P( A, B, C, D, 1, 4, 0xA4BEEA44 );
+ P( D, A, B, C, 4, 11, 0x4BDECFA9 );
+ P( C, D, A, B, 7, 16, 0xF6BB4B60 );
+ P( B, C, D, A, 10, 23, 0xBEBFBC70 );
+ P( A, B, C, D, 13, 4, 0x289B7EC6 );
+ P( D, A, B, C, 0, 11, 0xEAA127FA );
+ P( C, D, A, B, 3, 16, 0xD4EF3085 );
+ P( B, C, D, A, 6, 23, 0x04881D05 );
+ P( A, B, C, D, 9, 4, 0xD9D4D039 );
+ P( D, A, B, C, 12, 11, 0xE6DB99E5 );
+ P( C, D, A, B, 15, 16, 0x1FA27CF8 );
+ P( B, C, D, A, 2, 23, 0xC4AC5665 );
+
+#undef F
+
+#define F(x,y,z) (y ^ (x | ~z))
+
+ P( A, B, C, D, 0, 6, 0xF4292244 );
+ P( D, A, B, C, 7, 10, 0x432AFF97 );
+ P( C, D, A, B, 14, 15, 0xAB9423A7 );
+ P( B, C, D, A, 5, 21, 0xFC93A039 );
+ P( A, B, C, D, 12, 6, 0x655B59C3 );
+ P( D, A, B, C, 3, 10, 0x8F0CCC92 );
+ P( C, D, A, B, 10, 15, 0xFFEFF47D );
+ P( B, C, D, A, 1, 21, 0x85845DD1 );
+ P( A, B, C, D, 8, 6, 0x6FA87E4F );
+ P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
+ P( C, D, A, B, 6, 15, 0xA3014314 );
+ P( B, C, D, A, 13, 21, 0x4E0811A1 );
+ P( A, B, C, D, 4, 6, 0xF7537E82 );
+ P( D, A, B, C, 11, 10, 0xBD3AF235 );
+ P( C, D, A, B, 2, 15, 0x2AD7D2BB );
+ P( B, C, D, A, 9, 21, 0xEB86D391 );
+
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md5_process( mbedcrypto_md5_context *ctx,
+ const unsigned char data[64] )
+{
+ mbedcrypto_internal_md5_process( ctx, data );
+}
+#endif
+#endif /* !MBEDCRYPTO_MD5_PROCESS_ALT */
+
+/*
+ * MD5 process buffer
+ */
+int mbedcrypto_md5_update_ret( mbedcrypto_md5_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ int ret;
+ size_t fill;
+ uint32_t left;
+
+ if( ilen == 0 )
+ return( 0 );
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+ if( ( ret = mbedcrypto_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ if( ( ret = mbedcrypto_internal_md5_process( ctx, input ) ) != 0 )
+ return( ret );
+
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+ }
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md5_update( mbedcrypto_md5_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ mbedcrypto_md5_update_ret( ctx, input, ilen );
+}
+#endif
+
+static const unsigned char md5_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD5 final digest
+ */
+int mbedcrypto_md5_finish_ret( mbedcrypto_md5_context *ctx,
+ unsigned char output[16] )
+{
+ int ret;
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_LE( low, msglen, 0 );
+ PUT_UINT32_LE( high, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ if( ( ret = mbedcrypto_md5_update_ret( ctx, md5_padding, padn ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_md5_update_ret( ctx, msglen, 8 ) ) != 0 )
+ return( ret );
+
+ PUT_UINT32_LE( ctx->state[0], output, 0 );
+ PUT_UINT32_LE( ctx->state[1], output, 4 );
+ PUT_UINT32_LE( ctx->state[2], output, 8 );
+ PUT_UINT32_LE( ctx->state[3], output, 12 );
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md5_finish( mbedcrypto_md5_context *ctx,
+ unsigned char output[16] )
+{
+ mbedcrypto_md5_finish_ret( ctx, output );
+}
+#endif
+
+#endif /* !MBEDCRYPTO_MD5_ALT */
+
+/*
+ * output = MD5( input buffer )
+ */
+int mbedcrypto_md5_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] )
+{
+ int ret;
+ mbedcrypto_md5_context ctx;
+
+ mbedcrypto_md5_init( &ctx );
+
+ if( ( ret = mbedcrypto_md5_starts_ret( &ctx ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_md5_update_ret( &ctx, input, ilen ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_md5_finish_ret( &ctx, output ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedcrypto_md5_free( &ctx );
+
+ return( ret );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_md5( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[16] )
+{
+ mbedcrypto_md5_ret( input, ilen, output );
+}
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/*
+ * RFC 1321 test vectors
+ */
+static const unsigned char md5_test_buf[7][81] =
+{
+ { "" },
+ { "a" },
+ { "abc" },
+ { "message digest" },
+ { "abcdefghijklmnopqrstuvwxyz" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+ { "12345678901234567890123456789012345678901234567890123456789012"
+ "345678901234567890" }
+};
+
+static const size_t md5_test_buflen[7] =
+{
+ 0, 1, 3, 14, 26, 62, 80
+};
+
+static const unsigned char md5_test_sum[7][16] =
+{
+ { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
+ 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
+ { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
+ 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
+ { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
+ 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
+ { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
+ 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
+ { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
+ 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
+ { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
+ 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
+ { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
+ 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_md5_self_test( int verbose )
+{
+ int i, ret = 0;
+ unsigned char md5sum[16];
+
+ for( i = 0; i < 7; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " MD5 test #%d: ", i + 1 );
+
+ ret = mbedcrypto_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum );
+ if( ret != 0 )
+ goto fail;
+
+ if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
+ {
+ ret = 1;
+ goto fail;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ return( 0 );
+
+fail:
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_MD5_C */
diff --git a/library/md_wrap.c b/library/md_wrap.c
new file mode 100644
index 0000000..d4797c7
--- /dev/null
+++ b/library/md_wrap.c
@@ -0,0 +1,586 @@
+/**
+ * \file md_wrap.c
+ *
+ * \brief Generic message digest wrapper for Mbed Crypto
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_MD_C)
+
+#include "mbedcrypto/md_internal.h"
+
+#if defined(MBEDCRYPTO_MD2_C)
+#include "mbedcrypto/md2.h"
+#endif
+
+#if defined(MBEDCRYPTO_MD4_C)
+#include "mbedcrypto/md4.h"
+#endif
+
+#if defined(MBEDCRYPTO_MD5_C)
+#include "mbedcrypto/md5.h"
+#endif
+
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+#include "mbedcrypto/ripemd160.h"
+#endif
+
+#if defined(MBEDCRYPTO_SHA1_C)
+#include "mbedcrypto/sha1.h"
+#endif
+
+#if defined(MBEDCRYPTO_SHA256_C)
+#include "mbedcrypto/sha256.h"
+#endif
+
+#if defined(MBEDCRYPTO_SHA512_C)
+#include "mbedcrypto/sha512.h"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#if defined(MBEDCRYPTO_MD2_C)
+
+static int md2_starts_wrap( void *ctx )
+{
+ return( mbedcrypto_md2_starts_ret( (mbedcrypto_md2_context *) ctx ) );
+}
+
+static int md2_update_wrap( void *ctx, const unsigned char *input,
+ size_t ilen )
+{
+ return( mbedcrypto_md2_update_ret( (mbedcrypto_md2_context *) ctx, input, ilen ) );
+}
+
+static int md2_finish_wrap( void *ctx, unsigned char *output )
+{
+ return( mbedcrypto_md2_finish_ret( (mbedcrypto_md2_context *) ctx, output ) );
+}
+
+static void *md2_ctx_alloc( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_md2_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_md2_init( (mbedcrypto_md2_context *) ctx );
+
+ return( ctx );
+}
+
+static void md2_ctx_free( void *ctx )
+{
+ mbedcrypto_md2_free( (mbedcrypto_md2_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static void md2_clone_wrap( void *dst, const void *src )
+{
+ mbedcrypto_md2_clone( (mbedcrypto_md2_context *) dst,
+ (const mbedcrypto_md2_context *) src );
+}
+
+static int md2_process_wrap( void *ctx, const unsigned char *data )
+{
+ ((void) data);
+
+ return( mbedcrypto_internal_md2_process( (mbedcrypto_md2_context *) ctx ) );
+}
+
+const mbedcrypto_md_info_t mbedcrypto_md2_info = {
+ MBEDCRYPTO_MD_MD2,
+ "MD2",
+ 16,
+ 16,
+ md2_starts_wrap,
+ md2_update_wrap,
+ md2_finish_wrap,
+ mbedcrypto_md2_ret,
+ md2_ctx_alloc,
+ md2_ctx_free,
+ md2_clone_wrap,
+ md2_process_wrap,
+};
+
+#endif /* MBEDCRYPTO_MD2_C */
+
+#if defined(MBEDCRYPTO_MD4_C)
+
+static int md4_starts_wrap( void *ctx )
+{
+ return( mbedcrypto_md4_starts_ret( (mbedcrypto_md4_context *) ctx ) );
+}
+
+static int md4_update_wrap( void *ctx, const unsigned char *input,
+ size_t ilen )
+{
+ return( mbedcrypto_md4_update_ret( (mbedcrypto_md4_context *) ctx, input, ilen ) );
+}
+
+static int md4_finish_wrap( void *ctx, unsigned char *output )
+{
+ return( mbedcrypto_md4_finish_ret( (mbedcrypto_md4_context *) ctx, output ) );
+}
+
+static void *md4_ctx_alloc( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_md4_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_md4_init( (mbedcrypto_md4_context *) ctx );
+
+ return( ctx );
+}
+
+static void md4_ctx_free( void *ctx )
+{
+ mbedcrypto_md4_free( (mbedcrypto_md4_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static void md4_clone_wrap( void *dst, const void *src )
+{
+ mbedcrypto_md4_clone( (mbedcrypto_md4_context *) dst,
+ (const mbedcrypto_md4_context *) src );
+}
+
+static int md4_process_wrap( void *ctx, const unsigned char *data )
+{
+ return( mbedcrypto_internal_md4_process( (mbedcrypto_md4_context *) ctx, data ) );
+}
+
+const mbedcrypto_md_info_t mbedcrypto_md4_info = {
+ MBEDCRYPTO_MD_MD4,
+ "MD4",
+ 16,
+ 64,
+ md4_starts_wrap,
+ md4_update_wrap,
+ md4_finish_wrap,
+ mbedcrypto_md4_ret,
+ md4_ctx_alloc,
+ md4_ctx_free,
+ md4_clone_wrap,
+ md4_process_wrap,
+};
+
+#endif /* MBEDCRYPTO_MD4_C */
+
+#if defined(MBEDCRYPTO_MD5_C)
+
+static int md5_starts_wrap( void *ctx )
+{
+ return( mbedcrypto_md5_starts_ret( (mbedcrypto_md5_context *) ctx ) );
+}
+
+static int md5_update_wrap( void *ctx, const unsigned char *input,
+ size_t ilen )
+{
+ return( mbedcrypto_md5_update_ret( (mbedcrypto_md5_context *) ctx, input, ilen ) );
+}
+
+static int md5_finish_wrap( void *ctx, unsigned char *output )
+{
+ return( mbedcrypto_md5_finish_ret( (mbedcrypto_md5_context *) ctx, output ) );
+}
+
+static void *md5_ctx_alloc( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_md5_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_md5_init( (mbedcrypto_md5_context *) ctx );
+
+ return( ctx );
+}
+
+static void md5_ctx_free( void *ctx )
+{
+ mbedcrypto_md5_free( (mbedcrypto_md5_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static void md5_clone_wrap( void *dst, const void *src )
+{
+ mbedcrypto_md5_clone( (mbedcrypto_md5_context *) dst,
+ (const mbedcrypto_md5_context *) src );
+}
+
+static int md5_process_wrap( void *ctx, const unsigned char *data )
+{
+ return( mbedcrypto_internal_md5_process( (mbedcrypto_md5_context *) ctx, data ) );
+}
+
+const mbedcrypto_md_info_t mbedcrypto_md5_info = {
+ MBEDCRYPTO_MD_MD5,
+ "MD5",
+ 16,
+ 64,
+ md5_starts_wrap,
+ md5_update_wrap,
+ md5_finish_wrap,
+ mbedcrypto_md5_ret,
+ md5_ctx_alloc,
+ md5_ctx_free,
+ md5_clone_wrap,
+ md5_process_wrap,
+};
+
+#endif /* MBEDCRYPTO_MD5_C */
+
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+
+static int ripemd160_starts_wrap( void *ctx )
+{
+ return( mbedcrypto_ripemd160_starts_ret( (mbedcrypto_ripemd160_context *) ctx ) );
+}
+
+static int ripemd160_update_wrap( void *ctx, const unsigned char *input,
+ size_t ilen )
+{
+ return( mbedcrypto_ripemd160_update_ret( (mbedcrypto_ripemd160_context *) ctx,
+ input, ilen ) );
+}
+
+static int ripemd160_finish_wrap( void *ctx, unsigned char *output )
+{
+ return( mbedcrypto_ripemd160_finish_ret( (mbedcrypto_ripemd160_context *) ctx,
+ output ) );
+}
+
+static void *ripemd160_ctx_alloc( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_ripemd160_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_ripemd160_init( (mbedcrypto_ripemd160_context *) ctx );
+
+ return( ctx );
+}
+
+static void ripemd160_ctx_free( void *ctx )
+{
+ mbedcrypto_ripemd160_free( (mbedcrypto_ripemd160_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static void ripemd160_clone_wrap( void *dst, const void *src )
+{
+ mbedcrypto_ripemd160_clone( (mbedcrypto_ripemd160_context *) dst,
+ (const mbedcrypto_ripemd160_context *) src );
+}
+
+static int ripemd160_process_wrap( void *ctx, const unsigned char *data )
+{
+ return( mbedcrypto_internal_ripemd160_process(
+ (mbedcrypto_ripemd160_context *) ctx, data ) );
+}
+
+const mbedcrypto_md_info_t mbedcrypto_ripemd160_info = {
+ MBEDCRYPTO_MD_RIPEMD160,
+ "RIPEMD160",
+ 20,
+ 64,
+ ripemd160_starts_wrap,
+ ripemd160_update_wrap,
+ ripemd160_finish_wrap,
+ mbedcrypto_ripemd160_ret,
+ ripemd160_ctx_alloc,
+ ripemd160_ctx_free,
+ ripemd160_clone_wrap,
+ ripemd160_process_wrap,
+};
+
+#endif /* MBEDCRYPTO_RIPEMD160_C */
+
+#if defined(MBEDCRYPTO_SHA1_C)
+
+static int sha1_starts_wrap( void *ctx )
+{
+ return( mbedcrypto_sha1_starts_ret( (mbedcrypto_sha1_context *) ctx ) );
+}
+
+static int sha1_update_wrap( void *ctx, const unsigned char *input,
+ size_t ilen )
+{
+ return( mbedcrypto_sha1_update_ret( (mbedcrypto_sha1_context *) ctx,
+ input, ilen ) );
+}
+
+static int sha1_finish_wrap( void *ctx, unsigned char *output )
+{
+ return( mbedcrypto_sha1_finish_ret( (mbedcrypto_sha1_context *) ctx, output ) );
+}
+
+static void *sha1_ctx_alloc( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_sha1_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_sha1_init( (mbedcrypto_sha1_context *) ctx );
+
+ return( ctx );
+}
+
+static void sha1_clone_wrap( void *dst, const void *src )
+{
+ mbedcrypto_sha1_clone( (mbedcrypto_sha1_context *) dst,
+ (const mbedcrypto_sha1_context *) src );
+}
+
+static void sha1_ctx_free( void *ctx )
+{
+ mbedcrypto_sha1_free( (mbedcrypto_sha1_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static int sha1_process_wrap( void *ctx, const unsigned char *data )
+{
+ return( mbedcrypto_internal_sha1_process( (mbedcrypto_sha1_context *) ctx,
+ data ) );
+}
+
+const mbedcrypto_md_info_t mbedcrypto_sha1_info = {
+ MBEDCRYPTO_MD_SHA1,
+ "SHA1",
+ 20,
+ 64,
+ sha1_starts_wrap,
+ sha1_update_wrap,
+ sha1_finish_wrap,
+ mbedcrypto_sha1_ret,
+ sha1_ctx_alloc,
+ sha1_ctx_free,
+ sha1_clone_wrap,
+ sha1_process_wrap,
+};
+
+#endif /* MBEDCRYPTO_SHA1_C */
+
+/*
+ * Wrappers for generic message digests
+ */
+#if defined(MBEDCRYPTO_SHA256_C)
+
+static int sha224_starts_wrap( void *ctx )
+{
+ return( mbedcrypto_sha256_starts_ret( (mbedcrypto_sha256_context *) ctx, 1 ) );
+}
+
+static int sha224_update_wrap( void *ctx, const unsigned char *input,
+ size_t ilen )
+{
+ return( mbedcrypto_sha256_update_ret( (mbedcrypto_sha256_context *) ctx,
+ input, ilen ) );
+}
+
+static int sha224_finish_wrap( void *ctx, unsigned char *output )
+{
+ return( mbedcrypto_sha256_finish_ret( (mbedcrypto_sha256_context *) ctx,
+ output ) );
+}
+
+static int sha224_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ return( mbedcrypto_sha256_ret( input, ilen, output, 1 ) );
+}
+
+static void *sha224_ctx_alloc( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_sha256_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_sha256_init( (mbedcrypto_sha256_context *) ctx );
+
+ return( ctx );
+}
+
+static void sha224_ctx_free( void *ctx )
+{
+ mbedcrypto_sha256_free( (mbedcrypto_sha256_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static void sha224_clone_wrap( void *dst, const void *src )
+{
+ mbedcrypto_sha256_clone( (mbedcrypto_sha256_context *) dst,
+ (const mbedcrypto_sha256_context *) src );
+}
+
+static int sha224_process_wrap( void *ctx, const unsigned char *data )
+{
+ return( mbedcrypto_internal_sha256_process( (mbedcrypto_sha256_context *) ctx,
+ data ) );
+}
+
+const mbedcrypto_md_info_t mbedcrypto_sha224_info = {
+ MBEDCRYPTO_MD_SHA224,
+ "SHA224",
+ 28,
+ 64,
+ sha224_starts_wrap,
+ sha224_update_wrap,
+ sha224_finish_wrap,
+ sha224_wrap,
+ sha224_ctx_alloc,
+ sha224_ctx_free,
+ sha224_clone_wrap,
+ sha224_process_wrap,
+};
+
+static int sha256_starts_wrap( void *ctx )
+{
+ return( mbedcrypto_sha256_starts_ret( (mbedcrypto_sha256_context *) ctx, 0 ) );
+}
+
+static int sha256_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ return( mbedcrypto_sha256_ret( input, ilen, output, 0 ) );
+}
+
+const mbedcrypto_md_info_t mbedcrypto_sha256_info = {
+ MBEDCRYPTO_MD_SHA256,
+ "SHA256",
+ 32,
+ 64,
+ sha256_starts_wrap,
+ sha224_update_wrap,
+ sha224_finish_wrap,
+ sha256_wrap,
+ sha224_ctx_alloc,
+ sha224_ctx_free,
+ sha224_clone_wrap,
+ sha224_process_wrap,
+};
+
+#endif /* MBEDCRYPTO_SHA256_C */
+
+#if defined(MBEDCRYPTO_SHA512_C)
+
+static int sha384_starts_wrap( void *ctx )
+{
+ return( mbedcrypto_sha512_starts_ret( (mbedcrypto_sha512_context *) ctx, 1 ) );
+}
+
+static int sha384_update_wrap( void *ctx, const unsigned char *input,
+ size_t ilen )
+{
+ return( mbedcrypto_sha512_update_ret( (mbedcrypto_sha512_context *) ctx,
+ input, ilen ) );
+}
+
+static int sha384_finish_wrap( void *ctx, unsigned char *output )
+{
+ return( mbedcrypto_sha512_finish_ret( (mbedcrypto_sha512_context *) ctx,
+ output ) );
+}
+
+static int sha384_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ return( mbedcrypto_sha512_ret( input, ilen, output, 1 ) );
+}
+
+static void *sha384_ctx_alloc( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_sha512_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_sha512_init( (mbedcrypto_sha512_context *) ctx );
+
+ return( ctx );
+}
+
+static void sha384_ctx_free( void *ctx )
+{
+ mbedcrypto_sha512_free( (mbedcrypto_sha512_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static void sha384_clone_wrap( void *dst, const void *src )
+{
+ mbedcrypto_sha512_clone( (mbedcrypto_sha512_context *) dst,
+ (const mbedcrypto_sha512_context *) src );
+}
+
+static int sha384_process_wrap( void *ctx, const unsigned char *data )
+{
+ return( mbedcrypto_internal_sha512_process( (mbedcrypto_sha512_context *) ctx,
+ data ) );
+}
+
+const mbedcrypto_md_info_t mbedcrypto_sha384_info = {
+ MBEDCRYPTO_MD_SHA384,
+ "SHA384",
+ 48,
+ 128,
+ sha384_starts_wrap,
+ sha384_update_wrap,
+ sha384_finish_wrap,
+ sha384_wrap,
+ sha384_ctx_alloc,
+ sha384_ctx_free,
+ sha384_clone_wrap,
+ sha384_process_wrap,
+};
+
+static int sha512_starts_wrap( void *ctx )
+{
+ return( mbedcrypto_sha512_starts_ret( (mbedcrypto_sha512_context *) ctx, 0 ) );
+}
+
+static int sha512_wrap( const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ return( mbedcrypto_sha512_ret( input, ilen, output, 0 ) );
+}
+
+const mbedcrypto_md_info_t mbedcrypto_sha512_info = {
+ MBEDCRYPTO_MD_SHA512,
+ "SHA512",
+ 64,
+ 128,
+ sha512_starts_wrap,
+ sha384_update_wrap,
+ sha384_finish_wrap,
+ sha512_wrap,
+ sha384_ctx_alloc,
+ sha384_ctx_free,
+ sha384_clone_wrap,
+ sha384_process_wrap,
+};
+
+#endif /* MBEDCRYPTO_SHA512_C */
+
+#endif /* MBEDCRYPTO_MD_C */
diff --git a/library/oid.c b/library/oid.c
new file mode 100644
index 0000000..000b833
--- /dev/null
+++ b/library/oid.c
@@ -0,0 +1,755 @@
+/**
+ * \file oid.c
+ *
+ * \brief Object Identifier (OID) database
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_OID_C)
+
+#include "mbedcrypto/oid.h"
+#include "mbedcrypto/rsa.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#define mbedcrypto_snprintf snprintf
+#endif
+
+#if defined(MBEDCRYPTO_X509_USE_C) || defined(MBEDCRYPTO_X509_CREATE_C)
+#include "mbedcrypto/x509.h"
+#endif
+
+/*
+ * Macro to automatically add the size of #define'd OIDs
+ */
+#define ADD_LEN(s) s, MBEDCRYPTO_OID_SIZE(s)
+
+/*
+ * Macro to generate an internal function for oid_XXX_from_asn1() (used by
+ * the other functions)
+ */
+#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \
+static const TYPE_T * oid_ ## NAME ## _from_asn1( const mbedcrypto_asn1_buf *oid ) \
+{ \
+ const TYPE_T *p = LIST; \
+ const mbedcrypto_oid_descriptor_t *cur = (const mbedcrypto_oid_descriptor_t *) p; \
+ if( p == NULL || oid == NULL ) return( NULL ); \
+ while( cur->asn1 != NULL ) { \
+ if( cur->asn1_len == oid->len && \
+ memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \
+ return( p ); \
+ } \
+ p++; \
+ cur = (const mbedcrypto_oid_descriptor_t *) p; \
+ } \
+ return( NULL ); \
+}
+
+/*
+ * Macro to generate a function for retrieving a single attribute from the
+ * descriptor of an mbedcrypto_oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
+int FN_NAME( const mbedcrypto_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \
+{ \
+ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
+ if( data == NULL ) return( MBEDCRYPTO_ERR_OID_NOT_FOUND ); \
+ *ATTR1 = data->descriptor.ATTR1; \
+ return( 0 ); \
+}
+
+/*
+ * Macro to generate a function for retrieving a single attribute from an
+ * mbedcrypto_oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
+int FN_NAME( const mbedcrypto_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \
+{ \
+ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
+ if( data == NULL ) return( MBEDCRYPTO_ERR_OID_NOT_FOUND ); \
+ *ATTR1 = data->ATTR1; \
+ return( 0 ); \
+}
+
+/*
+ * Macro to generate a function for retrieving two attributes from an
+ * mbedcrypto_oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \
+ ATTR2_TYPE, ATTR2) \
+int FN_NAME( const mbedcrypto_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \
+{ \
+ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
+ if( data == NULL ) return( MBEDCRYPTO_ERR_OID_NOT_FOUND ); \
+ *ATTR1 = data->ATTR1; \
+ *ATTR2 = data->ATTR2; \
+ return( 0 ); \
+}
+
+/*
+ * Macro to generate a function for retrieving the OID based on a single
+ * attribute from a mbedcrypto_oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \
+int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \
+{ \
+ const TYPE_T *cur = LIST; \
+ while( cur->descriptor.asn1 != NULL ) { \
+ if( cur->ATTR1 == ATTR1 ) { \
+ *oid = cur->descriptor.asn1; \
+ *olen = cur->descriptor.asn1_len; \
+ return( 0 ); \
+ } \
+ cur++; \
+ } \
+ return( MBEDCRYPTO_ERR_OID_NOT_FOUND ); \
+}
+
+/*
+ * Macro to generate a function for retrieving the OID based on two
+ * attributes from a mbedcrypto_oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \
+ ATTR2_TYPE, ATTR2) \
+int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \
+ size_t *olen ) \
+{ \
+ const TYPE_T *cur = LIST; \
+ while( cur->descriptor.asn1 != NULL ) { \
+ if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \
+ *oid = cur->descriptor.asn1; \
+ *olen = cur->descriptor.asn1_len; \
+ return( 0 ); \
+ } \
+ cur++; \
+ } \
+ return( MBEDCRYPTO_ERR_OID_NOT_FOUND ); \
+}
+
+#if defined(MBEDCRYPTO_X509_USE_C) || defined(MBEDCRYPTO_X509_CREATE_C)
+/*
+ * For X520 attribute types
+ */
+typedef struct {
+ mbedcrypto_oid_descriptor_t descriptor;
+ const char *short_name;
+} oid_x520_attr_t;
+
+static const oid_x520_attr_t oid_x520_attr_type[] =
+{
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_CN ), "id-at-commonName", "Common Name" },
+ "CN",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_COUNTRY ), "id-at-countryName", "Country" },
+ "C",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_LOCALITY ), "id-at-locality", "Locality" },
+ "L",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_STATE ), "id-at-state", "State" },
+ "ST",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" },
+ "O",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" },
+ "OU",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" },
+ "emailAddress",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" },
+ "serialNumber",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" },
+ "postalAddress",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" },
+ "postalCode",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_SUR_NAME ), "id-at-surName", "Surname" },
+ "SN",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" },
+ "GN",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_INITIALS ), "id-at-initials", "Initials" },
+ "initials",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" },
+ "generationQualifier",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_TITLE ), "id-at-title", "Title" },
+ "title",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" },
+ "dnQualifier",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" },
+ "pseudonym",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" },
+ "DC",
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" },
+ "uniqueIdentifier",
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ NULL,
+ }
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type)
+FN_OID_GET_ATTR1(mbedcrypto_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name)
+
+/*
+ * For X509 extensions
+ */
+typedef struct {
+ mbedcrypto_oid_descriptor_t descriptor;
+ int ext_type;
+} oid_x509_ext_t;
+
+static const oid_x509_ext_t oid_x509_ext[] =
+{
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" },
+ MBEDCRYPTO_X509_EXT_BASIC_CONSTRAINTS,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" },
+ MBEDCRYPTO_X509_EXT_KEY_USAGE,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" },
+ MBEDCRYPTO_X509_EXT_EXTENDED_KEY_USAGE,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" },
+ MBEDCRYPTO_X509_EXT_SUBJECT_ALT_NAME,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" },
+ MBEDCRYPTO_X509_EXT_NS_CERT_TYPE,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ 0,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext)
+FN_OID_GET_ATTR1(mbedcrypto_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type)
+
+static const mbedcrypto_oid_descriptor_t oid_ext_key_usage[] =
+{
+ { ADD_LEN( MBEDCRYPTO_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" },
+ { ADD_LEN( MBEDCRYPTO_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" },
+ { ADD_LEN( MBEDCRYPTO_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" },
+ { ADD_LEN( MBEDCRYPTO_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" },
+ { ADD_LEN( MBEDCRYPTO_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" },
+ { ADD_LEN( MBEDCRYPTO_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" },
+ { NULL, 0, NULL, NULL },
+};
+
+FN_OID_TYPED_FROM_ASN1(mbedcrypto_oid_descriptor_t, ext_key_usage, oid_ext_key_usage)
+FN_OID_GET_ATTR1(mbedcrypto_oid_get_extended_key_usage, mbedcrypto_oid_descriptor_t, ext_key_usage, const char *, description)
+#endif /* MBEDCRYPTO_X509_USE_C || MBEDCRYPTO_X509_CREATE_C */
+
+#if defined(MBEDCRYPTO_MD_C)
+/*
+ * For SignatureAlgorithmIdentifier
+ */
+typedef struct {
+ mbedcrypto_oid_descriptor_t descriptor;
+ mbedcrypto_md_type_t md_alg;
+ mbedcrypto_pk_type_t pk_alg;
+} oid_sig_alg_t;
+
+static const oid_sig_alg_t oid_sig_alg[] =
+{
+#if defined(MBEDCRYPTO_RSA_C)
+#if defined(MBEDCRYPTO_MD2_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" },
+ MBEDCRYPTO_MD_MD2, MBEDCRYPTO_PK_RSA,
+ },
+#endif /* MBEDCRYPTO_MD2_C */
+#if defined(MBEDCRYPTO_MD4_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" },
+ MBEDCRYPTO_MD_MD4, MBEDCRYPTO_PK_RSA,
+ },
+#endif /* MBEDCRYPTO_MD4_C */
+#if defined(MBEDCRYPTO_MD5_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" },
+ MBEDCRYPTO_MD_MD5, MBEDCRYPTO_PK_RSA,
+ },
+#endif /* MBEDCRYPTO_MD5_C */
+#if defined(MBEDCRYPTO_SHA1_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" },
+ MBEDCRYPTO_MD_SHA1, MBEDCRYPTO_PK_RSA,
+ },
+#endif /* MBEDCRYPTO_SHA1_C */
+#if defined(MBEDCRYPTO_SHA256_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" },
+ MBEDCRYPTO_MD_SHA224, MBEDCRYPTO_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" },
+ MBEDCRYPTO_MD_SHA256, MBEDCRYPTO_PK_RSA,
+ },
+#endif /* MBEDCRYPTO_SHA256_C */
+#if defined(MBEDCRYPTO_SHA512_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" },
+ MBEDCRYPTO_MD_SHA384, MBEDCRYPTO_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" },
+ MBEDCRYPTO_MD_SHA512, MBEDCRYPTO_PK_RSA,
+ },
+#endif /* MBEDCRYPTO_SHA512_C */
+#if defined(MBEDCRYPTO_SHA1_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" },
+ MBEDCRYPTO_MD_SHA1, MBEDCRYPTO_PK_RSA,
+ },
+#endif /* MBEDCRYPTO_SHA1_C */
+#endif /* MBEDCRYPTO_RSA_C */
+#if defined(MBEDCRYPTO_ECDSA_C)
+#if defined(MBEDCRYPTO_SHA1_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" },
+ MBEDCRYPTO_MD_SHA1, MBEDCRYPTO_PK_ECDSA,
+ },
+#endif /* MBEDCRYPTO_SHA1_C */
+#if defined(MBEDCRYPTO_SHA256_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" },
+ MBEDCRYPTO_MD_SHA224, MBEDCRYPTO_PK_ECDSA,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" },
+ MBEDCRYPTO_MD_SHA256, MBEDCRYPTO_PK_ECDSA,
+ },
+#endif /* MBEDCRYPTO_SHA256_C */
+#if defined(MBEDCRYPTO_SHA512_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" },
+ MBEDCRYPTO_MD_SHA384, MBEDCRYPTO_PK_ECDSA,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" },
+ MBEDCRYPTO_MD_SHA512, MBEDCRYPTO_PK_ECDSA,
+ },
+#endif /* MBEDCRYPTO_SHA512_C */
+#endif /* MBEDCRYPTO_ECDSA_C */
+#if defined(MBEDCRYPTO_RSA_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" },
+ MBEDCRYPTO_MD_NONE, MBEDCRYPTO_PK_RSASSA_PSS,
+ },
+#endif /* MBEDCRYPTO_RSA_C */
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDCRYPTO_MD_NONE, MBEDCRYPTO_PK_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg)
+FN_OID_GET_DESCRIPTOR_ATTR1(mbedcrypto_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description)
+FN_OID_GET_ATTR2(mbedcrypto_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedcrypto_md_type_t, md_alg, mbedcrypto_pk_type_t, pk_alg)
+FN_OID_GET_OID_BY_ATTR2(mbedcrypto_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedcrypto_pk_type_t, pk_alg, mbedcrypto_md_type_t, md_alg)
+#endif /* MBEDCRYPTO_MD_C */
+
+/*
+ * For PublicKeyInfo (PKCS1, RFC 5480)
+ */
+typedef struct {
+ mbedcrypto_oid_descriptor_t descriptor;
+ mbedcrypto_pk_type_t pk_alg;
+} oid_pk_alg_t;
+
+static const oid_pk_alg_t oid_pk_alg[] =
+{
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS1_RSA ), "rsaEncryption", "RSA" },
+ MBEDCRYPTO_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" },
+ MBEDCRYPTO_PK_ECKEY,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" },
+ MBEDCRYPTO_PK_ECKEY_DH,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDCRYPTO_PK_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg)
+FN_OID_GET_ATTR1(mbedcrypto_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedcrypto_pk_type_t, pk_alg)
+FN_OID_GET_OID_BY_ATTR1(mbedcrypto_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedcrypto_pk_type_t, pk_alg)
+
+#if defined(MBEDCRYPTO_ECP_C)
+/*
+ * For namedCurve (RFC 5480)
+ */
+typedef struct {
+ mbedcrypto_oid_descriptor_t descriptor;
+ mbedcrypto_ecp_group_id grp_id;
+} oid_ecp_grp_t;
+
+static const oid_ecp_grp_t oid_ecp_grp[] =
+{
+#if defined(MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" },
+ MBEDCRYPTO_ECP_DP_SECP192R1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_SECP192R1_ENABLED */
+#if defined(MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" },
+ MBEDCRYPTO_ECP_DP_SECP224R1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_SECP224R1_ENABLED */
+#if defined(MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" },
+ MBEDCRYPTO_ECP_DP_SECP256R1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED */
+#if defined(MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" },
+ MBEDCRYPTO_ECP_DP_SECP384R1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED */
+#if defined(MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" },
+ MBEDCRYPTO_ECP_DP_SECP521R1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_SECP521R1_ENABLED */
+#if defined(MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" },
+ MBEDCRYPTO_ECP_DP_SECP192K1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_SECP192K1_ENABLED */
+#if defined(MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" },
+ MBEDCRYPTO_ECP_DP_SECP224K1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_SECP224K1_ENABLED */
+#if defined(MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" },
+ MBEDCRYPTO_ECP_DP_SECP256K1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_SECP256K1_ENABLED */
+#if defined(MBEDCRYPTO_ECP_DP_BP256R1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" },
+ MBEDCRYPTO_ECP_DP_BP256R1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_BP256R1_ENABLED */
+#if defined(MBEDCRYPTO_ECP_DP_BP384R1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" },
+ MBEDCRYPTO_ECP_DP_BP384R1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_BP384R1_ENABLED */
+#if defined(MBEDCRYPTO_ECP_DP_BP512R1_ENABLED)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" },
+ MBEDCRYPTO_ECP_DP_BP512R1,
+ },
+#endif /* MBEDCRYPTO_ECP_DP_BP512R1_ENABLED */
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDCRYPTO_ECP_DP_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp)
+FN_OID_GET_ATTR1(mbedcrypto_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedcrypto_ecp_group_id, grp_id)
+FN_OID_GET_OID_BY_ATTR1(mbedcrypto_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedcrypto_ecp_group_id, grp_id)
+#endif /* MBEDCRYPTO_ECP_C */
+
+#if defined(MBEDCRYPTO_CIPHER_C)
+/*
+ * For PKCS#5 PBES2 encryption algorithm
+ */
+typedef struct {
+ mbedcrypto_oid_descriptor_t descriptor;
+ mbedcrypto_cipher_type_t cipher_alg;
+} oid_cipher_alg_t;
+
+static const oid_cipher_alg_t oid_cipher_alg[] =
+{
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DES_CBC ), "desCBC", "DES-CBC" },
+ MBEDCRYPTO_CIPHER_DES_CBC,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" },
+ MBEDCRYPTO_CIPHER_DES_EDE3_CBC,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDCRYPTO_CIPHER_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg)
+FN_OID_GET_ATTR1(mbedcrypto_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedcrypto_cipher_type_t, cipher_alg)
+#endif /* MBEDCRYPTO_CIPHER_C */
+
+#if defined(MBEDCRYPTO_MD_C)
+/*
+ * For digestAlgorithm
+ */
+typedef struct {
+ mbedcrypto_oid_descriptor_t descriptor;
+ mbedcrypto_md_type_t md_alg;
+} oid_md_alg_t;
+
+static const oid_md_alg_t oid_md_alg[] =
+{
+#if defined(MBEDCRYPTO_MD2_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" },
+ MBEDCRYPTO_MD_MD2,
+ },
+#endif /* MBEDCRYPTO_MD2_C */
+#if defined(MBEDCRYPTO_MD4_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" },
+ MBEDCRYPTO_MD_MD4,
+ },
+#endif /* MBEDCRYPTO_MD4_C */
+#if defined(MBEDCRYPTO_MD5_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" },
+ MBEDCRYPTO_MD_MD5,
+ },
+#endif /* MBEDCRYPTO_MD5_C */
+#if defined(MBEDCRYPTO_SHA1_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" },
+ MBEDCRYPTO_MD_SHA1,
+ },
+#endif /* MBEDCRYPTO_SHA1_C */
+#if defined(MBEDCRYPTO_SHA256_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" },
+ MBEDCRYPTO_MD_SHA224,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" },
+ MBEDCRYPTO_MD_SHA256,
+ },
+#endif /* MBEDCRYPTO_SHA256_C */
+#if defined(MBEDCRYPTO_SHA512_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" },
+ MBEDCRYPTO_MD_SHA384,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" },
+ MBEDCRYPTO_MD_SHA512,
+ },
+#endif /* MBEDCRYPTO_SHA512_C */
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDCRYPTO_MD_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg)
+FN_OID_GET_ATTR1(mbedcrypto_oid_get_md_alg, oid_md_alg_t, md_alg, mbedcrypto_md_type_t, md_alg)
+FN_OID_GET_OID_BY_ATTR1(mbedcrypto_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedcrypto_md_type_t, md_alg)
+
+/*
+ * For HMAC digestAlgorithm
+ */
+typedef struct {
+ mbedcrypto_oid_descriptor_t descriptor;
+ mbedcrypto_md_type_t md_hmac;
+} oid_md_hmac_t;
+
+static const oid_md_hmac_t oid_md_hmac[] =
+{
+#if defined(MBEDCRYPTO_SHA1_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" },
+ MBEDCRYPTO_MD_SHA1,
+ },
+#endif /* MBEDCRYPTO_SHA1_C */
+#if defined(MBEDCRYPTO_SHA256_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" },
+ MBEDCRYPTO_MD_SHA224,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" },
+ MBEDCRYPTO_MD_SHA256,
+ },
+#endif /* MBEDCRYPTO_SHA256_C */
+#if defined(MBEDCRYPTO_SHA512_C)
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" },
+ MBEDCRYPTO_MD_SHA384,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" },
+ MBEDCRYPTO_MD_SHA512,
+ },
+#endif /* MBEDCRYPTO_SHA512_C */
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDCRYPTO_MD_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac)
+FN_OID_GET_ATTR1(mbedcrypto_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedcrypto_md_type_t, md_hmac)
+#endif /* MBEDCRYPTO_MD_C */
+
+#if defined(MBEDCRYPTO_PKCS12_C)
+/*
+ * For PKCS#12 PBEs
+ */
+typedef struct {
+ mbedcrypto_oid_descriptor_t descriptor;
+ mbedcrypto_md_type_t md_alg;
+ mbedcrypto_cipher_type_t cipher_alg;
+} oid_pkcs12_pbe_alg_t;
+
+static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] =
+{
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" },
+ MBEDCRYPTO_MD_SHA1, MBEDCRYPTO_CIPHER_DES_EDE3_CBC,
+ },
+ {
+ { ADD_LEN( MBEDCRYPTO_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" },
+ MBEDCRYPTO_MD_SHA1, MBEDCRYPTO_CIPHER_DES_EDE_CBC,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDCRYPTO_MD_NONE, MBEDCRYPTO_CIPHER_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg)
+FN_OID_GET_ATTR2(mbedcrypto_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedcrypto_md_type_t, md_alg, mbedcrypto_cipher_type_t, cipher_alg)
+#endif /* MBEDCRYPTO_PKCS12_C */
+
+#define OID_SAFE_SNPRINTF \
+ do { \
+ if( ret < 0 || (size_t) ret >= n ) \
+ return( MBEDCRYPTO_ERR_OID_BUF_TOO_SMALL ); \
+ \
+ n -= (size_t) ret; \
+ p += (size_t) ret; \
+ } while( 0 )
+
+/* Return the x.y.z.... style numeric string for the given OID */
+int mbedcrypto_oid_get_numeric_string( char *buf, size_t size,
+ const mbedcrypto_asn1_buf *oid )
+{
+ int ret;
+ size_t i, n;
+ unsigned int value;
+ char *p;
+
+ p = buf;
+ n = size;
+
+ /* First byte contains first two dots */
+ if( oid->len > 0 )
+ {
+ ret = mbedcrypto_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 );
+ OID_SAFE_SNPRINTF;
+ }
+
+ value = 0;
+ for( i = 1; i < oid->len; i++ )
+ {
+ /* Prevent overflow in value. */
+ if( ( ( value << 7 ) >> 7 ) != value )
+ return( MBEDCRYPTO_ERR_OID_BUF_TOO_SMALL );
+
+ value <<= 7;
+ value += oid->p[i] & 0x7F;
+
+ if( !( oid->p[i] & 0x80 ) )
+ {
+ /* Last byte */
+ ret = mbedcrypto_snprintf( p, n, ".%d", value );
+ OID_SAFE_SNPRINTF;
+ value = 0;
+ }
+ }
+
+ return( (int) ( size - n ) );
+}
+
+#endif /* MBEDCRYPTO_OID_C */
diff --git a/library/pem.c b/library/pem.c
new file mode 100644
index 0000000..a1a9a84
--- /dev/null
+++ b/library/pem.c
@@ -0,0 +1,488 @@
+/*
+ * Privacy Enhanced Mail (PEM) decoding
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PEM_PARSE_C) || defined(MBEDCRYPTO_PEM_WRITE_C)
+
+#include "mbedcrypto/pem.h"
+#include "mbedcrypto/base64.h"
+#include "mbedcrypto/des.h"
+#include "mbedcrypto/aes.h"
+#include "mbedcrypto/md5.h"
+#include "mbedcrypto/cipher.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#if defined(MBEDCRYPTO_PEM_PARSE_C)
+void mbedcrypto_pem_init( mbedcrypto_pem_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_pem_context ) );
+}
+
+#if defined(MBEDCRYPTO_MD5_C) && defined(MBEDCRYPTO_CIPHER_MODE_CBC) && \
+ ( defined(MBEDCRYPTO_DES_C) || defined(MBEDCRYPTO_AES_C) )
+/*
+ * Read a 16-byte hex string and convert it to binary
+ */
+static int pem_get_iv( const unsigned char *s, unsigned char *iv,
+ size_t iv_len )
+{
+ size_t i, j, k;
+
+ memset( iv, 0, iv_len );
+
+ for( i = 0; i < iv_len * 2; i++, s++ )
+ {
+ if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
+ if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
+ if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
+ return( MBEDCRYPTO_ERR_PEM_INVALID_ENC_IV );
+
+ k = ( ( i & 1 ) != 0 ) ? j : j << 4;
+
+ iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
+ }
+
+ return( 0 );
+}
+
+static int pem_pbkdf1( unsigned char *key, size_t keylen,
+ unsigned char *iv,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ mbedcrypto_md5_context md5_ctx;
+ unsigned char md5sum[16];
+ size_t use_len;
+ int ret;
+
+ mbedcrypto_md5_init( &md5_ctx );
+
+ /*
+ * key[ 0..15] = MD5(pwd || IV)
+ */
+ if( ( ret = mbedcrypto_md5_starts_ret( &md5_ctx ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 )
+ goto exit;
+
+ if( keylen <= 16 )
+ {
+ memcpy( key, md5sum, keylen );
+ goto exit;
+ }
+
+ memcpy( key, md5sum, 16 );
+
+ /*
+ * key[16..23] = MD5(key[ 0..15] || pwd || IV])
+ */
+ if( ( ret = mbedcrypto_md5_starts_ret( &md5_ctx ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 )
+ goto exit;
+
+ use_len = 16;
+ if( keylen < 32 )
+ use_len = keylen - 16;
+
+ memcpy( key + 16, md5sum, use_len );
+
+exit:
+ mbedcrypto_md5_free( &md5_ctx );
+ mbedcrypto_platform_zeroize( md5sum, 16 );
+
+ return( ret );
+}
+
+#if defined(MBEDCRYPTO_DES_C)
+/*
+ * Decrypt with DES-CBC, using PBKDF1 for key derivation
+ */
+static int pem_des_decrypt( unsigned char des_iv[8],
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ mbedcrypto_des_context des_ctx;
+ unsigned char des_key[8];
+ int ret;
+
+ mbedcrypto_des_init( &des_ctx );
+
+ if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_des_setkey_dec( &des_ctx, des_key ) ) != 0 )
+ goto exit;
+ ret = mbedcrypto_des_crypt_cbc( &des_ctx, MBEDCRYPTO_DES_DECRYPT, buflen,
+ des_iv, buf, buf );
+
+exit:
+ mbedcrypto_des_free( &des_ctx );
+ mbedcrypto_platform_zeroize( des_key, 8 );
+
+ return( ret );
+}
+
+/*
+ * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
+ */
+static int pem_des3_decrypt( unsigned char des3_iv[8],
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ mbedcrypto_des3_context des3_ctx;
+ unsigned char des3_key[24];
+ int ret;
+
+ mbedcrypto_des3_init( &des3_ctx );
+
+ if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 )
+ goto exit;
+ ret = mbedcrypto_des3_crypt_cbc( &des3_ctx, MBEDCRYPTO_DES_DECRYPT, buflen,
+ des3_iv, buf, buf );
+
+exit:
+ mbedcrypto_des3_free( &des3_ctx );
+ mbedcrypto_platform_zeroize( des3_key, 24 );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_DES_C */
+
+#if defined(MBEDCRYPTO_AES_C)
+/*
+ * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
+ */
+static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ mbedcrypto_aes_context aes_ctx;
+ unsigned char aes_key[32];
+ int ret;
+
+ mbedcrypto_aes_init( &aes_ctx );
+
+ if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 )
+ goto exit;
+ ret = mbedcrypto_aes_crypt_cbc( &aes_ctx, MBEDCRYPTO_AES_DECRYPT, buflen,
+ aes_iv, buf, buf );
+
+exit:
+ mbedcrypto_aes_free( &aes_ctx );
+ mbedcrypto_platform_zeroize( aes_key, keylen );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_AES_C */
+
+#endif /* MBEDCRYPTO_MD5_C && MBEDCRYPTO_CIPHER_MODE_CBC &&
+ ( MBEDCRYPTO_AES_C || MBEDCRYPTO_DES_C ) */
+
+int mbedcrypto_pem_read_buffer( mbedcrypto_pem_context *ctx, const char *header, const char *footer,
+ const unsigned char *data, const unsigned char *pwd,
+ size_t pwdlen, size_t *use_len )
+{
+ int ret, enc;
+ size_t len;
+ unsigned char *buf;
+ const unsigned char *s1, *s2, *end;
+#if defined(MBEDCRYPTO_MD5_C) && defined(MBEDCRYPTO_CIPHER_MODE_CBC) && \
+ ( defined(MBEDCRYPTO_DES_C) || defined(MBEDCRYPTO_AES_C) )
+ unsigned char pem_iv[16];
+ mbedcrypto_cipher_type_t enc_alg = MBEDCRYPTO_CIPHER_NONE;
+#else
+ ((void) pwd);
+ ((void) pwdlen);
+#endif /* MBEDCRYPTO_MD5_C && MBEDCRYPTO_CIPHER_MODE_CBC &&
+ ( MBEDCRYPTO_AES_C || MBEDCRYPTO_DES_C ) */
+
+ if( ctx == NULL )
+ return( MBEDCRYPTO_ERR_PEM_BAD_INPUT_DATA );
+
+ s1 = (unsigned char *) strstr( (const char *) data, header );
+
+ if( s1 == NULL )
+ return( MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+ s2 = (unsigned char *) strstr( (const char *) data, footer );
+
+ if( s2 == NULL || s2 <= s1 )
+ return( MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+ s1 += strlen( header );
+ if( *s1 == ' ' ) s1++;
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+ end = s2;
+ end += strlen( footer );
+ if( *end == ' ' ) end++;
+ if( *end == '\r' ) end++;
+ if( *end == '\n' ) end++;
+ *use_len = end - data;
+
+ enc = 0;
+
+ if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
+ {
+#if defined(MBEDCRYPTO_MD5_C) && defined(MBEDCRYPTO_CIPHER_MODE_CBC) && \
+ ( defined(MBEDCRYPTO_DES_C) || defined(MBEDCRYPTO_AES_C) )
+ enc++;
+
+ s1 += 22;
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( MBEDCRYPTO_ERR_PEM_INVALID_DATA );
+
+
+#if defined(MBEDCRYPTO_DES_C)
+ if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
+ {
+ enc_alg = MBEDCRYPTO_CIPHER_DES_EDE3_CBC;
+
+ s1 += 23;
+ if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 )
+ return( MBEDCRYPTO_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 16;
+ }
+ else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
+ {
+ enc_alg = MBEDCRYPTO_CIPHER_DES_CBC;
+
+ s1 += 18;
+ if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 )
+ return( MBEDCRYPTO_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 16;
+ }
+#endif /* MBEDCRYPTO_DES_C */
+
+#if defined(MBEDCRYPTO_AES_C)
+ if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
+ {
+ if( s2 - s1 < 22 )
+ return( MBEDCRYPTO_ERR_PEM_UNKNOWN_ENC_ALG );
+ else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
+ enc_alg = MBEDCRYPTO_CIPHER_AES_128_CBC;
+ else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
+ enc_alg = MBEDCRYPTO_CIPHER_AES_192_CBC;
+ else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
+ enc_alg = MBEDCRYPTO_CIPHER_AES_256_CBC;
+ else
+ return( MBEDCRYPTO_ERR_PEM_UNKNOWN_ENC_ALG );
+
+ s1 += 22;
+ if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 )
+ return( MBEDCRYPTO_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 32;
+ }
+#endif /* MBEDCRYPTO_AES_C */
+
+ if( enc_alg == MBEDCRYPTO_CIPHER_NONE )
+ return( MBEDCRYPTO_ERR_PEM_UNKNOWN_ENC_ALG );
+
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( MBEDCRYPTO_ERR_PEM_INVALID_DATA );
+#else
+ return( MBEDCRYPTO_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif /* MBEDCRYPTO_MD5_C && MBEDCRYPTO_CIPHER_MODE_CBC &&
+ ( MBEDCRYPTO_AES_C || MBEDCRYPTO_DES_C ) */
+ }
+
+ if( s1 >= s2 )
+ return( MBEDCRYPTO_ERR_PEM_INVALID_DATA );
+
+ ret = mbedcrypto_base64_decode( NULL, 0, &len, s1, s2 - s1 );
+
+ if( ret == MBEDCRYPTO_ERR_BASE64_INVALID_CHARACTER )
+ return( MBEDCRYPTO_ERR_PEM_INVALID_DATA + ret );
+
+ if( ( buf = mbedcrypto_calloc( 1, len ) ) == NULL )
+ return( MBEDCRYPTO_ERR_PEM_ALLOC_FAILED );
+
+ if( ( ret = mbedcrypto_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 )
+ {
+ mbedcrypto_platform_zeroize( buf, len );
+ mbedcrypto_free( buf );
+ return( MBEDCRYPTO_ERR_PEM_INVALID_DATA + ret );
+ }
+
+ if( enc != 0 )
+ {
+#if defined(MBEDCRYPTO_MD5_C) && defined(MBEDCRYPTO_CIPHER_MODE_CBC) && \
+ ( defined(MBEDCRYPTO_DES_C) || defined(MBEDCRYPTO_AES_C) )
+ if( pwd == NULL )
+ {
+ mbedcrypto_platform_zeroize( buf, len );
+ mbedcrypto_free( buf );
+ return( MBEDCRYPTO_ERR_PEM_PASSWORD_REQUIRED );
+ }
+
+ ret = 0;
+
+#if defined(MBEDCRYPTO_DES_C)
+ if( enc_alg == MBEDCRYPTO_CIPHER_DES_EDE3_CBC )
+ ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
+ else if( enc_alg == MBEDCRYPTO_CIPHER_DES_CBC )
+ ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
+#endif /* MBEDCRYPTO_DES_C */
+
+#if defined(MBEDCRYPTO_AES_C)
+ if( enc_alg == MBEDCRYPTO_CIPHER_AES_128_CBC )
+ ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
+ else if( enc_alg == MBEDCRYPTO_CIPHER_AES_192_CBC )
+ ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
+ else if( enc_alg == MBEDCRYPTO_CIPHER_AES_256_CBC )
+ ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
+#endif /* MBEDCRYPTO_AES_C */
+
+ if( ret != 0 )
+ {
+ mbedcrypto_free( buf );
+ return( ret );
+ }
+
+ /*
+ * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
+ * length bytes (allow 4 to be sure) in all known use cases.
+ *
+ * Use that as a heuristic to try to detect password mismatches.
+ */
+ if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
+ {
+ mbedcrypto_platform_zeroize( buf, len );
+ mbedcrypto_free( buf );
+ return( MBEDCRYPTO_ERR_PEM_PASSWORD_MISMATCH );
+ }
+#else
+ mbedcrypto_platform_zeroize( buf, len );
+ mbedcrypto_free( buf );
+ return( MBEDCRYPTO_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif /* MBEDCRYPTO_MD5_C && MBEDCRYPTO_CIPHER_MODE_CBC &&
+ ( MBEDCRYPTO_AES_C || MBEDCRYPTO_DES_C ) */
+ }
+
+ ctx->buf = buf;
+ ctx->buflen = len;
+
+ return( 0 );
+}
+
+void mbedcrypto_pem_free( mbedcrypto_pem_context *ctx )
+{
+ if( ctx->buf != NULL )
+ mbedcrypto_platform_zeroize( ctx->buf, ctx->buflen );
+ mbedcrypto_free( ctx->buf );
+ mbedcrypto_free( ctx->info );
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_pem_context ) );
+}
+#endif /* MBEDCRYPTO_PEM_PARSE_C */
+
+#if defined(MBEDCRYPTO_PEM_WRITE_C)
+int mbedcrypto_pem_write_buffer( const char *header, const char *footer,
+ const unsigned char *der_data, size_t der_len,
+ unsigned char *buf, size_t buf_len, size_t *olen )
+{
+ int ret;
+ unsigned char *encode_buf = NULL, *c, *p = buf;
+ size_t len = 0, use_len, add_len = 0;
+
+ mbedcrypto_base64_encode( NULL, 0, &use_len, der_data, der_len );
+ add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
+
+ if( use_len + add_len > buf_len )
+ {
+ *olen = use_len + add_len;
+ return( MBEDCRYPTO_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ if( use_len != 0 &&
+ ( ( encode_buf = mbedcrypto_calloc( 1, use_len ) ) == NULL ) )
+ return( MBEDCRYPTO_ERR_PEM_ALLOC_FAILED );
+
+ if( ( ret = mbedcrypto_base64_encode( encode_buf, use_len, &use_len, der_data,
+ der_len ) ) != 0 )
+ {
+ mbedcrypto_free( encode_buf );
+ return( ret );
+ }
+
+ memcpy( p, header, strlen( header ) );
+ p += strlen( header );
+ c = encode_buf;
+
+ while( use_len )
+ {
+ len = ( use_len > 64 ) ? 64 : use_len;
+ memcpy( p, c, len );
+ use_len -= len;
+ p += len;
+ c += len;
+ *p++ = '\n';
+ }
+
+ memcpy( p, footer, strlen( footer ) );
+ p += strlen( footer );
+
+ *p++ = '\0';
+ *olen = p - buf;
+
+ mbedcrypto_free( encode_buf );
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PEM_WRITE_C */
+#endif /* MBEDCRYPTO_PEM_PARSE_C || MBEDCRYPTO_PEM_WRITE_C */
diff --git a/library/pk.c b/library/pk.c
new file mode 100644
index 0000000..364ef38
--- /dev/null
+++ b/library/pk.c
@@ -0,0 +1,379 @@
+/*
+ * Public Key abstraction layer
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PK_C)
+#include "mbedcrypto/pk.h"
+#include "mbedcrypto/pk_internal.h"
+
+#include "mbedcrypto/platform_util.h"
+
+#if defined(MBEDCRYPTO_RSA_C)
+#include "mbedcrypto/rsa.h"
+#endif
+#if defined(MBEDCRYPTO_ECP_C)
+#include "mbedcrypto/ecp.h"
+#endif
+#if defined(MBEDCRYPTO_ECDSA_C)
+#include "mbedcrypto/ecdsa.h"
+#endif
+
+#include <limits.h>
+#include <stdint.h>
+
+/*
+ * Initialise a mbedcrypto_pk_context
+ */
+void mbedcrypto_pk_init( mbedcrypto_pk_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ ctx->pk_info = NULL;
+ ctx->pk_ctx = NULL;
+}
+
+/*
+ * Free (the components of) a mbedcrypto_pk_context
+ */
+void mbedcrypto_pk_free( mbedcrypto_pk_context *ctx )
+{
+ if( ctx == NULL || ctx->pk_info == NULL )
+ return;
+
+ ctx->pk_info->ctx_free_func( ctx->pk_ctx );
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_pk_context ) );
+}
+
+/*
+ * Get pk_info structure from type
+ */
+const mbedcrypto_pk_info_t * mbedcrypto_pk_info_from_type( mbedcrypto_pk_type_t pk_type )
+{
+ switch( pk_type ) {
+#if defined(MBEDCRYPTO_RSA_C)
+ case MBEDCRYPTO_PK_RSA:
+ return( &mbedcrypto_rsa_info );
+#endif
+#if defined(MBEDCRYPTO_ECP_C)
+ case MBEDCRYPTO_PK_ECKEY:
+ return( &mbedcrypto_eckey_info );
+ case MBEDCRYPTO_PK_ECKEY_DH:
+ return( &mbedcrypto_eckeydh_info );
+#endif
+#if defined(MBEDCRYPTO_ECDSA_C)
+ case MBEDCRYPTO_PK_ECDSA:
+ return( &mbedcrypto_ecdsa_info );
+#endif
+ /* MBEDCRYPTO_PK_RSA_ALT omitted on purpose */
+ default:
+ return( NULL );
+ }
+}
+
+/*
+ * Initialise context
+ */
+int mbedcrypto_pk_setup( mbedcrypto_pk_context *ctx, const mbedcrypto_pk_info_t *info )
+{
+ if( ctx == NULL || info == NULL || ctx->pk_info != NULL )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+
+ if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
+ return( MBEDCRYPTO_ERR_PK_ALLOC_FAILED );
+
+ ctx->pk_info = info;
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+/*
+ * Initialize an RSA-alt context
+ */
+int mbedcrypto_pk_setup_rsa_alt( mbedcrypto_pk_context *ctx, void * key,
+ mbedcrypto_pk_rsa_alt_decrypt_func decrypt_func,
+ mbedcrypto_pk_rsa_alt_sign_func sign_func,
+ mbedcrypto_pk_rsa_alt_key_len_func key_len_func )
+{
+ mbedcrypto_rsa_alt_context *rsa_alt;
+ const mbedcrypto_pk_info_t *info = &mbedcrypto_rsa_alt_info;
+
+ if( ctx == NULL || ctx->pk_info != NULL )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+
+ if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
+ return( MBEDCRYPTO_ERR_PK_ALLOC_FAILED );
+
+ ctx->pk_info = info;
+
+ rsa_alt = (mbedcrypto_rsa_alt_context *) ctx->pk_ctx;
+
+ rsa_alt->key = key;
+ rsa_alt->decrypt_func = decrypt_func;
+ rsa_alt->sign_func = sign_func;
+ rsa_alt->key_len_func = key_len_func;
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PK_RSA_ALT_SUPPORT */
+
+/*
+ * Tell if a PK can do the operations of the given type
+ */
+int mbedcrypto_pk_can_do( const mbedcrypto_pk_context *ctx, mbedcrypto_pk_type_t type )
+{
+ /* null or NONE context can't do anything */
+ if( ctx == NULL || ctx->pk_info == NULL )
+ return( 0 );
+
+ return( ctx->pk_info->can_do( type ) );
+}
+
+/*
+ * Helper for mbedcrypto_pk_sign and mbedcrypto_pk_verify
+ */
+static inline int pk_hashlen_helper( mbedcrypto_md_type_t md_alg, size_t *hash_len )
+{
+ const mbedcrypto_md_info_t *md_info;
+
+ if( *hash_len != 0 )
+ return( 0 );
+
+ if( ( md_info = mbedcrypto_md_info_from_type( md_alg ) ) == NULL )
+ return( -1 );
+
+ *hash_len = mbedcrypto_md_get_size( md_info );
+ return( 0 );
+}
+
+/*
+ * Verify a signature
+ */
+int mbedcrypto_pk_verify( mbedcrypto_pk_context *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len )
+{
+ if( ctx == NULL || ctx->pk_info == NULL ||
+ pk_hashlen_helper( md_alg, &hash_len ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+
+ if( ctx->pk_info->verify_func == NULL )
+ return( MBEDCRYPTO_ERR_PK_TYPE_MISMATCH );
+
+ return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
+ sig, sig_len ) );
+}
+
+/*
+ * Verify a signature with options
+ */
+int mbedcrypto_pk_verify_ext( mbedcrypto_pk_type_t type, const void *options,
+ mbedcrypto_pk_context *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len )
+{
+ if( ctx == NULL || ctx->pk_info == NULL )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+
+ if( ! mbedcrypto_pk_can_do( ctx, type ) )
+ return( MBEDCRYPTO_ERR_PK_TYPE_MISMATCH );
+
+ if( type == MBEDCRYPTO_PK_RSASSA_PSS )
+ {
+#if defined(MBEDCRYPTO_RSA_C) && defined(MBEDCRYPTO_PKCS1_V21)
+ int ret;
+ const mbedcrypto_pk_rsassa_pss_options *pss_opts;
+
+#if SIZE_MAX > UINT_MAX
+ if( md_alg == MBEDCRYPTO_MD_NONE && UINT_MAX < hash_len )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+#endif /* SIZE_MAX > UINT_MAX */
+
+ if( options == NULL )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+
+ pss_opts = (const mbedcrypto_pk_rsassa_pss_options *) options;
+
+ if( sig_len < mbedcrypto_pk_get_len( ctx ) )
+ return( MBEDCRYPTO_ERR_RSA_VERIFY_FAILED );
+
+ ret = mbedcrypto_rsa_rsassa_pss_verify_ext( mbedcrypto_pk_rsa( *ctx ),
+ NULL, NULL, MBEDCRYPTO_RSA_PUBLIC,
+ md_alg, (unsigned int) hash_len, hash,
+ pss_opts->mgf1_hash_id,
+ pss_opts->expected_salt_len,
+ sig );
+ if( ret != 0 )
+ return( ret );
+
+ if( sig_len > mbedcrypto_pk_get_len( ctx ) )
+ return( MBEDCRYPTO_ERR_PK_SIG_LEN_MISMATCH );
+
+ return( 0 );
+#else
+ return( MBEDCRYPTO_ERR_PK_FEATURE_UNAVAILABLE );
+#endif /* MBEDCRYPTO_RSA_C && MBEDCRYPTO_PKCS1_V21 */
+ }
+
+ /* General case: no options */
+ if( options != NULL )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+
+ return( mbedcrypto_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) );
+}
+
+/*
+ * Make a signature
+ */
+int mbedcrypto_pk_sign( mbedcrypto_pk_context *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ if( ctx == NULL || ctx->pk_info == NULL ||
+ pk_hashlen_helper( md_alg, &hash_len ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+
+ if( ctx->pk_info->sign_func == NULL )
+ return( MBEDCRYPTO_ERR_PK_TYPE_MISMATCH );
+
+ return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
+ sig, sig_len, f_rng, p_rng ) );
+}
+
+/*
+ * Decrypt message
+ */
+int mbedcrypto_pk_decrypt( mbedcrypto_pk_context *ctx,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen, size_t osize,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ if( ctx == NULL || ctx->pk_info == NULL )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+
+ if( ctx->pk_info->decrypt_func == NULL )
+ return( MBEDCRYPTO_ERR_PK_TYPE_MISMATCH );
+
+ return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen,
+ output, olen, osize, f_rng, p_rng ) );
+}
+
+/*
+ * Encrypt message
+ */
+int mbedcrypto_pk_encrypt( mbedcrypto_pk_context *ctx,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen, size_t osize,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ if( ctx == NULL || ctx->pk_info == NULL )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+
+ if( ctx->pk_info->encrypt_func == NULL )
+ return( MBEDCRYPTO_ERR_PK_TYPE_MISMATCH );
+
+ return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen,
+ output, olen, osize, f_rng, p_rng ) );
+}
+
+/*
+ * Check public-private key pair
+ */
+int mbedcrypto_pk_check_pair( const mbedcrypto_pk_context *pub, const mbedcrypto_pk_context *prv )
+{
+ if( pub == NULL || pub->pk_info == NULL ||
+ prv == NULL || prv->pk_info == NULL ||
+ prv->pk_info->check_pair_func == NULL )
+ {
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+ }
+
+ if( prv->pk_info->type == MBEDCRYPTO_PK_RSA_ALT )
+ {
+ if( pub->pk_info->type != MBEDCRYPTO_PK_RSA )
+ return( MBEDCRYPTO_ERR_PK_TYPE_MISMATCH );
+ }
+ else
+ {
+ if( pub->pk_info != prv->pk_info )
+ return( MBEDCRYPTO_ERR_PK_TYPE_MISMATCH );
+ }
+
+ return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) );
+}
+
+/*
+ * Get key size in bits
+ */
+size_t mbedcrypto_pk_get_bitlen( const mbedcrypto_pk_context *ctx )
+{
+ if( ctx == NULL || ctx->pk_info == NULL )
+ return( 0 );
+
+ return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) );
+}
+
+/*
+ * Export debug information
+ */
+int mbedcrypto_pk_debug( const mbedcrypto_pk_context *ctx, mbedcrypto_pk_debug_item *items )
+{
+ if( ctx == NULL || ctx->pk_info == NULL )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+
+ if( ctx->pk_info->debug_func == NULL )
+ return( MBEDCRYPTO_ERR_PK_TYPE_MISMATCH );
+
+ ctx->pk_info->debug_func( ctx->pk_ctx, items );
+ return( 0 );
+}
+
+/*
+ * Access the PK type name
+ */
+const char *mbedcrypto_pk_get_name( const mbedcrypto_pk_context *ctx )
+{
+ if( ctx == NULL || ctx->pk_info == NULL )
+ return( "invalid PK" );
+
+ return( ctx->pk_info->name );
+}
+
+/*
+ * Access the PK type
+ */
+mbedcrypto_pk_type_t mbedcrypto_pk_get_type( const mbedcrypto_pk_context *ctx )
+{
+ if( ctx == NULL || ctx->pk_info == NULL )
+ return( MBEDCRYPTO_PK_NONE );
+
+ return( ctx->pk_info->type );
+}
+
+#endif /* MBEDCRYPTO_PK_C */
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
new file mode 100644
index 0000000..987244c
--- /dev/null
+++ b/library/pk_wrap.c
@@ -0,0 +1,523 @@
+/*
+ * Public Key abstraction layer: wrapper functions
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PK_C)
+#include "mbedcrypto/pk_internal.h"
+
+/* Even if RSA not activated, for the sake of RSA-alt */
+#include "mbedcrypto/rsa.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_ECP_C)
+#include "mbedcrypto/ecp.h"
+#endif
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+#include "mbedcrypto/ecdsa.h"
+#endif
+
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+#include "mbedcrypto/platform_util.h"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#include <limits.h>
+#include <stdint.h>
+
+#if defined(MBEDCRYPTO_RSA_C)
+static int rsa_can_do( mbedcrypto_pk_type_t type )
+{
+ return( type == MBEDCRYPTO_PK_RSA ||
+ type == MBEDCRYPTO_PK_RSASSA_PSS );
+}
+
+static size_t rsa_get_bitlen( const void *ctx )
+{
+ const mbedcrypto_rsa_context * rsa = (const mbedcrypto_rsa_context *) ctx;
+ return( mbedcrypto_rsa_get_bitlen( rsa ) );
+}
+
+static int rsa_verify_wrap( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len )
+{
+ int ret;
+ mbedcrypto_rsa_context * rsa = (mbedcrypto_rsa_context *) ctx;
+ size_t rsa_len = mbedcrypto_rsa_get_len( rsa );
+
+#if SIZE_MAX > UINT_MAX
+ if( md_alg == MBEDCRYPTO_MD_NONE && UINT_MAX < hash_len )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+#endif /* SIZE_MAX > UINT_MAX */
+
+ if( sig_len < rsa_len )
+ return( MBEDCRYPTO_ERR_RSA_VERIFY_FAILED );
+
+ if( ( ret = mbedcrypto_rsa_pkcs1_verify( rsa, NULL, NULL,
+ MBEDCRYPTO_RSA_PUBLIC, md_alg,
+ (unsigned int) hash_len, hash, sig ) ) != 0 )
+ return( ret );
+
+ /* The buffer contains a valid signature followed by extra data.
+ * We have a special error code for that so that so that callers can
+ * use mbedcrypto_pk_verify() to check "Does the buffer start with a
+ * valid signature?" and not just "Does the buffer contain a valid
+ * signature?". */
+ if( sig_len > rsa_len )
+ return( MBEDCRYPTO_ERR_PK_SIG_LEN_MISMATCH );
+
+ return( 0 );
+}
+
+static int rsa_sign_wrap( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ mbedcrypto_rsa_context * rsa = (mbedcrypto_rsa_context *) ctx;
+
+#if SIZE_MAX > UINT_MAX
+ if( md_alg == MBEDCRYPTO_MD_NONE && UINT_MAX < hash_len )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+#endif /* SIZE_MAX > UINT_MAX */
+
+ *sig_len = mbedcrypto_rsa_get_len( rsa );
+
+ return( mbedcrypto_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDCRYPTO_RSA_PRIVATE,
+ md_alg, (unsigned int) hash_len, hash, sig ) );
+}
+
+static int rsa_decrypt_wrap( void *ctx,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen, size_t osize,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ mbedcrypto_rsa_context * rsa = (mbedcrypto_rsa_context *) ctx;
+
+ if( ilen != mbedcrypto_rsa_get_len( rsa ) )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ return( mbedcrypto_rsa_pkcs1_decrypt( rsa, f_rng, p_rng,
+ MBEDCRYPTO_RSA_PRIVATE, olen, input, output, osize ) );
+}
+
+static int rsa_encrypt_wrap( void *ctx,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen, size_t osize,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ mbedcrypto_rsa_context * rsa = (mbedcrypto_rsa_context *) ctx;
+ *olen = mbedcrypto_rsa_get_len( rsa );
+
+ if( *olen > osize )
+ return( MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE );
+
+ return( mbedcrypto_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDCRYPTO_RSA_PUBLIC,
+ ilen, input, output ) );
+}
+
+static int rsa_check_pair_wrap( const void *pub, const void *prv )
+{
+ return( mbedcrypto_rsa_check_pub_priv( (const mbedcrypto_rsa_context *) pub,
+ (const mbedcrypto_rsa_context *) prv ) );
+}
+
+static void *rsa_alloc_wrap( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_rsa_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_rsa_init( (mbedcrypto_rsa_context *) ctx, 0, 0 );
+
+ return( ctx );
+}
+
+static void rsa_free_wrap( void *ctx )
+{
+ mbedcrypto_rsa_free( (mbedcrypto_rsa_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static void rsa_debug( const void *ctx, mbedcrypto_pk_debug_item *items )
+{
+ items->type = MBEDCRYPTO_PK_DEBUG_MPI;
+ items->name = "rsa.N";
+ items->value = &( ((mbedcrypto_rsa_context *) ctx)->N );
+
+ items++;
+
+ items->type = MBEDCRYPTO_PK_DEBUG_MPI;
+ items->name = "rsa.E";
+ items->value = &( ((mbedcrypto_rsa_context *) ctx)->E );
+}
+
+const mbedcrypto_pk_info_t mbedcrypto_rsa_info = {
+ MBEDCRYPTO_PK_RSA,
+ "RSA",
+ rsa_get_bitlen,
+ rsa_can_do,
+ rsa_verify_wrap,
+ rsa_sign_wrap,
+ rsa_decrypt_wrap,
+ rsa_encrypt_wrap,
+ rsa_check_pair_wrap,
+ rsa_alloc_wrap,
+ rsa_free_wrap,
+ rsa_debug,
+};
+#endif /* MBEDCRYPTO_RSA_C */
+
+#if defined(MBEDCRYPTO_ECP_C)
+/*
+ * Generic EC key
+ */
+static int eckey_can_do( mbedcrypto_pk_type_t type )
+{
+ return( type == MBEDCRYPTO_PK_ECKEY ||
+ type == MBEDCRYPTO_PK_ECKEY_DH ||
+ type == MBEDCRYPTO_PK_ECDSA );
+}
+
+static size_t eckey_get_bitlen( const void *ctx )
+{
+ return( ((mbedcrypto_ecp_keypair *) ctx)->grp.pbits );
+}
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+/* Forward declarations */
+static int ecdsa_verify_wrap( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len );
+
+static int ecdsa_sign_wrap( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+static int eckey_verify_wrap( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len )
+{
+ int ret;
+ mbedcrypto_ecdsa_context ecdsa;
+
+ mbedcrypto_ecdsa_init( &ecdsa );
+
+ if( ( ret = mbedcrypto_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )
+ ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len );
+
+ mbedcrypto_ecdsa_free( &ecdsa );
+
+ return( ret );
+}
+
+static int eckey_sign_wrap( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ int ret;
+ mbedcrypto_ecdsa_context ecdsa;
+
+ mbedcrypto_ecdsa_init( &ecdsa );
+
+ if( ( ret = mbedcrypto_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )
+ ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len,
+ f_rng, p_rng );
+
+ mbedcrypto_ecdsa_free( &ecdsa );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_ECDSA_C */
+
+static int eckey_check_pair( const void *pub, const void *prv )
+{
+ return( mbedcrypto_ecp_check_pub_priv( (const mbedcrypto_ecp_keypair *) pub,
+ (const mbedcrypto_ecp_keypair *) prv ) );
+}
+
+static void *eckey_alloc_wrap( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_ecp_keypair ) );
+
+ if( ctx != NULL )
+ mbedcrypto_ecp_keypair_init( ctx );
+
+ return( ctx );
+}
+
+static void eckey_free_wrap( void *ctx )
+{
+ mbedcrypto_ecp_keypair_free( (mbedcrypto_ecp_keypair *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+static void eckey_debug( const void *ctx, mbedcrypto_pk_debug_item *items )
+{
+ items->type = MBEDCRYPTO_PK_DEBUG_ECP;
+ items->name = "eckey.Q";
+ items->value = &( ((mbedcrypto_ecp_keypair *) ctx)->Q );
+}
+
+const mbedcrypto_pk_info_t mbedcrypto_eckey_info = {
+ MBEDCRYPTO_PK_ECKEY,
+ "EC",
+ eckey_get_bitlen,
+ eckey_can_do,
+#if defined(MBEDCRYPTO_ECDSA_C)
+ eckey_verify_wrap,
+ eckey_sign_wrap,
+#else
+ NULL,
+ NULL,
+#endif
+ NULL,
+ NULL,
+ eckey_check_pair,
+ eckey_alloc_wrap,
+ eckey_free_wrap,
+ eckey_debug,
+};
+
+/*
+ * EC key restricted to ECDH
+ */
+static int eckeydh_can_do( mbedcrypto_pk_type_t type )
+{
+ return( type == MBEDCRYPTO_PK_ECKEY ||
+ type == MBEDCRYPTO_PK_ECKEY_DH );
+}
+
+const mbedcrypto_pk_info_t mbedcrypto_eckeydh_info = {
+ MBEDCRYPTO_PK_ECKEY_DH,
+ "EC_DH",
+ eckey_get_bitlen, /* Same underlying key structure */
+ eckeydh_can_do,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ eckey_check_pair,
+ eckey_alloc_wrap, /* Same underlying key structure */
+ eckey_free_wrap, /* Same underlying key structure */
+ eckey_debug, /* Same underlying key structure */
+};
+#endif /* MBEDCRYPTO_ECP_C */
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+static int ecdsa_can_do( mbedcrypto_pk_type_t type )
+{
+ return( type == MBEDCRYPTO_PK_ECDSA );
+}
+
+static int ecdsa_verify_wrap( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len )
+{
+ int ret;
+ ((void) md_alg);
+
+ ret = mbedcrypto_ecdsa_read_signature( (mbedcrypto_ecdsa_context *) ctx,
+ hash, hash_len, sig, sig_len );
+
+ if( ret == MBEDCRYPTO_ERR_ECP_SIG_LEN_MISMATCH )
+ return( MBEDCRYPTO_ERR_PK_SIG_LEN_MISMATCH );
+
+ return( ret );
+}
+
+static int ecdsa_sign_wrap( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ return( mbedcrypto_ecdsa_write_signature( (mbedcrypto_ecdsa_context *) ctx,
+ md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) );
+}
+
+static void *ecdsa_alloc_wrap( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_ecdsa_context ) );
+
+ if( ctx != NULL )
+ mbedcrypto_ecdsa_init( (mbedcrypto_ecdsa_context *) ctx );
+
+ return( ctx );
+}
+
+static void ecdsa_free_wrap( void *ctx )
+{
+ mbedcrypto_ecdsa_free( (mbedcrypto_ecdsa_context *) ctx );
+ mbedcrypto_free( ctx );
+}
+
+const mbedcrypto_pk_info_t mbedcrypto_ecdsa_info = {
+ MBEDCRYPTO_PK_ECDSA,
+ "ECDSA",
+ eckey_get_bitlen, /* Compatible key structures */
+ ecdsa_can_do,
+ ecdsa_verify_wrap,
+ ecdsa_sign_wrap,
+ NULL,
+ NULL,
+ eckey_check_pair, /* Compatible key structures */
+ ecdsa_alloc_wrap,
+ ecdsa_free_wrap,
+ eckey_debug, /* Compatible key structures */
+};
+#endif /* MBEDCRYPTO_ECDSA_C */
+
+#if defined(MBEDCRYPTO_PK_RSA_ALT_SUPPORT)
+/*
+ * Support for alternative RSA-private implementations
+ */
+
+static int rsa_alt_can_do( mbedcrypto_pk_type_t type )
+{
+ return( type == MBEDCRYPTO_PK_RSA );
+}
+
+static size_t rsa_alt_get_bitlen( const void *ctx )
+{
+ const mbedcrypto_rsa_alt_context *rsa_alt = (const mbedcrypto_rsa_alt_context *) ctx;
+
+ return( 8 * rsa_alt->key_len_func( rsa_alt->key ) );
+}
+
+static int rsa_alt_sign_wrap( void *ctx, mbedcrypto_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ mbedcrypto_rsa_alt_context *rsa_alt = (mbedcrypto_rsa_alt_context *) ctx;
+
+#if SIZE_MAX > UINT_MAX
+ if( UINT_MAX < hash_len )
+ return( MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA );
+#endif /* SIZE_MAX > UINT_MAX */
+
+ *sig_len = rsa_alt->key_len_func( rsa_alt->key );
+
+ return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDCRYPTO_RSA_PRIVATE,
+ md_alg, (unsigned int) hash_len, hash, sig ) );
+}
+
+static int rsa_alt_decrypt_wrap( void *ctx,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output, size_t *olen, size_t osize,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ mbedcrypto_rsa_alt_context *rsa_alt = (mbedcrypto_rsa_alt_context *) ctx;
+
+ ((void) f_rng);
+ ((void) p_rng);
+
+ if( ilen != rsa_alt->key_len_func( rsa_alt->key ) )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ return( rsa_alt->decrypt_func( rsa_alt->key,
+ MBEDCRYPTO_RSA_PRIVATE, olen, input, output, osize ) );
+}
+
+#if defined(MBEDCRYPTO_RSA_C)
+static int rsa_alt_check_pair( const void *pub, const void *prv )
+{
+ unsigned char sig[MBEDCRYPTO_MPI_MAX_SIZE];
+ unsigned char hash[32];
+ size_t sig_len = 0;
+ int ret;
+
+ if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) )
+ return( MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED );
+
+ memset( hash, 0x2a, sizeof( hash ) );
+
+ if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDCRYPTO_MD_NONE,
+ hash, sizeof( hash ),
+ sig, &sig_len, NULL, NULL ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( rsa_verify_wrap( (void *) pub, MBEDCRYPTO_MD_NONE,
+ hash, sizeof( hash ), sig, sig_len ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED );
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_RSA_C */
+
+static void *rsa_alt_alloc_wrap( void )
+{
+ void *ctx = mbedcrypto_calloc( 1, sizeof( mbedcrypto_rsa_alt_context ) );
+
+ if( ctx != NULL )
+ memset( ctx, 0, sizeof( mbedcrypto_rsa_alt_context ) );
+
+ return( ctx );
+}
+
+static void rsa_alt_free_wrap( void *ctx )
+{
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_rsa_alt_context ) );
+ mbedcrypto_free( ctx );
+}
+
+const mbedcrypto_pk_info_t mbedcrypto_rsa_alt_info = {
+ MBEDCRYPTO_PK_RSA_ALT,
+ "RSA-alt",
+ rsa_alt_get_bitlen,
+ rsa_alt_can_do,
+ NULL,
+ rsa_alt_sign_wrap,
+ rsa_alt_decrypt_wrap,
+ NULL,
+#if defined(MBEDCRYPTO_RSA_C)
+ rsa_alt_check_pair,
+#else
+ NULL,
+#endif
+ rsa_alt_alloc_wrap,
+ rsa_alt_free_wrap,
+ NULL,
+};
+
+#endif /* MBEDCRYPTO_PK_RSA_ALT_SUPPORT */
+
+#endif /* MBEDCRYPTO_PK_C */
diff --git a/library/pkcs12.c b/library/pkcs12.c
new file mode 100644
index 0000000..ccebd4d
--- /dev/null
+++ b/library/pkcs12.c
@@ -0,0 +1,361 @@
+/*
+ * PKCS#12 Personal Information Exchange Syntax
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The PKCS #12 Personal Information Exchange Syntax Standard v1.1
+ *
+ * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf
+ * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PKCS12_C)
+
+#include "mbedcrypto/pkcs12.h"
+#include "mbedcrypto/asn1.h"
+#include "mbedcrypto/cipher.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_ARC4_C)
+#include "mbedcrypto/arc4.h"
+#endif
+
+#if defined(MBEDCRYPTO_DES_C)
+#include "mbedcrypto/des.h"
+#endif
+
+static int pkcs12_parse_pbe_params( mbedcrypto_asn1_buf *params,
+ mbedcrypto_asn1_buf *salt, int *iterations )
+{
+ int ret;
+ unsigned char **p = ¶ms->p;
+ const unsigned char *end = params->p + params->len;
+
+ /*
+ * pkcs-12PbeParams ::= SEQUENCE {
+ * salt OCTET STRING,
+ * iterations INTEGER
+ * }
+ *
+ */
+ if( params->tag != ( MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) )
+ return( MBEDCRYPTO_ERR_PKCS12_PBE_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG );
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &salt->len, MBEDCRYPTO_ASN1_OCTET_STRING ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
+
+ salt->p = *p;
+ *p += salt->len;
+
+ if( ( ret = mbedcrypto_asn1_get_int( p, end, iterations ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
+
+ if( *p != end )
+ return( MBEDCRYPTO_ERR_PKCS12_PBE_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+#define PKCS12_MAX_PWDLEN 128
+
+static int pkcs12_pbe_derive_key_iv( mbedcrypto_asn1_buf *pbe_params, mbedcrypto_md_type_t md_type,
+ const unsigned char *pwd, size_t pwdlen,
+ unsigned char *key, size_t keylen,
+ unsigned char *iv, size_t ivlen )
+{
+ int ret, iterations = 0;
+ mbedcrypto_asn1_buf salt;
+ size_t i;
+ unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2];
+
+ if( pwdlen > PKCS12_MAX_PWDLEN )
+ return( MBEDCRYPTO_ERR_PKCS12_BAD_INPUT_DATA );
+
+ memset( &salt, 0, sizeof(mbedcrypto_asn1_buf) );
+ memset( &unipwd, 0, sizeof(unipwd) );
+
+ if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt,
+ &iterations ) ) != 0 )
+ return( ret );
+
+ for( i = 0; i < pwdlen; i++ )
+ unipwd[i * 2 + 1] = pwd[i];
+
+ if( ( ret = mbedcrypto_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2,
+ salt.p, salt.len, md_type,
+ MBEDCRYPTO_PKCS12_DERIVE_KEY, iterations ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( iv == NULL || ivlen == 0 )
+ return( 0 );
+
+ if( ( ret = mbedcrypto_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2,
+ salt.p, salt.len, md_type,
+ MBEDCRYPTO_PKCS12_DERIVE_IV, iterations ) ) != 0 )
+ {
+ return( ret );
+ }
+ return( 0 );
+}
+
+#undef PKCS12_MAX_PWDLEN
+
+int mbedcrypto_pkcs12_pbe_sha1_rc4_128( mbedcrypto_asn1_buf *pbe_params, int mode,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *data, size_t len,
+ unsigned char *output )
+{
+#if !defined(MBEDCRYPTO_ARC4_C)
+ ((void) pbe_params);
+ ((void) mode);
+ ((void) pwd);
+ ((void) pwdlen);
+ ((void) data);
+ ((void) len);
+ ((void) output);
+ return( MBEDCRYPTO_ERR_PKCS12_FEATURE_UNAVAILABLE );
+#else
+ int ret;
+ unsigned char key[16];
+ mbedcrypto_arc4_context ctx;
+ ((void) mode);
+
+ mbedcrypto_arc4_init( &ctx );
+
+ if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDCRYPTO_MD_SHA1,
+ pwd, pwdlen,
+ key, 16, NULL, 0 ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ mbedcrypto_arc4_setup( &ctx, key, 16 );
+ if( ( ret = mbedcrypto_arc4_crypt( &ctx, len, data, output ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedcrypto_platform_zeroize( key, sizeof( key ) );
+ mbedcrypto_arc4_free( &ctx );
+
+ return( ret );
+#endif /* MBEDCRYPTO_ARC4_C */
+}
+
+int mbedcrypto_pkcs12_pbe( mbedcrypto_asn1_buf *pbe_params, int mode,
+ mbedcrypto_cipher_type_t cipher_type, mbedcrypto_md_type_t md_type,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *data, size_t len,
+ unsigned char *output )
+{
+ int ret, keylen = 0;
+ unsigned char key[32];
+ unsigned char iv[16];
+ const mbedcrypto_cipher_info_t *cipher_info;
+ mbedcrypto_cipher_context_t cipher_ctx;
+ size_t olen = 0;
+
+ cipher_info = mbedcrypto_cipher_info_from_type( cipher_type );
+ if( cipher_info == NULL )
+ return( MBEDCRYPTO_ERR_PKCS12_FEATURE_UNAVAILABLE );
+
+ keylen = cipher_info->key_bitlen / 8;
+
+ if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen,
+ key, keylen,
+ iv, cipher_info->iv_size ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ mbedcrypto_cipher_init( &cipher_ctx );
+
+ if( ( ret = mbedcrypto_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedcrypto_operation_t) mode ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_cipher_reset( &cipher_ctx ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_cipher_update( &cipher_ctx, data, len,
+ output, &olen ) ) != 0 )
+ {
+ goto exit;
+ }
+
+ if( ( ret = mbedcrypto_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
+ ret = MBEDCRYPTO_ERR_PKCS12_PASSWORD_MISMATCH;
+
+exit:
+ mbedcrypto_platform_zeroize( key, sizeof( key ) );
+ mbedcrypto_platform_zeroize( iv, sizeof( iv ) );
+ mbedcrypto_cipher_free( &cipher_ctx );
+
+ return( ret );
+}
+
+static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
+ const unsigned char *filler, size_t fill_len )
+{
+ unsigned char *p = data;
+ size_t use_len;
+
+ while( data_len > 0 )
+ {
+ use_len = ( data_len > fill_len ) ? fill_len : data_len;
+ memcpy( p, filler, use_len );
+ p += use_len;
+ data_len -= use_len;
+ }
+}
+
+int mbedcrypto_pkcs12_derivation( unsigned char *data, size_t datalen,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *salt, size_t saltlen,
+ mbedcrypto_md_type_t md_type, int id, int iterations )
+{
+ int ret;
+ unsigned int j;
+
+ unsigned char diversifier[128];
+ unsigned char salt_block[128], pwd_block[128], hash_block[128];
+ unsigned char hash_output[MBEDCRYPTO_MD_MAX_SIZE];
+ unsigned char *p;
+ unsigned char c;
+
+ size_t hlen, use_len, v, i;
+
+ const mbedcrypto_md_info_t *md_info;
+ mbedcrypto_md_context_t md_ctx;
+
+ // This version only allows max of 64 bytes of password or salt
+ if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
+ return( MBEDCRYPTO_ERR_PKCS12_BAD_INPUT_DATA );
+
+ md_info = mbedcrypto_md_info_from_type( md_type );
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_PKCS12_FEATURE_UNAVAILABLE );
+
+ mbedcrypto_md_init( &md_ctx );
+
+ if( ( ret = mbedcrypto_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
+ return( ret );
+ hlen = mbedcrypto_md_get_size( md_info );
+
+ if( hlen <= 32 )
+ v = 64;
+ else
+ v = 128;
+
+ memset( diversifier, (unsigned char) id, v );
+
+ pkcs12_fill_buffer( salt_block, v, salt, saltlen );
+ pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen );
+
+ p = data;
+ while( datalen > 0 )
+ {
+ // Calculate hash( diversifier || salt_block || pwd_block )
+ if( ( ret = mbedcrypto_md_starts( &md_ctx ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_md_update( &md_ctx, diversifier, v ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_md_update( &md_ctx, salt_block, v ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_md_update( &md_ctx, pwd_block, v ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_md_finish( &md_ctx, hash_output ) ) != 0 )
+ goto exit;
+
+ // Perform remaining ( iterations - 1 ) recursive hash calculations
+ for( i = 1; i < (size_t) iterations; i++ )
+ {
+ if( ( ret = mbedcrypto_md( md_info, hash_output, hlen, hash_output ) ) != 0 )
+ goto exit;
+ }
+
+ use_len = ( datalen > hlen ) ? hlen : datalen;
+ memcpy( p, hash_output, use_len );
+ datalen -= use_len;
+ p += use_len;
+
+ if( datalen == 0 )
+ break;
+
+ // Concatenating copies of hash_output into hash_block (B)
+ pkcs12_fill_buffer( hash_block, v, hash_output, hlen );
+
+ // B += 1
+ for( i = v; i > 0; i-- )
+ if( ++hash_block[i - 1] != 0 )
+ break;
+
+ // salt_block += B
+ c = 0;
+ for( i = v; i > 0; i-- )
+ {
+ j = salt_block[i - 1] + hash_block[i - 1] + c;
+ c = (unsigned char) (j >> 8);
+ salt_block[i - 1] = j & 0xFF;
+ }
+
+ // pwd_block += B
+ c = 0;
+ for( i = v; i > 0; i-- )
+ {
+ j = pwd_block[i - 1] + hash_block[i - 1] + c;
+ c = (unsigned char) (j >> 8);
+ pwd_block[i - 1] = j & 0xFF;
+ }
+ }
+
+ ret = 0;
+
+exit:
+ mbedcrypto_platform_zeroize( salt_block, sizeof( salt_block ) );
+ mbedcrypto_platform_zeroize( pwd_block, sizeof( pwd_block ) );
+ mbedcrypto_platform_zeroize( hash_block, sizeof( hash_block ) );
+ mbedcrypto_platform_zeroize( hash_output, sizeof( hash_output ) );
+
+ mbedcrypto_md_free( &md_ctx );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_PKCS12_C */
diff --git a/library/pkcs5.c b/library/pkcs5.c
new file mode 100644
index 0000000..4467dd7
--- /dev/null
+++ b/library/pkcs5.c
@@ -0,0 +1,424 @@
+/**
+ * \file pkcs5.c
+ *
+ * \brief PKCS#5 functions
+ *
+ * \author Mathias Olsson <mathias@kompetensum.com>
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * PKCS#5 includes PBKDF2 and more
+ *
+ * http://tools.ietf.org/html/rfc2898 (Specification)
+ * http://tools.ietf.org/html/rfc6070 (Test vectors)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PKCS5_C)
+
+#include "mbedcrypto/pkcs5.h"
+
+#if defined(MBEDCRYPTO_ASN1_PARSE_C)
+#include "mbedcrypto/asn1.h"
+#include "mbedcrypto/cipher.h"
+#include "mbedcrypto/oid.h"
+#endif /* MBEDCRYPTO_ASN1_PARSE_C */
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif
+
+#if !defined(MBEDCRYPTO_ASN1_PARSE_C)
+int mbedcrypto_pkcs5_pbes2( const mbedcrypto_asn1_buf *pbe_params, int mode,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *data, size_t datalen,
+ unsigned char *output )
+{
+ ((void) pbe_params);
+ ((void) mode);
+ ((void) pwd);
+ ((void) pwdlen);
+ ((void) data);
+ ((void) datalen);
+ ((void) output);
+ return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
+}
+#else
+static int pkcs5_parse_pbkdf2_params( const mbedcrypto_asn1_buf *params,
+ mbedcrypto_asn1_buf *salt, int *iterations,
+ int *keylen, mbedcrypto_md_type_t *md_type )
+{
+ int ret;
+ mbedcrypto_asn1_buf prf_alg_oid;
+ unsigned char *p = params->p;
+ const unsigned char *end = params->p + params->len;
+
+ if( params->tag != ( MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) )
+ return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG );
+ /*
+ * PBKDF2-params ::= SEQUENCE {
+ * salt OCTET STRING,
+ * iterationCount INTEGER,
+ * keyLength INTEGER OPTIONAL
+ * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
+ * }
+ *
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &salt->len, MBEDCRYPTO_ASN1_OCTET_STRING ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
+
+ salt->p = p;
+ p += salt->len;
+
+ if( ( ret = mbedcrypto_asn1_get_int( &p, end, iterations ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
+
+ if( p == end )
+ return( 0 );
+
+ if( ( ret = mbedcrypto_asn1_get_int( &p, end, keylen ) ) != 0 )
+ {
+ if( ret != MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG )
+ return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
+ }
+
+ if( p == end )
+ return( 0 );
+
+ if( ( ret = mbedcrypto_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
+
+ if( mbedcrypto_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 )
+ return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+ if( p != end )
+ return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+int mbedcrypto_pkcs5_pbes2( const mbedcrypto_asn1_buf *pbe_params, int mode,
+ const unsigned char *pwd, size_t pwdlen,
+ const unsigned char *data, size_t datalen,
+ unsigned char *output )
+{
+ int ret, iterations = 0, keylen = 0;
+ unsigned char *p, *end;
+ mbedcrypto_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
+ mbedcrypto_asn1_buf salt;
+ mbedcrypto_md_type_t md_type = MBEDCRYPTO_MD_SHA1;
+ unsigned char key[32], iv[32];
+ size_t olen = 0;
+ const mbedcrypto_md_info_t *md_info;
+ const mbedcrypto_cipher_info_t *cipher_info;
+ mbedcrypto_md_context_t md_ctx;
+ mbedcrypto_cipher_type_t cipher_alg;
+ mbedcrypto_cipher_context_t cipher_ctx;
+
+ p = pbe_params->p;
+ end = p + pbe_params->len;
+
+ /*
+ * PBES2-params ::= SEQUENCE {
+ * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+ * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
+ * }
+ */
+ if( pbe_params->tag != ( MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) )
+ return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG );
+
+ if( ( ret = mbedcrypto_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
+
+ // Only PBKDF2 supported at the moment
+ //
+ if( MBEDCRYPTO_OID_CMP( MBEDCRYPTO_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 )
+ return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+ if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params,
+ &salt, &iterations, &keylen,
+ &md_type ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ md_info = mbedcrypto_md_info_from_type( md_type );
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+ if( ( ret = mbedcrypto_asn1_get_alg( &p, end, &enc_scheme_oid,
+ &enc_scheme_params ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
+ }
+
+ if( mbedcrypto_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 )
+ return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+ cipher_info = mbedcrypto_cipher_info_from_type( cipher_alg );
+ if( cipher_info == NULL )
+ return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
+
+ /*
+ * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
+ * since it is optional and we don't know if it was set or not
+ */
+ keylen = cipher_info->key_bitlen / 8;
+
+ if( enc_scheme_params.tag != MBEDCRYPTO_ASN1_OCTET_STRING ||
+ enc_scheme_params.len != cipher_info->iv_size )
+ {
+ return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT );
+ }
+
+ mbedcrypto_md_init( &md_ctx );
+ mbedcrypto_cipher_init( &cipher_ctx );
+
+ memcpy( iv, enc_scheme_params.p, enc_scheme_params.len );
+
+ if( ( ret = mbedcrypto_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len,
+ iterations, keylen, key ) ) != 0 )
+ {
+ goto exit;
+ }
+
+ if( ( ret = mbedcrypto_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedcrypto_operation_t) mode ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len,
+ data, datalen, output, &olen ) ) != 0 )
+ ret = MBEDCRYPTO_ERR_PKCS5_PASSWORD_MISMATCH;
+
+exit:
+ mbedcrypto_md_free( &md_ctx );
+ mbedcrypto_cipher_free( &cipher_ctx );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ASN1_PARSE_C */
+
+int mbedcrypto_pkcs5_pbkdf2_hmac( mbedcrypto_md_context_t *ctx, const unsigned char *password,
+ size_t plen, const unsigned char *salt, size_t slen,
+ unsigned int iteration_count,
+ uint32_t key_length, unsigned char *output )
+{
+ int ret, j;
+ unsigned int i;
+ unsigned char md1[MBEDCRYPTO_MD_MAX_SIZE];
+ unsigned char work[MBEDCRYPTO_MD_MAX_SIZE];
+ unsigned char md_size = mbedcrypto_md_get_size( ctx->md_info );
+ size_t use_len;
+ unsigned char *out_p = output;
+ unsigned char counter[4];
+
+ memset( counter, 0, 4 );
+ counter[3] = 1;
+
+ if( iteration_count > 0xFFFFFFFF )
+ return( MBEDCRYPTO_ERR_PKCS5_BAD_INPUT_DATA );
+
+ while( key_length )
+ {
+ // U1 ends up in work
+ //
+ if( ( ret = mbedcrypto_md_hmac_starts( ctx, password, plen ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_md_hmac_update( ctx, salt, slen ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_md_hmac_update( ctx, counter, 4 ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_md_hmac_finish( ctx, work ) ) != 0 )
+ return( ret );
+
+ memcpy( md1, work, md_size );
+
+ for( i = 1; i < iteration_count; i++ )
+ {
+ // U2 ends up in md1
+ //
+ if( ( ret = mbedcrypto_md_hmac_starts( ctx, password, plen ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_md_hmac_update( ctx, md1, md_size ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_md_hmac_finish( ctx, md1 ) ) != 0 )
+ return( ret );
+
+ // U1 xor U2
+ //
+ for( j = 0; j < md_size; j++ )
+ work[j] ^= md1[j];
+ }
+
+ use_len = ( key_length < md_size ) ? key_length : md_size;
+ memcpy( out_p, work, use_len );
+
+ key_length -= (uint32_t) use_len;
+ out_p += use_len;
+
+ for( i = 4; i > 0; i-- )
+ if( ++counter[i - 1] != 0 )
+ break;
+ }
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+#if !defined(MBEDCRYPTO_SHA1_C)
+int mbedcrypto_pkcs5_self_test( int verbose )
+{
+ if( verbose != 0 )
+ mbedcrypto_printf( " PBKDF2 (SHA1): skipped\n\n" );
+
+ return( 0 );
+}
+#else
+
+#define MAX_TESTS 6
+
+static const size_t plen[MAX_TESTS] =
+ { 8, 8, 8, 24, 9 };
+
+static const unsigned char password[MAX_TESTS][32] =
+{
+ "password",
+ "password",
+ "password",
+ "passwordPASSWORDpassword",
+ "pass\0word",
+};
+
+static const size_t slen[MAX_TESTS] =
+ { 4, 4, 4, 36, 5 };
+
+static const unsigned char salt[MAX_TESTS][40] =
+{
+ "salt",
+ "salt",
+ "salt",
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt",
+ "sa\0lt",
+};
+
+static const uint32_t it_cnt[MAX_TESTS] =
+ { 1, 2, 4096, 4096, 4096 };
+
+static const uint32_t key_len[MAX_TESTS] =
+ { 20, 20, 20, 25, 16 };
+
+static const unsigned char result_key[MAX_TESTS][32] =
+{
+ { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
+ 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
+ 0x2f, 0xe0, 0x37, 0xa6 },
+ { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
+ 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
+ 0xd8, 0xde, 0x89, 0x57 },
+ { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
+ 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
+ 0x65, 0xa4, 0x29, 0xc1 },
+ { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
+ 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
+ 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
+ 0x38 },
+ { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
+ 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
+};
+
+int mbedcrypto_pkcs5_self_test( int verbose )
+{
+ mbedcrypto_md_context_t sha1_ctx;
+ const mbedcrypto_md_info_t *info_sha1;
+ int ret, i;
+ unsigned char key[64];
+
+ mbedcrypto_md_init( &sha1_ctx );
+
+ info_sha1 = mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_SHA1 );
+ if( info_sha1 == NULL )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ if( ( ret = mbedcrypto_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ for( i = 0; i < MAX_TESTS; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " PBKDF2 (SHA1) #%d: ", i );
+
+ ret = mbedcrypto_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i],
+ slen[i], it_cnt[i], key_len[i], key );
+ if( ret != 0 ||
+ memcmp( result_key[i], key, key_len[i] ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+exit:
+ mbedcrypto_md_free( &sha1_ctx );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_SHA1_C */
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_PKCS5_C */
diff --git a/library/pkparse.c b/library/pkparse.c
new file mode 100644
index 0000000..76d83ab
--- /dev/null
+++ b/library/pkparse.c
@@ -0,0 +1,1448 @@
+/*
+ * Public Key layer for parsing key files and structures
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PK_PARSE_C)
+
+#include "mbedcrypto/pk.h"
+#include "mbedcrypto/asn1.h"
+#include "mbedcrypto/oid.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_RSA_C)
+#include "mbedcrypto/rsa.h"
+#endif
+#if defined(MBEDCRYPTO_ECP_C)
+#include "mbedcrypto/ecp.h"
+#endif
+#if defined(MBEDCRYPTO_ECDSA_C)
+#include "mbedcrypto/ecdsa.h"
+#endif
+#if defined(MBEDCRYPTO_PEM_PARSE_C)
+#include "mbedcrypto/pem.h"
+#endif
+#if defined(MBEDCRYPTO_PKCS5_C)
+#include "mbedcrypto/pkcs5.h"
+#endif
+#if defined(MBEDCRYPTO_PKCS12_C)
+#include "mbedcrypto/pkcs12.h"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#if defined(MBEDCRYPTO_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ *
+ * The file is expected to contain either PEM or DER encoded data.
+ * A terminating null byte is always appended. It is included in the announced
+ * length only if the data looks like it is PEM encoded.
+ */
+int mbedcrypto_pk_load_file( const char *path, unsigned char **buf, size_t *n )
+{
+ FILE *f;
+ long size;
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( MBEDCRYPTO_ERR_PK_FILE_IO_ERROR );
+
+ fseek( f, 0, SEEK_END );
+ if( ( size = ftell( f ) ) == -1 )
+ {
+ fclose( f );
+ return( MBEDCRYPTO_ERR_PK_FILE_IO_ERROR );
+ }
+ fseek( f, 0, SEEK_SET );
+
+ *n = (size_t) size;
+
+ if( *n + 1 == 0 ||
+ ( *buf = mbedcrypto_calloc( 1, *n + 1 ) ) == NULL )
+ {
+ fclose( f );
+ return( MBEDCRYPTO_ERR_PK_ALLOC_FAILED );
+ }
+
+ if( fread( *buf, 1, *n, f ) != *n )
+ {
+ fclose( f );
+
+ mbedcrypto_platform_zeroize( *buf, *n );
+ mbedcrypto_free( *buf );
+
+ return( MBEDCRYPTO_ERR_PK_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+
+ (*buf)[*n] = '\0';
+
+ if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
+ ++*n;
+
+ return( 0 );
+}
+
+/*
+ * Load and parse a private key
+ */
+int mbedcrypto_pk_parse_keyfile( mbedcrypto_pk_context *ctx,
+ const char *path, const char *pwd )
+{
+ int ret;
+ size_t n;
+ unsigned char *buf;
+
+ if( ( ret = mbedcrypto_pk_load_file( path, &buf, &n ) ) != 0 )
+ return( ret );
+
+ if( pwd == NULL )
+ ret = mbedcrypto_pk_parse_key( ctx, buf, n, NULL, 0 );
+ else
+ ret = mbedcrypto_pk_parse_key( ctx, buf, n,
+ (const unsigned char *) pwd, strlen( pwd ) );
+
+ mbedcrypto_platform_zeroize( buf, n );
+ mbedcrypto_free( buf );
+
+ return( ret );
+}
+
+/*
+ * Load and parse a public key
+ */
+int mbedcrypto_pk_parse_public_keyfile( mbedcrypto_pk_context *ctx, const char *path )
+{
+ int ret;
+ size_t n;
+ unsigned char *buf;
+
+ if( ( ret = mbedcrypto_pk_load_file( path, &buf, &n ) ) != 0 )
+ return( ret );
+
+ ret = mbedcrypto_pk_parse_public_key( ctx, buf, n );
+
+ mbedcrypto_platform_zeroize( buf, n );
+ mbedcrypto_free( buf );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_FS_IO */
+
+#if defined(MBEDCRYPTO_ECP_C)
+/* Minimally parse an ECParameters buffer to and mbedcrypto_asn1_buf
+ *
+ * ECParameters ::= CHOICE {
+ * namedCurve OBJECT IDENTIFIER
+ * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
+ * -- implicitCurve NULL
+ * }
+ */
+static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
+ mbedcrypto_asn1_buf *params )
+{
+ int ret;
+
+ if ( end - *p < 1 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+
+ /* Tag may be either OID or SEQUENCE */
+ params->tag = **p;
+ if( params->tag != MBEDCRYPTO_ASN1_OID
+#if defined(MBEDCRYPTO_PK_PARSE_EC_EXTENDED)
+ && params->tag != ( MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE )
+#endif
+ )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG );
+ }
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ params->p = *p;
+ *p += params->len;
+
+ if( *p != end )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_PK_PARSE_EC_EXTENDED)
+/*
+ * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
+ * WARNING: the resulting group should only be used with
+ * pk_group_id_from_specified(), since its base point may not be set correctly
+ * if it was encoded compressed.
+ *
+ * SpecifiedECDomain ::= SEQUENCE {
+ * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
+ * fieldID FieldID {{FieldTypes}},
+ * curve Curve,
+ * base ECPoint,
+ * order INTEGER,
+ * cofactor INTEGER OPTIONAL,
+ * hash HashAlgorithm OPTIONAL,
+ * ...
+ * }
+ *
+ * We only support prime-field as field type, and ignore hash and cofactor.
+ */
+static int pk_group_from_specified( const mbedcrypto_asn1_buf *params, mbedcrypto_ecp_group *grp )
+{
+ int ret;
+ unsigned char *p = params->p;
+ const unsigned char * const end = params->p + params->len;
+ const unsigned char *end_field, *end_curve;
+ size_t len;
+ int ver;
+
+ /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
+ if( ( ret = mbedcrypto_asn1_get_int( &p, end, &ver ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ if( ver < 1 || ver > 3 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT );
+
+ /*
+ * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
+ * fieldType FIELD-ID.&id({IOSet}),
+ * parameters FIELD-ID.&Type({IOSet}{@fieldType})
+ * }
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ return( ret );
+
+ end_field = p + len;
+
+ /*
+ * FIELD-ID ::= TYPE-IDENTIFIER
+ * FieldTypes FIELD-ID ::= {
+ * { Prime-p IDENTIFIED BY prime-field } |
+ * { Characteristic-two IDENTIFIED BY characteristic-two-field }
+ * }
+ * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end_field, &len, MBEDCRYPTO_ASN1_OID ) ) != 0 )
+ return( ret );
+
+ if( len != MBEDCRYPTO_OID_SIZE( MBEDCRYPTO_OID_ANSI_X9_62_PRIME_FIELD ) ||
+ memcmp( p, MBEDCRYPTO_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_FEATURE_UNAVAILABLE );
+ }
+
+ p += len;
+
+ /* Prime-p ::= INTEGER -- Field of size p. */
+ if( ( ret = mbedcrypto_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ grp->pbits = mbedcrypto_mpi_bitlen( &grp->P );
+
+ if( p != end_field )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ /*
+ * Curve ::= SEQUENCE {
+ * a FieldElement,
+ * b FieldElement,
+ * seed BIT STRING OPTIONAL
+ * -- Shall be present if used in SpecifiedECDomain
+ * -- with version equal to ecdpVer2 or ecdpVer3
+ * }
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ return( ret );
+
+ end_curve = p + len;
+
+ /*
+ * FieldElement ::= OCTET STRING
+ * containing an integer in the case of a prime field
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end_curve, &len, MBEDCRYPTO_ASN1_OCTET_STRING ) ) != 0 ||
+ ( ret = mbedcrypto_mpi_read_binary( &grp->A, p, len ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ p += len;
+
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end_curve, &len, MBEDCRYPTO_ASN1_OCTET_STRING ) ) != 0 ||
+ ( ret = mbedcrypto_mpi_read_binary( &grp->B, p, len ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ p += len;
+
+ /* Ignore seed BIT STRING OPTIONAL */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end_curve, &len, MBEDCRYPTO_ASN1_BIT_STRING ) ) == 0 )
+ p += len;
+
+ if( p != end_curve )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ /*
+ * ECPoint ::= OCTET STRING
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len, MBEDCRYPTO_ASN1_OCTET_STRING ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ if( ( ret = mbedcrypto_ecp_point_read_binary( grp, &grp->G,
+ ( const unsigned char *) p, len ) ) != 0 )
+ {
+ /*
+ * If we can't read the point because it's compressed, cheat by
+ * reading only the X coordinate and the parity bit of Y.
+ */
+ if( ret != MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE ||
+ ( p[0] != 0x02 && p[0] != 0x03 ) ||
+ len != mbedcrypto_mpi_size( &grp->P ) + 1 ||
+ mbedcrypto_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 ||
+ mbedcrypto_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 ||
+ mbedcrypto_mpi_lset( &grp->G.Z, 1 ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT );
+ }
+ }
+
+ p += len;
+
+ /*
+ * order INTEGER
+ */
+ if( ( ret = mbedcrypto_asn1_get_mpi( &p, end, &grp->N ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ grp->nbits = mbedcrypto_mpi_bitlen( &grp->N );
+
+ /*
+ * Allow optional elements by purposefully not enforcing p == end here.
+ */
+
+ return( 0 );
+}
+
+/*
+ * Find the group id associated with an (almost filled) group as generated by
+ * pk_group_from_specified(), or return an error if unknown.
+ */
+static int pk_group_id_from_group( const mbedcrypto_ecp_group *grp, mbedcrypto_ecp_group_id *grp_id )
+{
+ int ret = 0;
+ mbedcrypto_ecp_group ref;
+ const mbedcrypto_ecp_group_id *id;
+
+ mbedcrypto_ecp_group_init( &ref );
+
+ for( id = mbedcrypto_ecp_grp_id_list(); *id != MBEDCRYPTO_ECP_DP_NONE; id++ )
+ {
+ /* Load the group associated to that id */
+ mbedcrypto_ecp_group_free( &ref );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecp_group_load( &ref, *id ) );
+
+ /* Compare to the group we were given, starting with easy tests */
+ if( grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
+ mbedcrypto_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 &&
+ mbedcrypto_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 &&
+ mbedcrypto_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 &&
+ mbedcrypto_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 &&
+ mbedcrypto_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 &&
+ mbedcrypto_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 &&
+ /* For Y we may only know the parity bit, so compare only that */
+ mbedcrypto_mpi_get_bit( &grp->G.Y, 0 ) == mbedcrypto_mpi_get_bit( &ref.G.Y, 0 ) )
+ {
+ break;
+ }
+
+ }
+
+cleanup:
+ mbedcrypto_ecp_group_free( &ref );
+
+ *grp_id = *id;
+
+ if( ret == 0 && *id == MBEDCRYPTO_ECP_DP_NONE )
+ ret = MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE;
+
+ return( ret );
+}
+
+/*
+ * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
+ */
+static int pk_group_id_from_specified( const mbedcrypto_asn1_buf *params,
+ mbedcrypto_ecp_group_id *grp_id )
+{
+ int ret;
+ mbedcrypto_ecp_group grp;
+
+ mbedcrypto_ecp_group_init( &grp );
+
+ if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 )
+ goto cleanup;
+
+ ret = pk_group_id_from_group( &grp, grp_id );
+
+cleanup:
+ mbedcrypto_ecp_group_free( &grp );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_PK_PARSE_EC_EXTENDED */
+
+/*
+ * Use EC parameters to initialise an EC group
+ *
+ * ECParameters ::= CHOICE {
+ * namedCurve OBJECT IDENTIFIER
+ * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
+ * -- implicitCurve NULL
+ */
+static int pk_use_ecparams( const mbedcrypto_asn1_buf *params, mbedcrypto_ecp_group *grp )
+{
+ int ret;
+ mbedcrypto_ecp_group_id grp_id;
+
+ if( params->tag == MBEDCRYPTO_ASN1_OID )
+ {
+ if( mbedcrypto_oid_get_ec_grp( params, &grp_id ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_UNKNOWN_NAMED_CURVE );
+ }
+ else
+ {
+#if defined(MBEDCRYPTO_PK_PARSE_EC_EXTENDED)
+ if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 )
+ return( ret );
+#else
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT );
+#endif
+ }
+
+ /*
+ * grp may already be initilialized; if so, make sure IDs match
+ */
+ if( grp->id != MBEDCRYPTO_ECP_DP_NONE && grp->id != grp_id )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT );
+
+ if( ( ret = mbedcrypto_ecp_group_load( grp, grp_id ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+}
+
+/*
+ * EC public key is an EC point
+ *
+ * The caller is responsible for clearing the structure upon failure if
+ * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
+ * return code of mbedcrypto_ecp_point_read_binary() and leave p in a usable state.
+ */
+static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
+ mbedcrypto_ecp_keypair *key )
+{
+ int ret;
+
+ if( ( ret = mbedcrypto_ecp_point_read_binary( &key->grp, &key->Q,
+ (const unsigned char *) *p, end - *p ) ) == 0 )
+ {
+ ret = mbedcrypto_ecp_check_pubkey( &key->grp, &key->Q );
+ }
+
+ /*
+ * We know mbedcrypto_ecp_point_read_binary consumed all bytes or failed
+ */
+ *p = (unsigned char *) end;
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_ECP_C */
+
+#if defined(MBEDCRYPTO_RSA_C)
+/*
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ */
+static int pk_get_rsapubkey( unsigned char **p,
+ const unsigned char *end,
+ mbedcrypto_rsa_context *rsa )
+{
+ int ret;
+ size_t len;
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY + ret );
+
+ if( *p + len != end )
+ return( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ /* Import N */
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &len, MBEDCRYPTO_ASN1_INTEGER ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY + ret );
+
+ if( ( ret = mbedcrypto_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0 ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY );
+
+ *p += len;
+
+ /* Import E */
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &len, MBEDCRYPTO_ASN1_INTEGER ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY + ret );
+
+ if( ( ret = mbedcrypto_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
+ NULL, 0, *p, len ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY );
+
+ *p += len;
+
+ if( mbedcrypto_rsa_complete( rsa ) != 0 ||
+ mbedcrypto_rsa_check_pubkey( rsa ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY );
+ }
+
+ if( *p != end )
+ return( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_RSA_C */
+
+/* Get a PK algorithm identifier
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ */
+static int pk_get_pk_alg( unsigned char **p,
+ const unsigned char *end,
+ mbedcrypto_pk_type_t *pk_alg, mbedcrypto_asn1_buf *params )
+{
+ int ret;
+ mbedcrypto_asn1_buf alg_oid;
+
+ memset( params, 0, sizeof(mbedcrypto_asn1_buf) );
+
+ if( ( ret = mbedcrypto_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_INVALID_ALG + ret );
+
+ if( mbedcrypto_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_UNKNOWN_PK_ALG );
+
+ /*
+ * No parameters with RSA (only for EC)
+ */
+ if( *pk_alg == MBEDCRYPTO_PK_RSA &&
+ ( ( params->tag != MBEDCRYPTO_ASN1_NULL && params->tag != 0 ) ||
+ params->len != 0 ) )
+ {
+ return( MBEDCRYPTO_ERR_PK_INVALID_ALG );
+ }
+
+ return( 0 );
+}
+
+/*
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ */
+int mbedcrypto_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
+ mbedcrypto_pk_context *pk )
+{
+ int ret;
+ size_t len;
+ mbedcrypto_asn1_buf alg_params;
+ mbedcrypto_pk_type_t pk_alg = MBEDCRYPTO_PK_NONE;
+ const mbedcrypto_pk_info_t *pk_info;
+
+ if( ( ret = mbedcrypto_asn1_get_tag( p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ end = *p + len;
+
+ if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY + ret );
+
+ if( *p + len != end )
+ return( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ if( ( pk_info = mbedcrypto_pk_info_from_type( pk_alg ) ) == NULL )
+ return( MBEDCRYPTO_ERR_PK_UNKNOWN_PK_ALG );
+
+ if( ( ret = mbedcrypto_pk_setup( pk, pk_info ) ) != 0 )
+ return( ret );
+
+#if defined(MBEDCRYPTO_RSA_C)
+ if( pk_alg == MBEDCRYPTO_PK_RSA )
+ {
+ ret = pk_get_rsapubkey( p, end, mbedcrypto_pk_rsa( *pk ) );
+ } else
+#endif /* MBEDCRYPTO_RSA_C */
+#if defined(MBEDCRYPTO_ECP_C)
+ if( pk_alg == MBEDCRYPTO_PK_ECKEY_DH || pk_alg == MBEDCRYPTO_PK_ECKEY )
+ {
+ ret = pk_use_ecparams( &alg_params, &mbedcrypto_pk_ec( *pk )->grp );
+ if( ret == 0 )
+ ret = pk_get_ecpubkey( p, end, mbedcrypto_pk_ec( *pk ) );
+ } else
+#endif /* MBEDCRYPTO_ECP_C */
+ ret = MBEDCRYPTO_ERR_PK_UNKNOWN_PK_ALG;
+
+ if( ret == 0 && *p != end )
+ ret = MBEDCRYPTO_ERR_PK_INVALID_PUBKEY
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH;
+
+ if( ret != 0 )
+ mbedcrypto_pk_free( pk );
+
+ return( ret );
+}
+
+#if defined(MBEDCRYPTO_RSA_C)
+/*
+ * Parse a PKCS#1 encoded private RSA key
+ */
+static int pk_parse_key_pkcs1_der( mbedcrypto_rsa_context *rsa,
+ const unsigned char *key,
+ size_t keylen )
+{
+ int ret, version;
+ size_t len;
+ unsigned char *p, *end;
+
+ mbedcrypto_mpi T;
+ mbedcrypto_mpi_init( &T );
+
+ p = (unsigned char *) key;
+ end = p + keylen;
+
+ /*
+ * This function parses the RSAPrivateKey (PKCS#1)
+ *
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ end = p + len;
+
+ if( ( ret = mbedcrypto_asn1_get_int( &p, end, &version ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ if( version != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_VERSION );
+ }
+
+ /* Import N */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_INTEGER ) ) != 0 ||
+ ( ret = mbedcrypto_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0 ) ) != 0 )
+ goto cleanup;
+ p += len;
+
+ /* Import E */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_INTEGER ) ) != 0 ||
+ ( ret = mbedcrypto_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
+ NULL, 0, p, len ) ) != 0 )
+ goto cleanup;
+ p += len;
+
+ /* Import D */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_INTEGER ) ) != 0 ||
+ ( ret = mbedcrypto_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
+ p, len, NULL, 0 ) ) != 0 )
+ goto cleanup;
+ p += len;
+
+ /* Import P */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_INTEGER ) ) != 0 ||
+ ( ret = mbedcrypto_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0,
+ NULL, 0, NULL, 0 ) ) != 0 )
+ goto cleanup;
+ p += len;
+
+ /* Import Q */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_INTEGER ) ) != 0 ||
+ ( ret = mbedcrypto_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len,
+ NULL, 0, NULL, 0 ) ) != 0 )
+ goto cleanup;
+ p += len;
+
+ /* Complete the RSA private key */
+ if( ( ret = mbedcrypto_rsa_complete( rsa ) ) != 0 )
+ goto cleanup;
+
+ /* Check optional parameters */
+ if( ( ret = mbedcrypto_asn1_get_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_get_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_get_mpi( &p, end, &T ) ) != 0 )
+ goto cleanup;
+
+ if( p != end )
+ {
+ ret = MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH ;
+ }
+
+cleanup:
+
+ mbedcrypto_mpi_free( &T );
+
+ if( ret != 0 )
+ {
+ /* Wrap error code if it's coming from a lower level */
+ if( ( ret & 0xff80 ) == 0 )
+ ret = MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret;
+ else
+ ret = MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT;
+
+ mbedcrypto_rsa_free( rsa );
+ }
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_RSA_C */
+
+#if defined(MBEDCRYPTO_ECP_C)
+/*
+ * Parse a SEC1 encoded private EC key
+ */
+static int pk_parse_key_sec1_der( mbedcrypto_ecp_keypair *eck,
+ const unsigned char *key,
+ size_t keylen )
+{
+ int ret;
+ int version, pubkey_done;
+ size_t len;
+ mbedcrypto_asn1_buf params;
+ unsigned char *p = (unsigned char *) key;
+ unsigned char *end = p + keylen;
+ unsigned char *end2;
+
+ /*
+ * RFC 5915, or SEC1 Appendix C.4
+ *
+ * ECPrivateKey ::= SEQUENCE {
+ * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ * privateKey OCTET STRING,
+ * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+ * publicKey [1] BIT STRING OPTIONAL
+ * }
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ end = p + len;
+
+ if( ( ret = mbedcrypto_asn1_get_int( &p, end, &version ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ if( version != 1 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_VERSION );
+
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len, MBEDCRYPTO_ASN1_OCTET_STRING ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ if( ( ret = mbedcrypto_mpi_read_binary( &eck->d, p, len ) ) != 0 )
+ {
+ mbedcrypto_ecp_keypair_free( eck );
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ p += len;
+
+ pubkey_done = 0;
+ if( p != end )
+ {
+ /*
+ * Is 'parameters' present?
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_CONTEXT_SPECIFIC | MBEDCRYPTO_ASN1_CONSTRUCTED | 0 ) ) == 0 )
+ {
+ if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 ||
+ ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 )
+ {
+ mbedcrypto_ecp_keypair_free( eck );
+ return( ret );
+ }
+ }
+ else if( ret != MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG )
+ {
+ mbedcrypto_ecp_keypair_free( eck );
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+ }
+
+ if( p != end )
+ {
+ /*
+ * Is 'publickey' present? If not, or if we can't read it (eg because it
+ * is compressed), create it from the private key.
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_CONTEXT_SPECIFIC | MBEDCRYPTO_ASN1_CONSTRUCTED | 1 ) ) == 0 )
+ {
+ end2 = p + len;
+
+ if( ( ret = mbedcrypto_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ if( p + len != end2 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
+
+ if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 )
+ pubkey_done = 1;
+ else
+ {
+ /*
+ * The only acceptable failure mode of pk_get_ecpubkey() above
+ * is if the point format is not recognized.
+ */
+ if( ret != MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT );
+ }
+ }
+ else if( ret != MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG )
+ {
+ mbedcrypto_ecp_keypair_free( eck );
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+ }
+
+ if( ! pubkey_done &&
+ ( ret = mbedcrypto_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G,
+ NULL, NULL ) ) != 0 )
+ {
+ mbedcrypto_ecp_keypair_free( eck );
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ if( ( ret = mbedcrypto_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
+ {
+ mbedcrypto_ecp_keypair_free( eck );
+ return( ret );
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_ECP_C */
+
+/*
+ * Parse an unencrypted PKCS#8 encoded private key
+ *
+ * Notes:
+ *
+ * - This function does not own the key buffer. It is the
+ * responsibility of the caller to take care of zeroizing
+ * and freeing it after use.
+ *
+ * - The function is responsible for freeing the provided
+ * PK context on failure.
+ *
+ */
+static int pk_parse_key_pkcs8_unencrypted_der(
+ mbedcrypto_pk_context *pk,
+ const unsigned char* key,
+ size_t keylen )
+{
+ int ret, version;
+ size_t len;
+ mbedcrypto_asn1_buf params;
+ unsigned char *p = (unsigned char *) key;
+ unsigned char *end = p + keylen;
+ mbedcrypto_pk_type_t pk_alg = MBEDCRYPTO_PK_NONE;
+ const mbedcrypto_pk_info_t *pk_info;
+
+ /*
+ * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
+ *
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes [0] IMPLICIT Attributes OPTIONAL }
+ *
+ * Version ::= INTEGER
+ * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+ * PrivateKey ::= OCTET STRING
+ *
+ * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
+ */
+
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ end = p + len;
+
+ if( ( ret = mbedcrypto_asn1_get_int( &p, end, &version ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ if( version != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_VERSION + ret );
+
+ if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len, MBEDCRYPTO_ASN1_OCTET_STRING ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ if( len < 1 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT +
+ MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA );
+
+ if( ( pk_info = mbedcrypto_pk_info_from_type( pk_alg ) ) == NULL )
+ return( MBEDCRYPTO_ERR_PK_UNKNOWN_PK_ALG );
+
+ if( ( ret = mbedcrypto_pk_setup( pk, pk_info ) ) != 0 )
+ return( ret );
+
+#if defined(MBEDCRYPTO_RSA_C)
+ if( pk_alg == MBEDCRYPTO_PK_RSA )
+ {
+ if( ( ret = pk_parse_key_pkcs1_der( mbedcrypto_pk_rsa( *pk ), p, len ) ) != 0 )
+ {
+ mbedcrypto_pk_free( pk );
+ return( ret );
+ }
+ } else
+#endif /* MBEDCRYPTO_RSA_C */
+#if defined(MBEDCRYPTO_ECP_C)
+ if( pk_alg == MBEDCRYPTO_PK_ECKEY || pk_alg == MBEDCRYPTO_PK_ECKEY_DH )
+ {
+ if( ( ret = pk_use_ecparams( ¶ms, &mbedcrypto_pk_ec( *pk )->grp ) ) != 0 ||
+ ( ret = pk_parse_key_sec1_der( mbedcrypto_pk_ec( *pk ), p, len ) ) != 0 )
+ {
+ mbedcrypto_pk_free( pk );
+ return( ret );
+ }
+ } else
+#endif /* MBEDCRYPTO_ECP_C */
+ return( MBEDCRYPTO_ERR_PK_UNKNOWN_PK_ALG );
+
+ return( 0 );
+}
+
+/*
+ * Parse an encrypted PKCS#8 encoded private key
+ *
+ * To save space, the decryption happens in-place on the given key buffer.
+ * Also, while this function may modify the keybuffer, it doesn't own it,
+ * and instead it is the responsibility of the caller to zeroize and properly
+ * free it after use.
+ *
+ */
+#if defined(MBEDCRYPTO_PKCS12_C) || defined(MBEDCRYPTO_PKCS5_C)
+static int pk_parse_key_pkcs8_encrypted_der(
+ mbedcrypto_pk_context *pk,
+ unsigned char *key, size_t keylen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ int ret, decrypted = 0;
+ size_t len;
+ unsigned char *buf;
+ unsigned char *p, *end;
+ mbedcrypto_asn1_buf pbe_alg_oid, pbe_params;
+#if defined(MBEDCRYPTO_PKCS12_C)
+ mbedcrypto_cipher_type_t cipher_alg;
+ mbedcrypto_md_type_t md_alg;
+#endif
+
+ p = key;
+ end = p + keylen;
+
+ if( pwdlen == 0 )
+ return( MBEDCRYPTO_ERR_PK_PASSWORD_REQUIRED );
+
+ /*
+ * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
+ *
+ * EncryptedPrivateKeyInfo ::= SEQUENCE {
+ * encryptionAlgorithm EncryptionAlgorithmIdentifier,
+ * encryptedData EncryptedData
+ * }
+ *
+ * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * EncryptedData ::= OCTET STRING
+ *
+ * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
+ *
+ */
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len,
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+ }
+
+ end = p + len;
+
+ if( ( ret = mbedcrypto_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &len, MBEDCRYPTO_ASN1_OCTET_STRING ) ) != 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT + ret );
+
+ buf = p;
+
+ /*
+ * Decrypt EncryptedData with appropriate PBE
+ */
+#if defined(MBEDCRYPTO_PKCS12_C)
+ if( mbedcrypto_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 )
+ {
+ if( ( ret = mbedcrypto_pkcs12_pbe( &pbe_params, MBEDCRYPTO_PKCS12_PBE_DECRYPT,
+ cipher_alg, md_alg,
+ pwd, pwdlen, p, len, buf ) ) != 0 )
+ {
+ if( ret == MBEDCRYPTO_ERR_PKCS12_PASSWORD_MISMATCH )
+ return( MBEDCRYPTO_ERR_PK_PASSWORD_MISMATCH );
+
+ return( ret );
+ }
+
+ decrypted = 1;
+ }
+ else if( MBEDCRYPTO_OID_CMP( MBEDCRYPTO_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 )
+ {
+ if( ( ret = mbedcrypto_pkcs12_pbe_sha1_rc4_128( &pbe_params,
+ MBEDCRYPTO_PKCS12_PBE_DECRYPT,
+ pwd, pwdlen,
+ p, len, buf ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ // Best guess for password mismatch when using RC4. If first tag is
+ // not MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE
+ //
+ if( *buf != ( MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) )
+ return( MBEDCRYPTO_ERR_PK_PASSWORD_MISMATCH );
+
+ decrypted = 1;
+ }
+ else
+#endif /* MBEDCRYPTO_PKCS12_C */
+#if defined(MBEDCRYPTO_PKCS5_C)
+ if( MBEDCRYPTO_OID_CMP( MBEDCRYPTO_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 )
+ {
+ if( ( ret = mbedcrypto_pkcs5_pbes2( &pbe_params, MBEDCRYPTO_PKCS5_DECRYPT, pwd, pwdlen,
+ p, len, buf ) ) != 0 )
+ {
+ if( ret == MBEDCRYPTO_ERR_PKCS5_PASSWORD_MISMATCH )
+ return( MBEDCRYPTO_ERR_PK_PASSWORD_MISMATCH );
+
+ return( ret );
+ }
+
+ decrypted = 1;
+ }
+ else
+#endif /* MBEDCRYPTO_PKCS5_C */
+ {
+ ((void) pwd);
+ }
+
+ if( decrypted == 0 )
+ return( MBEDCRYPTO_ERR_PK_FEATURE_UNAVAILABLE );
+
+ return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) );
+}
+#endif /* MBEDCRYPTO_PKCS12_C || MBEDCRYPTO_PKCS5_C */
+
+/*
+ * Parse a private key
+ */
+int mbedcrypto_pk_parse_key( mbedcrypto_pk_context *pk,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ int ret;
+ const mbedcrypto_pk_info_t *pk_info;
+
+#if defined(MBEDCRYPTO_PEM_PARSE_C)
+ size_t len;
+ mbedcrypto_pem_context pem;
+
+ mbedcrypto_pem_init( &pem );
+
+#if defined(MBEDCRYPTO_RSA_C)
+ /* Avoid calling mbedcrypto_pem_read_buffer() on non-null-terminated string */
+ if( keylen == 0 || key[keylen - 1] != '\0' )
+ ret = MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+ else
+ ret = mbedcrypto_pem_read_buffer( &pem,
+ "-----BEGIN RSA PRIVATE KEY-----",
+ "-----END RSA PRIVATE KEY-----",
+ key, pwd, pwdlen, &len );
+
+ if( ret == 0 )
+ {
+ pk_info = mbedcrypto_pk_info_from_type( MBEDCRYPTO_PK_RSA );
+ if( ( ret = mbedcrypto_pk_setup( pk, pk_info ) ) != 0 ||
+ ( ret = pk_parse_key_pkcs1_der( mbedcrypto_pk_rsa( *pk ),
+ pem.buf, pem.buflen ) ) != 0 )
+ {
+ mbedcrypto_pk_free( pk );
+ }
+
+ mbedcrypto_pem_free( &pem );
+ return( ret );
+ }
+ else if( ret == MBEDCRYPTO_ERR_PEM_PASSWORD_MISMATCH )
+ return( MBEDCRYPTO_ERR_PK_PASSWORD_MISMATCH );
+ else if( ret == MBEDCRYPTO_ERR_PEM_PASSWORD_REQUIRED )
+ return( MBEDCRYPTO_ERR_PK_PASSWORD_REQUIRED );
+ else if( ret != MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+ return( ret );
+#endif /* MBEDCRYPTO_RSA_C */
+
+#if defined(MBEDCRYPTO_ECP_C)
+ /* Avoid calling mbedcrypto_pem_read_buffer() on non-null-terminated string */
+ if( keylen == 0 || key[keylen - 1] != '\0' )
+ ret = MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+ else
+ ret = mbedcrypto_pem_read_buffer( &pem,
+ "-----BEGIN EC PRIVATE KEY-----",
+ "-----END EC PRIVATE KEY-----",
+ key, pwd, pwdlen, &len );
+ if( ret == 0 )
+ {
+ pk_info = mbedcrypto_pk_info_from_type( MBEDCRYPTO_PK_ECKEY );
+
+ if( ( ret = mbedcrypto_pk_setup( pk, pk_info ) ) != 0 ||
+ ( ret = pk_parse_key_sec1_der( mbedcrypto_pk_ec( *pk ),
+ pem.buf, pem.buflen ) ) != 0 )
+ {
+ mbedcrypto_pk_free( pk );
+ }
+
+ mbedcrypto_pem_free( &pem );
+ return( ret );
+ }
+ else if( ret == MBEDCRYPTO_ERR_PEM_PASSWORD_MISMATCH )
+ return( MBEDCRYPTO_ERR_PK_PASSWORD_MISMATCH );
+ else if( ret == MBEDCRYPTO_ERR_PEM_PASSWORD_REQUIRED )
+ return( MBEDCRYPTO_ERR_PK_PASSWORD_REQUIRED );
+ else if( ret != MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+ return( ret );
+#endif /* MBEDCRYPTO_ECP_C */
+
+ /* Avoid calling mbedcrypto_pem_read_buffer() on non-null-terminated string */
+ if( keylen == 0 || key[keylen - 1] != '\0' )
+ ret = MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+ else
+ ret = mbedcrypto_pem_read_buffer( &pem,
+ "-----BEGIN PRIVATE KEY-----",
+ "-----END PRIVATE KEY-----",
+ key, NULL, 0, &len );
+ if( ret == 0 )
+ {
+ if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk,
+ pem.buf, pem.buflen ) ) != 0 )
+ {
+ mbedcrypto_pk_free( pk );
+ }
+
+ mbedcrypto_pem_free( &pem );
+ return( ret );
+ }
+ else if( ret != MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+ return( ret );
+
+#if defined(MBEDCRYPTO_PKCS12_C) || defined(MBEDCRYPTO_PKCS5_C)
+ /* Avoid calling mbedcrypto_pem_read_buffer() on non-null-terminated string */
+ if( keylen == 0 || key[keylen - 1] != '\0' )
+ ret = MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+ else
+ ret = mbedcrypto_pem_read_buffer( &pem,
+ "-----BEGIN ENCRYPTED PRIVATE KEY-----",
+ "-----END ENCRYPTED PRIVATE KEY-----",
+ key, NULL, 0, &len );
+ if( ret == 0 )
+ {
+ if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk,
+ pem.buf, pem.buflen,
+ pwd, pwdlen ) ) != 0 )
+ {
+ mbedcrypto_pk_free( pk );
+ }
+
+ mbedcrypto_pem_free( &pem );
+ return( ret );
+ }
+ else if( ret != MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+ return( ret );
+#endif /* MBEDCRYPTO_PKCS12_C || MBEDCRYPTO_PKCS5_C */
+#else
+ ((void) ret);
+ ((void) pwd);
+ ((void) pwdlen);
+#endif /* MBEDCRYPTO_PEM_PARSE_C */
+
+ /*
+ * At this point we only know it's not a PEM formatted key. Could be any
+ * of the known DER encoded private key formats
+ *
+ * We try the different DER format parsers to see if one passes without
+ * error
+ */
+#if defined(MBEDCRYPTO_PKCS12_C) || defined(MBEDCRYPTO_PKCS5_C)
+ {
+ unsigned char *key_copy;
+
+ if( keylen == 0 )
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT );
+
+ if( ( key_copy = mbedcrypto_calloc( 1, keylen ) ) == NULL )
+ return( MBEDCRYPTO_ERR_PK_ALLOC_FAILED );
+
+ memcpy( key_copy, key, keylen );
+
+ ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen,
+ pwd, pwdlen );
+
+ mbedcrypto_platform_zeroize( key_copy, keylen );
+ mbedcrypto_free( key_copy );
+ }
+
+ if( ret == 0 )
+ return( 0 );
+
+ mbedcrypto_pk_free( pk );
+
+ if( ret == MBEDCRYPTO_ERR_PK_PASSWORD_MISMATCH )
+ {
+ return( ret );
+ }
+#endif /* MBEDCRYPTO_PKCS12_C || MBEDCRYPTO_PKCS5_C */
+
+ if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 )
+ return( 0 );
+
+ mbedcrypto_pk_free( pk );
+
+#if defined(MBEDCRYPTO_RSA_C)
+
+ pk_info = mbedcrypto_pk_info_from_type( MBEDCRYPTO_PK_RSA );
+ if( ( ret = mbedcrypto_pk_setup( pk, pk_info ) ) != 0 ||
+ ( ret = pk_parse_key_pkcs1_der( mbedcrypto_pk_rsa( *pk ),
+ key, keylen ) ) != 0 )
+ {
+ mbedcrypto_pk_free( pk );
+ }
+ else
+ {
+ return( 0 );
+ }
+
+#endif /* MBEDCRYPTO_RSA_C */
+
+#if defined(MBEDCRYPTO_ECP_C)
+
+ pk_info = mbedcrypto_pk_info_from_type( MBEDCRYPTO_PK_ECKEY );
+ if( ( ret = mbedcrypto_pk_setup( pk, pk_info ) ) != 0 ||
+ ( ret = pk_parse_key_sec1_der( mbedcrypto_pk_ec( *pk ),
+ key, keylen ) ) != 0 )
+ {
+ mbedcrypto_pk_free( pk );
+ }
+ else
+ {
+ return( 0 );
+ }
+
+#endif /* MBEDCRYPTO_ECP_C */
+
+ return( MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT );
+}
+
+/*
+ * Parse a public key
+ */
+int mbedcrypto_pk_parse_public_key( mbedcrypto_pk_context *ctx,
+ const unsigned char *key, size_t keylen )
+{
+ int ret;
+ unsigned char *p;
+#if defined(MBEDCRYPTO_RSA_C)
+ const mbedcrypto_pk_info_t *pk_info;
+#endif
+#if defined(MBEDCRYPTO_PEM_PARSE_C)
+ size_t len;
+ mbedcrypto_pem_context pem;
+
+ mbedcrypto_pem_init( &pem );
+#if defined(MBEDCRYPTO_RSA_C)
+ /* Avoid calling mbedcrypto_pem_read_buffer() on non-null-terminated string */
+ if( keylen == 0 || key[keylen - 1] != '\0' )
+ ret = MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+ else
+ ret = mbedcrypto_pem_read_buffer( &pem,
+ "-----BEGIN RSA PUBLIC KEY-----",
+ "-----END RSA PUBLIC KEY-----",
+ key, NULL, 0, &len );
+
+ if( ret == 0 )
+ {
+ p = pem.buf;
+ if( ( pk_info = mbedcrypto_pk_info_from_type( MBEDCRYPTO_PK_RSA ) ) == NULL )
+ return( MBEDCRYPTO_ERR_PK_UNKNOWN_PK_ALG );
+
+ if( ( ret = mbedcrypto_pk_setup( ctx, pk_info ) ) != 0 )
+ return( ret );
+
+ if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedcrypto_pk_rsa( *ctx ) ) ) != 0 )
+ mbedcrypto_pk_free( ctx );
+
+ mbedcrypto_pem_free( &pem );
+ return( ret );
+ }
+ else if( ret != MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+ {
+ mbedcrypto_pem_free( &pem );
+ return( ret );
+ }
+#endif /* MBEDCRYPTO_RSA_C */
+
+ /* Avoid calling mbedcrypto_pem_read_buffer() on non-null-terminated string */
+ if( keylen == 0 || key[keylen - 1] != '\0' )
+ ret = MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+ else
+ ret = mbedcrypto_pem_read_buffer( &pem,
+ "-----BEGIN PUBLIC KEY-----",
+ "-----END PUBLIC KEY-----",
+ key, NULL, 0, &len );
+
+ if( ret == 0 )
+ {
+ /*
+ * Was PEM encoded
+ */
+ p = pem.buf;
+
+ ret = mbedcrypto_pk_parse_subpubkey( &p, p + pem.buflen, ctx );
+ mbedcrypto_pem_free( &pem );
+ return( ret );
+ }
+ else if( ret != MBEDCRYPTO_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+ {
+ mbedcrypto_pem_free( &pem );
+ return( ret );
+ }
+ mbedcrypto_pem_free( &pem );
+#endif /* MBEDCRYPTO_PEM_PARSE_C */
+
+#if defined(MBEDCRYPTO_RSA_C)
+ if( ( pk_info = mbedcrypto_pk_info_from_type( MBEDCRYPTO_PK_RSA ) ) == NULL )
+ return( MBEDCRYPTO_ERR_PK_UNKNOWN_PK_ALG );
+
+ if( ( ret = mbedcrypto_pk_setup( ctx, pk_info ) ) != 0 )
+ return( ret );
+
+ p = (unsigned char *)key;
+ ret = pk_get_rsapubkey( &p, p + keylen, mbedcrypto_pk_rsa( *ctx ) );
+ if( ret == 0 )
+ {
+ return( ret );
+ }
+ mbedcrypto_pk_free( ctx );
+ if( ret != ( MBEDCRYPTO_ERR_PK_INVALID_PUBKEY + MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG ) )
+ {
+ return( ret );
+ }
+#endif /* MBEDCRYPTO_RSA_C */
+ p = (unsigned char *) key;
+
+ ret = mbedcrypto_pk_parse_subpubkey( &p, p + keylen, ctx );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_PK_PARSE_C */
diff --git a/library/pkwrite.c b/library/pkwrite.c
new file mode 100644
index 0000000..603c89e
--- /dev/null
+++ b/library/pkwrite.c
@@ -0,0 +1,515 @@
+/*
+ * Public Key layer for writing key files and structures
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PK_WRITE_C)
+
+#include "mbedcrypto/pk.h"
+#include "mbedcrypto/asn1write.h"
+#include "mbedcrypto/oid.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_RSA_C)
+#include "mbedcrypto/rsa.h"
+#endif
+#if defined(MBEDCRYPTO_ECP_C)
+#include "mbedcrypto/ecp.h"
+#endif
+#if defined(MBEDCRYPTO_ECDSA_C)
+#include "mbedcrypto/ecdsa.h"
+#endif
+#if defined(MBEDCRYPTO_PEM_WRITE_C)
+#include "mbedcrypto/pem.h"
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C)
+/*
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ */
+static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
+ mbedcrypto_rsa_context *rsa )
+{
+ int ret;
+ size_t len = 0;
+ mbedcrypto_mpi T;
+
+ mbedcrypto_mpi_init( &T );
+
+ /* Export E */
+ if ( ( ret = mbedcrypto_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_write_mpi( p, start, &T ) ) < 0 )
+ goto end_of_export;
+ len += ret;
+
+ /* Export N */
+ if ( ( ret = mbedcrypto_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_write_mpi( p, start, &T ) ) < 0 )
+ goto end_of_export;
+ len += ret;
+
+end_of_export:
+
+ mbedcrypto_mpi_free( &T );
+ if( ret < 0 )
+ return( ret );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_CONSTRUCTED |
+ MBEDCRYPTO_ASN1_SEQUENCE ) );
+
+ return( (int) len );
+}
+#endif /* MBEDCRYPTO_RSA_C */
+
+#if defined(MBEDCRYPTO_ECP_C)
+/*
+ * EC public key is an EC point
+ */
+static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
+ mbedcrypto_ecp_keypair *ec )
+{
+ int ret;
+ size_t len = 0;
+ unsigned char buf[MBEDCRYPTO_ECP_MAX_PT_LEN];
+
+ if( ( ret = mbedcrypto_ecp_point_write_binary( &ec->grp, &ec->Q,
+ MBEDCRYPTO_ECP_PF_UNCOMPRESSED,
+ &len, buf, sizeof( buf ) ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( *p < start || (size_t)( *p - start ) < len )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ *p -= len;
+ memcpy( *p, buf, len );
+
+ return( (int) len );
+}
+
+/*
+ * ECParameters ::= CHOICE {
+ * namedCurve OBJECT IDENTIFIER
+ * }
+ */
+static int pk_write_ec_param( unsigned char **p, unsigned char *start,
+ mbedcrypto_ecp_keypair *ec )
+{
+ int ret;
+ size_t len = 0;
+ const char *oid;
+ size_t oid_len;
+
+ if( ( ret = mbedcrypto_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
+ return( ret );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_oid( p, start, oid, oid_len ) );
+
+ return( (int) len );
+}
+#endif /* MBEDCRYPTO_ECP_C */
+
+int mbedcrypto_pk_write_pubkey( unsigned char **p, unsigned char *start,
+ const mbedcrypto_pk_context *key )
+{
+ int ret;
+ size_t len = 0;
+
+#if defined(MBEDCRYPTO_RSA_C)
+ if( mbedcrypto_pk_get_type( key ) == MBEDCRYPTO_PK_RSA )
+ MBEDCRYPTO_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedcrypto_pk_rsa( *key ) ) );
+ else
+#endif
+#if defined(MBEDCRYPTO_ECP_C)
+ if( mbedcrypto_pk_get_type( key ) == MBEDCRYPTO_PK_ECKEY )
+ MBEDCRYPTO_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedcrypto_pk_ec( *key ) ) );
+ else
+#endif
+ return( MBEDCRYPTO_ERR_PK_FEATURE_UNAVAILABLE );
+
+ return( (int) len );
+}
+
+int mbedcrypto_pk_write_pubkey_der( mbedcrypto_pk_context *key, unsigned char *buf, size_t size )
+{
+ int ret;
+ unsigned char *c;
+ size_t len = 0, par_len = 0, oid_len;
+ const char *oid;
+
+ c = buf + size;
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_pk_write_pubkey( &c, buf, key ) );
+
+ if( c - buf < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+
+ /*
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ */
+ *--c = 0;
+ len += 1;
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( &c, buf, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( &c, buf, MBEDCRYPTO_ASN1_BIT_STRING ) );
+
+ if( ( ret = mbedcrypto_oid_get_oid_by_pk_alg( mbedcrypto_pk_get_type( key ),
+ &oid, &oid_len ) ) != 0 )
+ {
+ return( ret );
+ }
+
+#if defined(MBEDCRYPTO_ECP_C)
+ if( mbedcrypto_pk_get_type( key ) == MBEDCRYPTO_PK_ECKEY )
+ {
+ MBEDCRYPTO_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedcrypto_pk_ec( *key ) ) );
+ }
+#endif
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
+ par_len ) );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( &c, buf, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( &c, buf, MBEDCRYPTO_ASN1_CONSTRUCTED |
+ MBEDCRYPTO_ASN1_SEQUENCE ) );
+
+ return( (int) len );
+}
+
+int mbedcrypto_pk_write_key_der( mbedcrypto_pk_context *key, unsigned char *buf, size_t size )
+{
+ int ret;
+ unsigned char *c = buf + size;
+ size_t len = 0;
+
+#if defined(MBEDCRYPTO_RSA_C)
+ if( mbedcrypto_pk_get_type( key ) == MBEDCRYPTO_PK_RSA )
+ {
+ mbedcrypto_mpi T; /* Temporary holding the exported parameters */
+ mbedcrypto_rsa_context *rsa = mbedcrypto_pk_rsa( *key );
+
+ /*
+ * Export the parameters one after another to avoid simultaneous copies.
+ */
+
+ mbedcrypto_mpi_init( &T );
+
+ /* Export QP */
+ if( ( ret = mbedcrypto_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+ goto end_of_export;
+ len += ret;
+
+ /* Export DQ */
+ if( ( ret = mbedcrypto_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+ goto end_of_export;
+ len += ret;
+
+ /* Export DP */
+ if( ( ret = mbedcrypto_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+ goto end_of_export;
+ len += ret;
+
+ /* Export Q */
+ if ( ( ret = mbedcrypto_rsa_export( rsa, NULL, NULL,
+ &T, NULL, NULL ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+ goto end_of_export;
+ len += ret;
+
+ /* Export P */
+ if ( ( ret = mbedcrypto_rsa_export( rsa, NULL, &T,
+ NULL, NULL, NULL ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+ goto end_of_export;
+ len += ret;
+
+ /* Export D */
+ if ( ( ret = mbedcrypto_rsa_export( rsa, NULL, NULL,
+ NULL, &T, NULL ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+ goto end_of_export;
+ len += ret;
+
+ /* Export E */
+ if ( ( ret = mbedcrypto_rsa_export( rsa, NULL, NULL,
+ NULL, NULL, &T ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+ goto end_of_export;
+ len += ret;
+
+ /* Export N */
+ if ( ( ret = mbedcrypto_rsa_export( rsa, &T, NULL,
+ NULL, NULL, NULL ) ) != 0 ||
+ ( ret = mbedcrypto_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+ goto end_of_export;
+ len += ret;
+
+ end_of_export:
+
+ mbedcrypto_mpi_free( &T );
+ if( ret < 0 )
+ return( ret );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_int( &c, buf, 0 ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( &c, buf, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( &c,
+ buf, MBEDCRYPTO_ASN1_CONSTRUCTED |
+ MBEDCRYPTO_ASN1_SEQUENCE ) );
+ }
+ else
+#endif /* MBEDCRYPTO_RSA_C */
+#if defined(MBEDCRYPTO_ECP_C)
+ if( mbedcrypto_pk_get_type( key ) == MBEDCRYPTO_PK_ECKEY )
+ {
+ mbedcrypto_ecp_keypair *ec = mbedcrypto_pk_ec( *key );
+ size_t pub_len = 0, par_len = 0;
+
+ /*
+ * RFC 5915, or SEC1 Appendix C.4
+ *
+ * ECPrivateKey ::= SEQUENCE {
+ * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ * privateKey OCTET STRING,
+ * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+ * publicKey [1] BIT STRING OPTIONAL
+ * }
+ */
+
+ /* publicKey */
+ MBEDCRYPTO_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
+
+ if( c - buf < 1 )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+ *--c = 0;
+ pub_len += 1;
+
+ MBEDCRYPTO_ASN1_CHK_ADD( pub_len, mbedcrypto_asn1_write_len( &c, buf, pub_len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( pub_len, mbedcrypto_asn1_write_tag( &c, buf, MBEDCRYPTO_ASN1_BIT_STRING ) );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( pub_len, mbedcrypto_asn1_write_len( &c, buf, pub_len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( pub_len, mbedcrypto_asn1_write_tag( &c, buf,
+ MBEDCRYPTO_ASN1_CONTEXT_SPECIFIC | MBEDCRYPTO_ASN1_CONSTRUCTED | 1 ) );
+ len += pub_len;
+
+ /* parameters */
+ MBEDCRYPTO_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( par_len, mbedcrypto_asn1_write_len( &c, buf, par_len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( par_len, mbedcrypto_asn1_write_tag( &c, buf,
+ MBEDCRYPTO_ASN1_CONTEXT_SPECIFIC | MBEDCRYPTO_ASN1_CONSTRUCTED | 0 ) );
+ len += par_len;
+
+ /* privateKey: write as MPI then fix tag */
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_mpi( &c, buf, &ec->d ) );
+ *c = MBEDCRYPTO_ASN1_OCTET_STRING;
+
+ /* version */
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_int( &c, buf, 1 ) );
+
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( &c, buf, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( &c, buf, MBEDCRYPTO_ASN1_CONSTRUCTED |
+ MBEDCRYPTO_ASN1_SEQUENCE ) );
+ }
+ else
+#endif /* MBEDCRYPTO_ECP_C */
+ return( MBEDCRYPTO_ERR_PK_FEATURE_UNAVAILABLE );
+
+ return( (int) len );
+}
+
+#if defined(MBEDCRYPTO_PEM_WRITE_C)
+
+#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
+#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
+
+#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n"
+#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n"
+#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n"
+#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n"
+
+/*
+ * Max sizes of key per types. Shown as tag + len (+ content).
+ */
+
+#if defined(MBEDCRYPTO_RSA_C)
+/*
+ * RSA public keys:
+ * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3
+ * algorithm AlgorithmIdentifier, 1 + 1 (sequence)
+ * + 1 + 1 + 9 (rsa oid)
+ * + 1 + 1 (params null)
+ * subjectPublicKey BIT STRING } 1 + 3 + (1 + below)
+ * RSAPublicKey ::= SEQUENCE { 1 + 3
+ * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1
+ * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1
+ * }
+ */
+#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDCRYPTO_MPI_MAX_SIZE
+
+/*
+ * RSA private keys:
+ * RSAPrivateKey ::= SEQUENCE { 1 + 3
+ * version Version, 1 + 1 + 1
+ * modulus INTEGER, 1 + 3 + MPI_MAX + 1
+ * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1
+ * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1
+ * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
+ * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
+ * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
+ * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
+ * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported)
+ * }
+ */
+#define MPI_MAX_SIZE_2 MBEDCRYPTO_MPI_MAX_SIZE / 2 + \
+ MBEDCRYPTO_MPI_MAX_SIZE % 2
+#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDCRYPTO_MPI_MAX_SIZE \
+ + 5 * MPI_MAX_SIZE_2
+
+#else /* MBEDCRYPTO_RSA_C */
+
+#define RSA_PUB_DER_MAX_BYTES 0
+#define RSA_PRV_DER_MAX_BYTES 0
+
+#endif /* MBEDCRYPTO_RSA_C */
+
+#if defined(MBEDCRYPTO_ECP_C)
+/*
+ * EC public keys:
+ * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2
+ * algorithm AlgorithmIdentifier, 1 + 1 (sequence)
+ * + 1 + 1 + 7 (ec oid)
+ * + 1 + 1 + 9 (namedCurve oid)
+ * subjectPublicKey BIT STRING 1 + 2 + 1 [1]
+ * + 1 (point format) [1]
+ * + 2 * ECP_MAX (coords) [1]
+ * }
+ */
+#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDCRYPTO_ECP_MAX_BYTES
+
+/*
+ * EC private keys:
+ * ECPrivateKey ::= SEQUENCE { 1 + 2
+ * version INTEGER , 1 + 1 + 1
+ * privateKey OCTET STRING, 1 + 1 + ECP_MAX
+ * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9)
+ * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above
+ * }
+ */
+#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDCRYPTO_ECP_MAX_BYTES
+
+#else /* MBEDCRYPTO_ECP_C */
+
+#define ECP_PUB_DER_MAX_BYTES 0
+#define ECP_PRV_DER_MAX_BYTES 0
+
+#endif /* MBEDCRYPTO_ECP_C */
+
+#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
+ RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
+#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
+ RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES
+
+int mbedcrypto_pk_write_pubkey_pem( mbedcrypto_pk_context *key, unsigned char *buf, size_t size )
+{
+ int ret;
+ unsigned char output_buf[PUB_DER_MAX_BYTES];
+ size_t olen = 0;
+
+ if( ( ret = mbedcrypto_pk_write_pubkey_der( key, output_buf,
+ sizeof(output_buf) ) ) < 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = mbedcrypto_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
+ output_buf + sizeof(output_buf) - ret,
+ ret, buf, size, &olen ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+int mbedcrypto_pk_write_key_pem( mbedcrypto_pk_context *key, unsigned char *buf, size_t size )
+{
+ int ret;
+ unsigned char output_buf[PRV_DER_MAX_BYTES];
+ const char *begin, *end;
+ size_t olen = 0;
+
+ if( ( ret = mbedcrypto_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
+ return( ret );
+
+#if defined(MBEDCRYPTO_RSA_C)
+ if( mbedcrypto_pk_get_type( key ) == MBEDCRYPTO_PK_RSA )
+ {
+ begin = PEM_BEGIN_PRIVATE_KEY_RSA;
+ end = PEM_END_PRIVATE_KEY_RSA;
+ }
+ else
+#endif
+#if defined(MBEDCRYPTO_ECP_C)
+ if( mbedcrypto_pk_get_type( key ) == MBEDCRYPTO_PK_ECKEY )
+ {
+ begin = PEM_BEGIN_PRIVATE_KEY_EC;
+ end = PEM_END_PRIVATE_KEY_EC;
+ }
+ else
+#endif
+ return( MBEDCRYPTO_ERR_PK_FEATURE_UNAVAILABLE );
+
+ if( ( ret = mbedcrypto_pem_write_buffer( begin, end,
+ output_buf + sizeof(output_buf) - ret,
+ ret, buf, size, &olen ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PEM_WRITE_C */
+
+#endif /* MBEDCRYPTO_PK_WRITE_C */
diff --git a/library/platform.c b/library/platform.c
new file mode 100644
index 0000000..40a3099
--- /dev/null
+++ b/library/platform.c
@@ -0,0 +1,329 @@
+/*
+ * Platform abstraction layer
+ *
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+
+#include "mbedcrypto/platform.h"
+#include "mbedcrypto/platform_util.h"
+
+#if defined(MBEDCRYPTO_PLATFORM_MEMORY)
+#if !defined(MBEDCRYPTO_PLATFORM_STD_CALLOC)
+static void *platform_calloc_uninit( size_t n, size_t size )
+{
+ ((void) n);
+ ((void) size);
+ return( NULL );
+}
+
+#define MBEDCRYPTO_PLATFORM_STD_CALLOC platform_calloc_uninit
+#endif /* !MBEDCRYPTO_PLATFORM_STD_CALLOC */
+
+#if !defined(MBEDCRYPTO_PLATFORM_STD_FREE)
+static void platform_free_uninit( void *ptr )
+{
+ ((void) ptr);
+}
+
+#define MBEDCRYPTO_PLATFORM_STD_FREE platform_free_uninit
+#endif /* !MBEDCRYPTO_PLATFORM_STD_FREE */
+
+void * (*mbedcrypto_calloc)( size_t, size_t ) = MBEDCRYPTO_PLATFORM_STD_CALLOC;
+void (*mbedcrypto_free)( void * ) = MBEDCRYPTO_PLATFORM_STD_FREE;
+
+int mbedcrypto_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
+ void (*free_func)( void * ) )
+{
+ mbedcrypto_calloc = calloc_func;
+ mbedcrypto_free = free_func;
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PLATFORM_MEMORY */
+
+#if defined(_WIN32)
+#include <stdarg.h>
+int mbedcrypto_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... )
+{
+ int ret;
+ va_list argp;
+
+ /* Avoid calling the invalid parameter handler by checking ourselves */
+ if( s == NULL || n == 0 || fmt == NULL )
+ return( -1 );
+
+ va_start( argp, fmt );
+#if defined(_TRUNCATE) && !defined(__MINGW32__)
+ ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp );
+#else
+ ret = _vsnprintf( s, n, fmt, argp );
+ if( ret < 0 || (size_t) ret == n )
+ {
+ s[n-1] = '\0';
+ ret = -1;
+ }
+#endif
+ va_end( argp );
+
+ return( ret );
+}
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_SNPRINTF_ALT)
+#if !defined(MBEDCRYPTO_PLATFORM_STD_SNPRINTF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_snprintf_uninit( char * s, size_t n,
+ const char * format, ... )
+{
+ ((void) s);
+ ((void) n);
+ ((void) format);
+ return( 0 );
+}
+
+#define MBEDCRYPTO_PLATFORM_STD_SNPRINTF platform_snprintf_uninit
+#endif /* !MBEDCRYPTO_PLATFORM_STD_SNPRINTF */
+
+int (*mbedcrypto_snprintf)( char * s, size_t n,
+ const char * format,
+ ... ) = MBEDCRYPTO_PLATFORM_STD_SNPRINTF;
+
+int mbedcrypto_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n,
+ const char * format,
+ ... ) )
+{
+ mbedcrypto_snprintf = snprintf_func;
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PLATFORM_SNPRINTF_ALT */
+
+#if defined(MBEDCRYPTO_PLATFORM_PRINTF_ALT)
+#if !defined(MBEDCRYPTO_PLATFORM_STD_PRINTF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_printf_uninit( const char *format, ... )
+{
+ ((void) format);
+ return( 0 );
+}
+
+#define MBEDCRYPTO_PLATFORM_STD_PRINTF platform_printf_uninit
+#endif /* !MBEDCRYPTO_PLATFORM_STD_PRINTF */
+
+int (*mbedcrypto_printf)( const char *, ... ) = MBEDCRYPTO_PLATFORM_STD_PRINTF;
+
+int mbedcrypto_platform_set_printf( int (*printf_func)( const char *, ... ) )
+{
+ mbedcrypto_printf = printf_func;
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PLATFORM_PRINTF_ALT */
+
+#if defined(MBEDCRYPTO_PLATFORM_FPRINTF_ALT)
+#if !defined(MBEDCRYPTO_PLATFORM_STD_FPRINTF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_fprintf_uninit( FILE *stream, const char *format, ... )
+{
+ ((void) stream);
+ ((void) format);
+ return( 0 );
+}
+
+#define MBEDCRYPTO_PLATFORM_STD_FPRINTF platform_fprintf_uninit
+#endif /* !MBEDCRYPTO_PLATFORM_STD_FPRINTF */
+
+int (*mbedcrypto_fprintf)( FILE *, const char *, ... ) =
+ MBEDCRYPTO_PLATFORM_STD_FPRINTF;
+
+int mbedcrypto_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) )
+{
+ mbedcrypto_fprintf = fprintf_func;
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PLATFORM_FPRINTF_ALT */
+
+#if defined(MBEDCRYPTO_PLATFORM_EXIT_ALT)
+#if !defined(MBEDCRYPTO_PLATFORM_STD_EXIT)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static void platform_exit_uninit( int status )
+{
+ ((void) status);
+}
+
+#define MBEDCRYPTO_PLATFORM_STD_EXIT platform_exit_uninit
+#endif /* !MBEDCRYPTO_PLATFORM_STD_EXIT */
+
+void (*mbedcrypto_exit)( int status ) = MBEDCRYPTO_PLATFORM_STD_EXIT;
+
+int mbedcrypto_platform_set_exit( void (*exit_func)( int status ) )
+{
+ mbedcrypto_exit = exit_func;
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PLATFORM_EXIT_ALT */
+
+#if defined(MBEDCRYPTO_HAVE_TIME)
+
+#if defined(MBEDCRYPTO_PLATFORM_TIME_ALT)
+#if !defined(MBEDCRYPTO_PLATFORM_STD_TIME)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static mbedcrypto_time_t platform_time_uninit( mbedcrypto_time_t* timer )
+{
+ ((void) timer);
+ return( 0 );
+}
+
+#define MBEDCRYPTO_PLATFORM_STD_TIME platform_time_uninit
+#endif /* !MBEDCRYPTO_PLATFORM_STD_TIME */
+
+mbedcrypto_time_t (*mbedcrypto_time)( mbedcrypto_time_t* timer ) = MBEDCRYPTO_PLATFORM_STD_TIME;
+
+int mbedcrypto_platform_set_time( mbedcrypto_time_t (*time_func)( mbedcrypto_time_t* timer ) )
+{
+ mbedcrypto_time = time_func;
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PLATFORM_TIME_ALT */
+
+#endif /* MBEDCRYPTO_HAVE_TIME */
+
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+#if !defined(MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDCRYPTO_FS_IO)
+/* Default implementations for the platform independent seed functions use
+ * standard libc file functions to read from and write to a pre-defined filename
+ */
+int mbedcrypto_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len )
+{
+ FILE *file;
+ size_t n;
+
+ if( ( file = fopen( MBEDCRYPTO_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL )
+ return( -1 );
+
+ if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len )
+ {
+ fclose( file );
+ mbedcrypto_platform_zeroize( buf, buf_len );
+ return( -1 );
+ }
+
+ fclose( file );
+ return( (int)n );
+}
+
+int mbedcrypto_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len )
+{
+ FILE *file;
+ size_t n;
+
+ if( ( file = fopen( MBEDCRYPTO_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL )
+ return -1;
+
+ if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len )
+ {
+ fclose( file );
+ return -1;
+ }
+
+ fclose( file );
+ return( (int)n );
+}
+#endif /* MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS */
+
+#if defined(MBEDCRYPTO_PLATFORM_NV_SEED_ALT)
+#if !defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len )
+{
+ ((void) buf);
+ ((void) buf_len);
+ return( -1 );
+}
+
+#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit
+#endif /* !MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ */
+
+#if !defined(MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len )
+{
+ ((void) buf);
+ ((void) buf_len);
+ return( -1 );
+}
+
+#define MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit
+#endif /* !MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE */
+
+int (*mbedcrypto_nv_seed_read)( unsigned char *buf, size_t buf_len ) =
+ MBEDCRYPTO_PLATFORM_STD_NV_SEED_READ;
+int (*mbedcrypto_nv_seed_write)( unsigned char *buf, size_t buf_len ) =
+ MBEDCRYPTO_PLATFORM_STD_NV_SEED_WRITE;
+
+int mbedcrypto_platform_set_nv_seed(
+ int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ),
+ int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) )
+{
+ mbedcrypto_nv_seed_read = nv_seed_read_func;
+ mbedcrypto_nv_seed_write = nv_seed_write_func;
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PLATFORM_NV_SEED_ALT */
+#endif /* MBEDCRYPTO_ENTROPY_NV_SEED */
+
+#if !defined(MBEDCRYPTO_PLATFORM_SETUP_TEARDOWN_ALT)
+/*
+ * Placeholder platform setup that does nothing by default
+ */
+int mbedcrypto_platform_setup( mbedcrypto_platform_context *ctx )
+{
+ (void)ctx;
+
+ return( 0 );
+}
+
+/*
+ * Placeholder platform teardown that does nothing by default
+ */
+void mbedcrypto_platform_teardown( mbedcrypto_platform_context *ctx )
+{
+ (void)ctx;
+}
+#endif /* MBEDCRYPTO_PLATFORM_SETUP_TEARDOWN_ALT */
+
+#endif /* MBEDCRYPTO_PLATFORM_C */
diff --git a/library/platform_util.c b/library/platform_util.c
new file mode 100644
index 0000000..28ea881
--- /dev/null
+++ b/library/platform_util.c
@@ -0,0 +1,67 @@
+/*
+ * Common and shared functions used by multiple modules in the Mbed Crypto
+ * library.
+ *
+ * Copyright (C) 2018, Arm Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#include "mbedcrypto/platform_util.h"
+
+#include <stddef.h>
+#include <string.h>
+
+#if !defined(MBEDCRYPTO_PLATFORM_ZEROIZE_ALT)
+/*
+ * This implementation should never be optimized out by the compiler
+ *
+ * This implementation for mbedcrypto_platform_zeroize() was inspired from Colin
+ * Percival's blog article at:
+ *
+ * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
+ *
+ * It uses a volatile function pointer to the standard memset(). Because the
+ * pointer is volatile the compiler expects it to change at
+ * any time and will not optimize out the call that could potentially perform
+ * other operations on the input buffer instead of just setting it to 0.
+ * Nevertheless, as pointed out by davidtgoldblatt on Hacker News
+ * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for
+ * details), optimizations of the following form are still possible:
+ *
+ * if( memset_func != memset )
+ * memset_func( buf, 0, len );
+ *
+ * Note that it is extremely difficult to guarantee that
+ * mbedcrypto_platform_zeroize() will not be optimized out by aggressive compilers
+ * in a portable way. For this reason, Mbed Crypto also provides the configuration
+ * option MBEDCRYPTO_PLATFORM_ZEROIZE_ALT, which allows users to configure
+ * mbedcrypto_platform_zeroize() to use a suitable implementation for their
+ * platform and needs.
+ */
+static void * (* const volatile memset_func)( void *, int, size_t ) = memset;
+
+void mbedcrypto_platform_zeroize( void *buf, size_t len )
+{
+ memset_func( buf, 0, len );
+}
+#endif /* MBEDCRYPTO_PLATFORM_ZEROIZE_ALT */
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
new file mode 100644
index 0000000..4408b45
--- /dev/null
+++ b/library/psa_crypto.c
@@ -0,0 +1,3513 @@
+/*
+ * PSA crypto layer on top of Mbed Crypto crypto
+ */
+/* Copyright (C) 2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PSA_CRYPTO_C)
+/*
+ * In case MBEDCRYPTO_PSA_CRYPTO_SPM is defined the code is built for SPM (Secure
+ * Partition Manager) integration which separate the code into two parts
+ * NSPE (Non-Secure Process Environment) and SPE (Secure Process Environment).
+ * In this mode an additional header file should be included.
+ */
+#if defined(MBEDCRYPTO_PSA_CRYPTO_SPM)
+/*
+ * PSA_CRYPTO_SECURE means that this file is compiled to the SPE side.
+ * some headers will be affected by this flag.
+ */
+#define PSA_CRYPTO_SECURE 1
+#include "crypto_spe.h"
+#endif
+
+#include "psa/crypto.h"
+
+#include <stdlib.h>
+#include <string.h>
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#include "mbedcrypto/arc4.h"
+#include "mbedcrypto/asn1.h"
+#include "mbedcrypto/bignum.h"
+#include "mbedcrypto/blowfish.h"
+#include "mbedcrypto/camellia.h"
+#include "mbedcrypto/cipher.h"
+#include "mbedcrypto/ccm.h"
+#include "mbedcrypto/cmac.h"
+#include "mbedcrypto/ctr_drbg.h"
+#include "mbedcrypto/des.h"
+#include "mbedcrypto/ecp.h"
+#include "mbedcrypto/entropy.h"
+#include "mbedcrypto/error.h"
+#include "mbedcrypto/gcm.h"
+#include "mbedcrypto/md2.h"
+#include "mbedcrypto/md4.h"
+#include "mbedcrypto/md5.h"
+#include "mbedcrypto/md.h"
+#include "mbedcrypto/md_internal.h"
+#include "mbedcrypto/pk.h"
+#include "mbedcrypto/pk_internal.h"
+#include "mbedcrypto/ripemd160.h"
+#include "mbedcrypto/rsa.h"
+#include "mbedcrypto/sha1.h"
+#include "mbedcrypto/sha256.h"
+#include "mbedcrypto/sha512.h"
+#include "mbedcrypto/xtea.h"
+
+
+
+#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) )
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedcrypto_zeroize( void *v, size_t n )
+{
+ volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/* constant-time buffer comparison */
+static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n )
+{
+ size_t i;
+ unsigned char diff = 0;
+
+ for( i = 0; i < n; i++ )
+ diff |= a[i] ^ b[i];
+
+ return( diff );
+}
+
+
+
+/****************************************************************/
+/* Global data, support functions and library management */
+/****************************************************************/
+
+/* Number of key slots (plus one because 0 is not used).
+ * The value is a compile-time constant for now, for simplicity. */
+#define PSA_KEY_SLOT_COUNT 32
+
+typedef struct
+{
+ psa_key_type_t type;
+ psa_key_policy_t policy;
+ psa_key_lifetime_t lifetime;
+ union
+ {
+ struct raw_data
+ {
+ uint8_t *data;
+ size_t bytes;
+ } raw;
+#if defined(MBEDCRYPTO_RSA_C)
+ mbedcrypto_rsa_context *rsa;
+#endif /* MBEDCRYPTO_RSA_C */
+#if defined(MBEDCRYPTO_ECP_C)
+ mbedcrypto_ecp_keypair *ecp;
+#endif /* MBEDCRYPTO_ECP_C */
+ } data;
+} key_slot_t;
+
+static int key_type_is_raw_bytes( psa_key_type_t type )
+{
+ psa_key_type_t category = type & PSA_KEY_TYPE_CATEGORY_MASK;
+ return( category == PSA_KEY_TYPE_RAW_DATA ||
+ category == PSA_KEY_TYPE_CATEGORY_SYMMETRIC );
+}
+
+typedef struct
+{
+ int initialized;
+ mbedcrypto_entropy_context entropy;
+ mbedcrypto_ctr_drbg_context ctr_drbg;
+ key_slot_t key_slots[PSA_KEY_SLOT_COUNT];
+} psa_global_data_t;
+
+static psa_global_data_t global_data;
+
+static psa_status_t mbedcrypto_to_psa_error( int ret )
+{
+ /* If there's both a high-level code and low-level code, dispatch on
+ * the high-level code. */
+ switch( ret < -0x7f ? - ( -ret & 0x7f80 ) : ret )
+ {
+ case 0:
+ return( PSA_SUCCESS );
+
+ case MBEDCRYPTO_ERR_AES_INVALID_KEY_LENGTH:
+ case MBEDCRYPTO_ERR_AES_INVALID_INPUT_LENGTH:
+ case MBEDCRYPTO_ERR_AES_FEATURE_UNAVAILABLE:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_AES_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_ARC4_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_ASN1_OUT_OF_DATA:
+ case MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG:
+ case MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH:
+ case MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH:
+ case MBEDCRYPTO_ERR_ASN1_INVALID_DATA:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_ASN1_ALLOC_FAILED:
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ case MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL:
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+ case MBEDCRYPTO_ERR_BLOWFISH_INVALID_KEY_LENGTH:
+ case MBEDCRYPTO_ERR_BLOWFISH_INVALID_INPUT_LENGTH:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_BLOWFISH_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_CAMELLIA_INVALID_KEY_LENGTH:
+ case MBEDCRYPTO_ERR_CAMELLIA_INVALID_INPUT_LENGTH:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_CAMELLIA_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_CCM_BAD_INPUT:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_CCM_AUTH_FAILED:
+ return( PSA_ERROR_INVALID_SIGNATURE );
+ case MBEDCRYPTO_ERR_CCM_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_CIPHER_BAD_INPUT_DATA:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_CIPHER_ALLOC_FAILED:
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ case MBEDCRYPTO_ERR_CIPHER_INVALID_PADDING:
+ return( PSA_ERROR_INVALID_PADDING );
+ case MBEDCRYPTO_ERR_CIPHER_FULL_BLOCK_EXPECTED:
+ return( PSA_ERROR_BAD_STATE );
+ case MBEDCRYPTO_ERR_CIPHER_AUTH_FAILED:
+ return( PSA_ERROR_INVALID_SIGNATURE );
+ case MBEDCRYPTO_ERR_CIPHER_INVALID_CONTEXT:
+ return( PSA_ERROR_TAMPERING_DETECTED );
+ case MBEDCRYPTO_ERR_CIPHER_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_CMAC_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED:
+ return( PSA_ERROR_INSUFFICIENT_ENTROPY );
+ case MBEDCRYPTO_ERR_CTR_DRBG_REQUEST_TOO_BIG:
+ case MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR:
+ return( PSA_ERROR_INSUFFICIENT_ENTROPY );
+
+ case MBEDCRYPTO_ERR_DES_INVALID_INPUT_LENGTH:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_DES_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_ENTROPY_NO_SOURCES_DEFINED:
+ case MBEDCRYPTO_ERR_ENTROPY_NO_STRONG_SOURCE:
+ case MBEDCRYPTO_ERR_ENTROPY_SOURCE_FAILED:
+ return( PSA_ERROR_INSUFFICIENT_ENTROPY );
+
+ case MBEDCRYPTO_ERR_GCM_AUTH_FAILED:
+ return( PSA_ERROR_INVALID_SIGNATURE );
+ case MBEDCRYPTO_ERR_GCM_BAD_INPUT:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_GCM_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_MD2_HW_ACCEL_FAILED:
+ case MBEDCRYPTO_ERR_MD4_HW_ACCEL_FAILED:
+ case MBEDCRYPTO_ERR_MD5_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_MD_FEATURE_UNAVAILABLE:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_MD_ALLOC_FAILED:
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ case MBEDCRYPTO_ERR_MD_FILE_IO_ERROR:
+ return( PSA_ERROR_STORAGE_FAILURE );
+ case MBEDCRYPTO_ERR_MD_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_PK_ALLOC_FAILED:
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ case MBEDCRYPTO_ERR_PK_TYPE_MISMATCH:
+ case MBEDCRYPTO_ERR_PK_BAD_INPUT_DATA:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_PK_FILE_IO_ERROR:
+ return( PSA_ERROR_STORAGE_FAILURE );
+ case MBEDCRYPTO_ERR_PK_KEY_INVALID_VERSION:
+ case MBEDCRYPTO_ERR_PK_KEY_INVALID_FORMAT:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_PK_UNKNOWN_PK_ALG:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_PK_PASSWORD_REQUIRED:
+ case MBEDCRYPTO_ERR_PK_PASSWORD_MISMATCH:
+ return( PSA_ERROR_NOT_PERMITTED );
+ case MBEDCRYPTO_ERR_PK_INVALID_PUBKEY:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_PK_INVALID_ALG:
+ case MBEDCRYPTO_ERR_PK_UNKNOWN_NAMED_CURVE:
+ case MBEDCRYPTO_ERR_PK_FEATURE_UNAVAILABLE:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_PK_SIG_LEN_MISMATCH:
+ return( PSA_ERROR_INVALID_SIGNATURE );
+ case MBEDCRYPTO_ERR_PK_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_RIPEMD160_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_RSA_INVALID_PADDING:
+ return( PSA_ERROR_INVALID_PADDING );
+ case MBEDCRYPTO_ERR_RSA_KEY_GEN_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+ case MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_RSA_PUBLIC_FAILED:
+ case MBEDCRYPTO_ERR_RSA_PRIVATE_FAILED:
+ return( PSA_ERROR_TAMPERING_DETECTED );
+ case MBEDCRYPTO_ERR_RSA_VERIFY_FAILED:
+ return( PSA_ERROR_INVALID_SIGNATURE );
+ case MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE:
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+ case MBEDCRYPTO_ERR_RSA_RNG_FAILED:
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ case MBEDCRYPTO_ERR_RSA_UNSUPPORTED_OPERATION:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_RSA_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_SHA1_HW_ACCEL_FAILED:
+ case MBEDCRYPTO_ERR_SHA256_HW_ACCEL_FAILED:
+ case MBEDCRYPTO_ERR_SHA512_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_XTEA_INVALID_INPUT_LENGTH:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_XTEA_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ case MBEDCRYPTO_ERR_ECP_BAD_INPUT_DATA:
+ case MBEDCRYPTO_ERR_ECP_INVALID_KEY:
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ case MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL:
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+ case MBEDCRYPTO_ERR_ECP_FEATURE_UNAVAILABLE:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ case MBEDCRYPTO_ERR_ECP_SIG_LEN_MISMATCH:
+ case MBEDCRYPTO_ERR_ECP_VERIFY_FAILED:
+ return( PSA_ERROR_INVALID_SIGNATURE );
+ case MBEDCRYPTO_ERR_ECP_ALLOC_FAILED:
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ case MBEDCRYPTO_ERR_ECP_HW_ACCEL_FAILED:
+ return( PSA_ERROR_HARDWARE_FAILURE );
+
+ default:
+ return( PSA_ERROR_UNKNOWN_ERROR );
+ }
+}
+
+/* Retrieve a key slot, occupied or not. */
+static psa_status_t psa_get_key_slot( psa_key_slot_t key,
+ key_slot_t **p_slot )
+{
+ /* 0 is not a valid slot number under any circumstance. This
+ * implementation provides slots number 1 to N where N is the
+ * number of available slots. */
+ if( key == 0 || key > ARRAY_LENGTH( global_data.key_slots ) )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ *p_slot = &global_data.key_slots[key - 1];
+ return( PSA_SUCCESS );
+}
+
+/* Retrieve an empty key slot (slot with no key data, but possibly
+ * with some metadata such as a policy). */
+static psa_status_t psa_get_empty_key_slot( psa_key_slot_t key,
+ key_slot_t **p_slot )
+{
+ psa_status_t status;
+ key_slot_t *slot = NULL;
+
+ *p_slot = NULL;
+
+ status = psa_get_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( slot->type != PSA_KEY_TYPE_NONE )
+ return( PSA_ERROR_OCCUPIED_SLOT );
+
+ *p_slot = slot;
+ return( status );
+}
+
+/** Retrieve a slot which must contain a key. The key must have allow all the
+ * usage flags set in \p usage. If \p alg is nonzero, the key must allow
+ * operations with this algorithm. */
+static psa_status_t psa_get_key_from_slot( psa_key_slot_t key,
+ key_slot_t **p_slot,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ psa_status_t status;
+ key_slot_t *slot = NULL;
+
+ *p_slot = NULL;
+
+ status = psa_get_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ return( status );
+ if( slot->type == PSA_KEY_TYPE_NONE )
+ return( PSA_ERROR_EMPTY_SLOT );
+
+ /* Enforce that usage policy for the key slot contains all the flags
+ * required by the usage parameter. There is one exception: public
+ * keys can always be exported, so we treat public key objects as
+ * if they had the export flag. */
+ if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) )
+ usage &= ~PSA_KEY_USAGE_EXPORT;
+ if( ( slot->policy.usage & usage ) != usage )
+ return( PSA_ERROR_NOT_PERMITTED );
+ if( alg != 0 && ( alg != slot->policy.alg ) )
+ return( PSA_ERROR_NOT_PERMITTED );
+
+ *p_slot = slot;
+ return( PSA_SUCCESS );
+}
+
+
+
+/****************************************************************/
+/* Key management */
+/****************************************************************/
+
+#if defined(MBEDCRYPTO_ECP_C)
+static psa_ecc_curve_t mbedcrypto_ecc_group_to_psa( mbedcrypto_ecp_group_id grpid )
+{
+ switch( grpid )
+ {
+ case MBEDCRYPTO_ECP_DP_SECP192R1:
+ return( PSA_ECC_CURVE_SECP192R1 );
+ case MBEDCRYPTO_ECP_DP_SECP224R1:
+ return( PSA_ECC_CURVE_SECP224R1 );
+ case MBEDCRYPTO_ECP_DP_SECP256R1:
+ return( PSA_ECC_CURVE_SECP256R1 );
+ case MBEDCRYPTO_ECP_DP_SECP384R1:
+ return( PSA_ECC_CURVE_SECP384R1 );
+ case MBEDCRYPTO_ECP_DP_SECP521R1:
+ return( PSA_ECC_CURVE_SECP521R1 );
+ case MBEDCRYPTO_ECP_DP_BP256R1:
+ return( PSA_ECC_CURVE_BRAINPOOL_P256R1 );
+ case MBEDCRYPTO_ECP_DP_BP384R1:
+ return( PSA_ECC_CURVE_BRAINPOOL_P384R1 );
+ case MBEDCRYPTO_ECP_DP_BP512R1:
+ return( PSA_ECC_CURVE_BRAINPOOL_P512R1 );
+ case MBEDCRYPTO_ECP_DP_CURVE25519:
+ return( PSA_ECC_CURVE_CURVE25519 );
+ case MBEDCRYPTO_ECP_DP_SECP192K1:
+ return( PSA_ECC_CURVE_SECP192K1 );
+ case MBEDCRYPTO_ECP_DP_SECP224K1:
+ return( PSA_ECC_CURVE_SECP224K1 );
+ case MBEDCRYPTO_ECP_DP_SECP256K1:
+ return( PSA_ECC_CURVE_SECP256K1 );
+ case MBEDCRYPTO_ECP_DP_CURVE448:
+ return( PSA_ECC_CURVE_CURVE448 );
+ default:
+ return( 0 );
+ }
+}
+
+static mbedcrypto_ecp_group_id mbedcrypto_ecc_group_of_psa( psa_ecc_curve_t curve )
+{
+ switch( curve )
+ {
+ case PSA_ECC_CURVE_SECP192R1:
+ return( MBEDCRYPTO_ECP_DP_SECP192R1 );
+ case PSA_ECC_CURVE_SECP224R1:
+ return( MBEDCRYPTO_ECP_DP_SECP224R1 );
+ case PSA_ECC_CURVE_SECP256R1:
+ return( MBEDCRYPTO_ECP_DP_SECP256R1 );
+ case PSA_ECC_CURVE_SECP384R1:
+ return( MBEDCRYPTO_ECP_DP_SECP384R1 );
+ case PSA_ECC_CURVE_SECP521R1:
+ return( MBEDCRYPTO_ECP_DP_SECP521R1 );
+ case PSA_ECC_CURVE_BRAINPOOL_P256R1:
+ return( MBEDCRYPTO_ECP_DP_BP256R1 );
+ case PSA_ECC_CURVE_BRAINPOOL_P384R1:
+ return( MBEDCRYPTO_ECP_DP_BP384R1 );
+ case PSA_ECC_CURVE_BRAINPOOL_P512R1:
+ return( MBEDCRYPTO_ECP_DP_BP512R1 );
+ case PSA_ECC_CURVE_CURVE25519:
+ return( MBEDCRYPTO_ECP_DP_CURVE25519 );
+ case PSA_ECC_CURVE_SECP192K1:
+ return( MBEDCRYPTO_ECP_DP_SECP192K1 );
+ case PSA_ECC_CURVE_SECP224K1:
+ return( MBEDCRYPTO_ECP_DP_SECP224K1 );
+ case PSA_ECC_CURVE_SECP256K1:
+ return( MBEDCRYPTO_ECP_DP_SECP256K1 );
+ case PSA_ECC_CURVE_CURVE448:
+ return( MBEDCRYPTO_ECP_DP_CURVE448 );
+ default:
+ return( MBEDCRYPTO_ECP_DP_NONE );
+ }
+}
+#endif /* defined(MBEDCRYPTO_ECP_C) */
+
+static psa_status_t prepare_raw_data_slot( psa_key_type_t type,
+ size_t bits,
+ struct raw_data *raw )
+{
+ /* Check that the bit size is acceptable for the key type */
+ switch( type )
+ {
+ case PSA_KEY_TYPE_RAW_DATA:
+ if( bits == 0 )
+ {
+ raw->bytes = 0;
+ raw->data = NULL;
+ return( PSA_SUCCESS );
+ }
+ break;
+#if defined(MBEDCRYPTO_MD_C)
+ case PSA_KEY_TYPE_HMAC:
+#endif
+ case PSA_KEY_TYPE_DERIVE:
+ break;
+#if defined(MBEDCRYPTO_AES_C)
+ case PSA_KEY_TYPE_AES:
+ if( bits != 128 && bits != 192 && bits != 256 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ break;
+#endif
+#if defined(MBEDCRYPTO_CAMELLIA_C)
+ case PSA_KEY_TYPE_CAMELLIA:
+ if( bits != 128 && bits != 192 && bits != 256 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ break;
+#endif
+#if defined(MBEDCRYPTO_DES_C)
+ case PSA_KEY_TYPE_DES:
+ if( bits != 64 && bits != 128 && bits != 192 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ break;
+#endif
+#if defined(MBEDCRYPTO_ARC4_C)
+ case PSA_KEY_TYPE_ARC4:
+ if( bits < 8 || bits > 2048 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ break;
+#endif
+ default:
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+ if( bits % 8 != 0 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ /* Allocate memory for the key */
+ raw->bytes = PSA_BITS_TO_BYTES( bits );
+ raw->data = mbedcrypto_calloc( 1, raw->bytes );
+ if( raw->data == NULL )
+ {
+ raw->bytes = 0;
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ }
+ return( PSA_SUCCESS );
+}
+
+#if defined(MBEDCRYPTO_RSA_C) && defined(MBEDCRYPTO_PK_PARSE_C)
+static psa_status_t psa_import_rsa_key( mbedcrypto_pk_context *pk,
+ mbedcrypto_rsa_context **p_rsa )
+{
+ if( mbedcrypto_pk_get_type( pk ) != MBEDCRYPTO_PK_RSA )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ else
+ {
+ mbedcrypto_rsa_context *rsa = mbedcrypto_pk_rsa( *pk );
+ size_t bits = mbedcrypto_rsa_get_bitlen( rsa );
+ if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ *p_rsa = rsa;
+ return( PSA_SUCCESS );
+ }
+}
+#endif /* defined(MBEDCRYPTO_RSA_C) && defined(MBEDCRYPTO_PK_PARSE_C) */
+
+#if defined(MBEDCRYPTO_ECP_C) && defined(MBEDCRYPTO_PK_PARSE_C)
+static psa_status_t psa_import_ecp_key( psa_ecc_curve_t expected_curve,
+ mbedcrypto_pk_context *pk,
+ mbedcrypto_ecp_keypair **p_ecp )
+{
+ if( mbedcrypto_pk_get_type( pk ) != MBEDCRYPTO_PK_ECKEY )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ else
+ {
+ mbedcrypto_ecp_keypair *ecp = mbedcrypto_pk_ec( *pk );
+ psa_ecc_curve_t actual_curve = mbedcrypto_ecc_group_to_psa( ecp->grp.id );
+ if( actual_curve != expected_curve )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ *p_ecp = ecp;
+ return( PSA_SUCCESS );
+ }
+}
+#endif /* defined(MBEDCRYPTO_ECP_C) && defined(MBEDCRYPTO_PK_PARSE_C) */
+
+psa_status_t psa_import_key( psa_key_slot_t key,
+ psa_key_type_t type,
+ const uint8_t *data,
+ size_t data_length )
+{
+ key_slot_t *slot;
+ psa_status_t status = PSA_SUCCESS;
+ status = psa_get_empty_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( key_type_is_raw_bytes( type ) )
+ {
+ /* Ensure that a bytes-to-bit conversion won't overflow. */
+ if( data_length > SIZE_MAX / 8 )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ status = prepare_raw_data_slot( type,
+ PSA_BYTES_TO_BITS( data_length ),
+ &slot->data.raw );
+ if( status != PSA_SUCCESS )
+ return( status );
+ if( data_length != 0 )
+ memcpy( slot->data.raw.data, data, data_length );
+ }
+ else
+#if defined(MBEDCRYPTO_PK_PARSE_C)
+ if( PSA_KEY_TYPE_IS_RSA( type ) || PSA_KEY_TYPE_IS_ECC( type ) )
+ {
+ int ret;
+ mbedcrypto_pk_context pk;
+ mbedcrypto_pk_init( &pk );
+
+ /* Parse the data. */
+ if( PSA_KEY_TYPE_IS_KEYPAIR( type ) )
+ ret = mbedcrypto_pk_parse_key( &pk, data, data_length, NULL, 0 );
+ else
+ ret = mbedcrypto_pk_parse_public_key( &pk, data, data_length );
+ if( ret != 0 )
+ return( mbedcrypto_to_psa_error( ret ) );
+
+ /* We have something that the pkparse module recognizes.
+ * If it has the expected type and passes any type-specific
+ * checks, store it. */
+#if defined(MBEDCRYPTO_RSA_C)
+ if( PSA_KEY_TYPE_IS_RSA( type ) )
+ status = psa_import_rsa_key( &pk, &slot->data.rsa );
+ else
+#endif /* MBEDCRYPTO_RSA_C */
+#if defined(MBEDCRYPTO_ECP_C)
+ if( PSA_KEY_TYPE_IS_ECC( type ) )
+ status = psa_import_ecp_key( PSA_KEY_TYPE_GET_CURVE( type ),
+ &pk, &slot->data.ecp );
+ else
+#endif /* MBEDCRYPTO_ECP_C */
+ {
+ status = PSA_ERROR_NOT_SUPPORTED;
+ }
+
+ /* Free the content of the pk object only on error. On success,
+ * the content of the object has been stored in the slot. */
+ if( status != PSA_SUCCESS )
+ {
+ mbedcrypto_pk_free( &pk );
+ return( status );
+ }
+ }
+ else
+#endif /* defined(MBEDCRYPTO_PK_PARSE_C) */
+ {
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+
+ slot->type = type;
+ return( PSA_SUCCESS );
+}
+
+psa_status_t psa_destroy_key( psa_key_slot_t key )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ status = psa_get_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( slot->type == PSA_KEY_TYPE_NONE )
+ {
+ /* No key material to clean, but do zeroize the slot below to wipe
+ * metadata such as policies. */
+ }
+ else if( key_type_is_raw_bytes( slot->type ) )
+ {
+ mbedcrypto_free( slot->data.raw.data );
+ }
+ else
+#if defined(MBEDCRYPTO_RSA_C)
+ if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+ {
+ mbedcrypto_rsa_free( slot->data.rsa );
+ mbedcrypto_free( slot->data.rsa );
+ }
+ else
+#endif /* defined(MBEDCRYPTO_RSA_C) */
+#if defined(MBEDCRYPTO_ECP_C)
+ if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
+ {
+ mbedcrypto_ecp_keypair_free( slot->data.ecp );
+ mbedcrypto_free( slot->data.ecp );
+ }
+ else
+#endif /* defined(MBEDCRYPTO_ECP_C) */
+ {
+ /* Shouldn't happen: the key type is not any type that we
+ * put in. */
+ return( PSA_ERROR_TAMPERING_DETECTED );
+ }
+
+ mbedcrypto_zeroize( slot, sizeof( *slot ) );
+ return( PSA_SUCCESS );
+}
+
+/* Return the size of the key in the given slot, in bits. */
+static size_t psa_get_key_bits( const key_slot_t *slot )
+{
+ if( key_type_is_raw_bytes( slot->type ) )
+ return( slot->data.raw.bytes * 8 );
+#if defined(MBEDCRYPTO_RSA_C)
+ if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+ return( mbedcrypto_rsa_get_bitlen( slot->data.rsa ) );
+#endif /* defined(MBEDCRYPTO_RSA_C) */
+#if defined(MBEDCRYPTO_ECP_C)
+ if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
+ return( slot->data.ecp->grp.pbits );
+#endif /* defined(MBEDCRYPTO_ECP_C) */
+ /* Shouldn't happen except on an empty slot. */
+ return( 0 );
+}
+
+psa_status_t psa_get_key_information( psa_key_slot_t key,
+ psa_key_type_t *type,
+ size_t *bits )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ if( type != NULL )
+ *type = 0;
+ if( bits != NULL )
+ *bits = 0;
+ status = psa_get_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( slot->type == PSA_KEY_TYPE_NONE )
+ return( PSA_ERROR_EMPTY_SLOT );
+ if( type != NULL )
+ *type = slot->type;
+ if( bits != NULL )
+ *bits = psa_get_key_bits( slot );
+ return( PSA_SUCCESS );
+}
+
+static psa_status_t psa_internal_export_key( psa_key_slot_t key,
+ uint8_t *data,
+ size_t data_size,
+ size_t *data_length,
+ int export_public_key )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+ /* Exporting a public key doesn't require a usage flag. If we're
+ * called by psa_export_public_key(), don't require the EXPORT flag.
+ * If we're called by psa_export_key(), do require the EXPORT flag;
+ * if the key turns out to be public key object, psa_get_key_from_slot()
+ * will ignore this flag. */
+ psa_key_usage_t usage = export_public_key ? 0 : PSA_KEY_USAGE_EXPORT;
+
+ /* Set the key to empty now, so that even when there are errors, we always
+ * set data_length to a value between 0 and data_size. On error, setting
+ * the key to empty is a good choice because an empty key representation is
+ * unlikely to be accepted anywhere. */
+ *data_length = 0;
+
+ status = psa_get_key_from_slot( key, &slot, usage, 0 );
+ if( status != PSA_SUCCESS )
+ return( status );
+ if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->type ) )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ if( key_type_is_raw_bytes( slot->type ) )
+ {
+ if( slot->data.raw.bytes > data_size )
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+ if( slot->data.raw.bytes != 0 )
+ memcpy( data, slot->data.raw.data, slot->data.raw.bytes );
+ *data_length = slot->data.raw.bytes;
+ return( PSA_SUCCESS );
+ }
+ else
+ {
+#if defined(MBEDCRYPTO_PK_WRITE_C)
+ if( PSA_KEY_TYPE_IS_RSA( slot->type ) ||
+ PSA_KEY_TYPE_IS_ECC( slot->type ) )
+ {
+ mbedcrypto_pk_context pk;
+ int ret;
+ if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+ {
+#if defined(MBEDCRYPTO_RSA_C)
+ mbedcrypto_pk_init( &pk );
+ pk.pk_info = &mbedcrypto_rsa_info;
+ pk.pk_ctx = slot->data.rsa;
+#else
+ return( PSA_ERROR_NOT_SUPPORTED );
+#endif
+ }
+ else
+ {
+#if defined(MBEDCRYPTO_ECP_C)
+ mbedcrypto_pk_init( &pk );
+ pk.pk_info = &mbedcrypto_eckey_info;
+ pk.pk_ctx = slot->data.ecp;
+#else
+ return( PSA_ERROR_NOT_SUPPORTED );
+#endif
+ }
+ if( export_public_key || PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) )
+ ret = mbedcrypto_pk_write_pubkey_der( &pk, data, data_size );
+ else
+ ret = mbedcrypto_pk_write_key_der( &pk, data, data_size );
+ if( ret < 0 )
+ {
+ /* If data_size is 0 then data may be NULL and then the
+ * call to memset would have undefined behavior. */
+ if( data_size != 0 )
+ memset( data, 0, data_size );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+ /* The mbedcrypto_pk_xxx functions write to the end of the buffer.
+ * Move the data to the beginning and erase remaining data
+ * at the original location. */
+ if( 2 * (size_t) ret <= data_size )
+ {
+ memcpy( data, data + data_size - ret, ret );
+ memset( data + data_size - ret, 0, ret );
+ }
+ else if( (size_t) ret < data_size )
+ {
+ memmove( data, data + data_size - ret, ret );
+ memset( data + ret, 0, data_size - ret );
+ }
+ *data_length = ret;
+ return( PSA_SUCCESS );
+ }
+ else
+#endif /* defined(MBEDCRYPTO_PK_WRITE_C) */
+ {
+ /* This shouldn't happen in the reference implementation, but
+ it is valid for a special-purpose implementation to omit
+ support for exporting certain key types. */
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+ }
+}
+
+psa_status_t psa_export_key( psa_key_slot_t key,
+ uint8_t *data,
+ size_t data_size,
+ size_t *data_length )
+{
+ return( psa_internal_export_key( key, data, data_size,
+ data_length, 0 ) );
+}
+
+psa_status_t psa_export_public_key( psa_key_slot_t key,
+ uint8_t *data,
+ size_t data_size,
+ size_t *data_length )
+{
+ return( psa_internal_export_key( key, data, data_size,
+ data_length, 1 ) );
+}
+
+
+
+/****************************************************************/
+/* Message digests */
+/****************************************************************/
+
+static const mbedcrypto_md_info_t *mbedcrypto_md_info_from_psa( psa_algorithm_t alg )
+{
+ switch( alg )
+ {
+#if defined(MBEDCRYPTO_MD2_C)
+ case PSA_ALG_MD2:
+ return( &mbedcrypto_md2_info );
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+ case PSA_ALG_MD4:
+ return( &mbedcrypto_md4_info );
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+ case PSA_ALG_MD5:
+ return( &mbedcrypto_md5_info );
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+ case PSA_ALG_RIPEMD160:
+ return( &mbedcrypto_ripemd160_info );
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+ case PSA_ALG_SHA_1:
+ return( &mbedcrypto_sha1_info );
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+ case PSA_ALG_SHA_224:
+ return( &mbedcrypto_sha224_info );
+ case PSA_ALG_SHA_256:
+ return( &mbedcrypto_sha256_info );
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+ case PSA_ALG_SHA_384:
+ return( &mbedcrypto_sha384_info );
+ case PSA_ALG_SHA_512:
+ return( &mbedcrypto_sha512_info );
+#endif
+ default:
+ return( NULL );
+ }
+}
+
+psa_status_t psa_hash_abort( psa_hash_operation_t *operation )
+{
+ switch( operation->alg )
+ {
+ case 0:
+ /* The object has (apparently) been initialized but it is not
+ * in use. It's ok to call abort on such an object, and there's
+ * nothing to do. */
+ break;
+#if defined(MBEDCRYPTO_MD2_C)
+ case PSA_ALG_MD2:
+ mbedcrypto_md2_free( &operation->ctx.md2 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+ case PSA_ALG_MD4:
+ mbedcrypto_md4_free( &operation->ctx.md4 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+ case PSA_ALG_MD5:
+ mbedcrypto_md5_free( &operation->ctx.md5 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+ case PSA_ALG_RIPEMD160:
+ mbedcrypto_ripemd160_free( &operation->ctx.ripemd160 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+ case PSA_ALG_SHA_1:
+ mbedcrypto_sha1_free( &operation->ctx.sha1 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+ case PSA_ALG_SHA_224:
+ case PSA_ALG_SHA_256:
+ mbedcrypto_sha256_free( &operation->ctx.sha256 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+ case PSA_ALG_SHA_384:
+ case PSA_ALG_SHA_512:
+ mbedcrypto_sha512_free( &operation->ctx.sha512 );
+ break;
+#endif
+ default:
+ return( PSA_ERROR_BAD_STATE );
+ }
+ operation->alg = 0;
+ return( PSA_SUCCESS );
+}
+
+psa_status_t psa_hash_setup( psa_hash_operation_t *operation,
+ psa_algorithm_t alg )
+{
+ int ret;
+ operation->alg = 0;
+ switch( alg )
+ {
+#if defined(MBEDCRYPTO_MD2_C)
+ case PSA_ALG_MD2:
+ mbedcrypto_md2_init( &operation->ctx.md2 );
+ ret = mbedcrypto_md2_starts_ret( &operation->ctx.md2 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+ case PSA_ALG_MD4:
+ mbedcrypto_md4_init( &operation->ctx.md4 );
+ ret = mbedcrypto_md4_starts_ret( &operation->ctx.md4 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+ case PSA_ALG_MD5:
+ mbedcrypto_md5_init( &operation->ctx.md5 );
+ ret = mbedcrypto_md5_starts_ret( &operation->ctx.md5 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+ case PSA_ALG_RIPEMD160:
+ mbedcrypto_ripemd160_init( &operation->ctx.ripemd160 );
+ ret = mbedcrypto_ripemd160_starts_ret( &operation->ctx.ripemd160 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+ case PSA_ALG_SHA_1:
+ mbedcrypto_sha1_init( &operation->ctx.sha1 );
+ ret = mbedcrypto_sha1_starts_ret( &operation->ctx.sha1 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+ case PSA_ALG_SHA_224:
+ mbedcrypto_sha256_init( &operation->ctx.sha256 );
+ ret = mbedcrypto_sha256_starts_ret( &operation->ctx.sha256, 1 );
+ break;
+ case PSA_ALG_SHA_256:
+ mbedcrypto_sha256_init( &operation->ctx.sha256 );
+ ret = mbedcrypto_sha256_starts_ret( &operation->ctx.sha256, 0 );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+ case PSA_ALG_SHA_384:
+ mbedcrypto_sha512_init( &operation->ctx.sha512 );
+ ret = mbedcrypto_sha512_starts_ret( &operation->ctx.sha512, 1 );
+ break;
+ case PSA_ALG_SHA_512:
+ mbedcrypto_sha512_init( &operation->ctx.sha512 );
+ ret = mbedcrypto_sha512_starts_ret( &operation->ctx.sha512, 0 );
+ break;
+#endif
+ default:
+ return( PSA_ALG_IS_HASH( alg ) ?
+ PSA_ERROR_NOT_SUPPORTED :
+ PSA_ERROR_INVALID_ARGUMENT );
+ }
+ if( ret == 0 )
+ operation->alg = alg;
+ else
+ psa_hash_abort( operation );
+ return( mbedcrypto_to_psa_error( ret ) );
+}
+
+psa_status_t psa_hash_update( psa_hash_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length )
+{
+ int ret;
+
+ /* Don't require hash implementations to behave correctly on a
+ * zero-length input, which may have an invalid pointer. */
+ if( input_length == 0 )
+ return( PSA_SUCCESS );
+
+ switch( operation->alg )
+ {
+#if defined(MBEDCRYPTO_MD2_C)
+ case PSA_ALG_MD2:
+ ret = mbedcrypto_md2_update_ret( &operation->ctx.md2,
+ input, input_length );
+ break;
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+ case PSA_ALG_MD4:
+ ret = mbedcrypto_md4_update_ret( &operation->ctx.md4,
+ input, input_length );
+ break;
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+ case PSA_ALG_MD5:
+ ret = mbedcrypto_md5_update_ret( &operation->ctx.md5,
+ input, input_length );
+ break;
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+ case PSA_ALG_RIPEMD160:
+ ret = mbedcrypto_ripemd160_update_ret( &operation->ctx.ripemd160,
+ input, input_length );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+ case PSA_ALG_SHA_1:
+ ret = mbedcrypto_sha1_update_ret( &operation->ctx.sha1,
+ input, input_length );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+ case PSA_ALG_SHA_224:
+ case PSA_ALG_SHA_256:
+ ret = mbedcrypto_sha256_update_ret( &operation->ctx.sha256,
+ input, input_length );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+ case PSA_ALG_SHA_384:
+ case PSA_ALG_SHA_512:
+ ret = mbedcrypto_sha512_update_ret( &operation->ctx.sha512,
+ input, input_length );
+ break;
+#endif
+ default:
+ ret = MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA;
+ break;
+ }
+
+ if( ret != 0 )
+ psa_hash_abort( operation );
+ return( mbedcrypto_to_psa_error( ret ) );
+}
+
+psa_status_t psa_hash_finish( psa_hash_operation_t *operation,
+ uint8_t *hash,
+ size_t hash_size,
+ size_t *hash_length )
+{
+ int ret;
+ size_t actual_hash_length = PSA_HASH_SIZE( operation->alg );
+
+ /* Fill the output buffer with something that isn't a valid hash
+ * (barring an attack on the hash and deliberately-crafted input),
+ * in case the caller doesn't check the return status properly. */
+ *hash_length = hash_size;
+ /* If hash_size is 0 then hash may be NULL and then the
+ * call to memset would have undefined behavior. */
+ if( hash_size != 0 )
+ memset( hash, '!', hash_size );
+
+ if( hash_size < actual_hash_length )
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+ switch( operation->alg )
+ {
+#if defined(MBEDCRYPTO_MD2_C)
+ case PSA_ALG_MD2:
+ ret = mbedcrypto_md2_finish_ret( &operation->ctx.md2, hash );
+ break;
+#endif
+#if defined(MBEDCRYPTO_MD4_C)
+ case PSA_ALG_MD4:
+ ret = mbedcrypto_md4_finish_ret( &operation->ctx.md4, hash );
+ break;
+#endif
+#if defined(MBEDCRYPTO_MD5_C)
+ case PSA_ALG_MD5:
+ ret = mbedcrypto_md5_finish_ret( &operation->ctx.md5, hash );
+ break;
+#endif
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+ case PSA_ALG_RIPEMD160:
+ ret = mbedcrypto_ripemd160_finish_ret( &operation->ctx.ripemd160, hash );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA1_C)
+ case PSA_ALG_SHA_1:
+ ret = mbedcrypto_sha1_finish_ret( &operation->ctx.sha1, hash );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA256_C)
+ case PSA_ALG_SHA_224:
+ case PSA_ALG_SHA_256:
+ ret = mbedcrypto_sha256_finish_ret( &operation->ctx.sha256, hash );
+ break;
+#endif
+#if defined(MBEDCRYPTO_SHA512_C)
+ case PSA_ALG_SHA_384:
+ case PSA_ALG_SHA_512:
+ ret = mbedcrypto_sha512_finish_ret( &operation->ctx.sha512, hash );
+ break;
+#endif
+ default:
+ ret = MBEDCRYPTO_ERR_MD_BAD_INPUT_DATA;
+ break;
+ }
+
+ if( ret == 0 )
+ {
+ *hash_length = actual_hash_length;
+ return( psa_hash_abort( operation ) );
+ }
+ else
+ {
+ psa_hash_abort( operation );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+}
+
+psa_status_t psa_hash_verify( psa_hash_operation_t *operation,
+ const uint8_t *hash,
+ size_t hash_length )
+{
+ uint8_t actual_hash[MBEDCRYPTO_MD_MAX_SIZE];
+ size_t actual_hash_length;
+ psa_status_t status = psa_hash_finish( operation,
+ actual_hash, sizeof( actual_hash ),
+ &actual_hash_length );
+ if( status != PSA_SUCCESS )
+ return( status );
+ if( actual_hash_length != hash_length )
+ return( PSA_ERROR_INVALID_SIGNATURE );
+ if( safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 )
+ return( PSA_ERROR_INVALID_SIGNATURE );
+ return( PSA_SUCCESS );
+}
+
+
+
+/****************************************************************/
+/* MAC */
+/****************************************************************/
+
+static const mbedcrypto_cipher_info_t *mbedcrypto_cipher_info_from_psa(
+ psa_algorithm_t alg,
+ psa_key_type_t key_type,
+ size_t key_bits,
+ mbedcrypto_cipher_id_t* cipher_id )
+{
+ mbedcrypto_cipher_mode_t mode;
+ mbedcrypto_cipher_id_t cipher_id_tmp;
+
+ if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) )
+ {
+ if( PSA_ALG_IS_BLOCK_CIPHER( alg ) )
+ {
+ alg &= ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
+ }
+
+ switch( alg )
+ {
+ case PSA_ALG_STREAM_CIPHER_BASE:
+ mode = MBEDCRYPTO_MODE_STREAM;
+ break;
+ case PSA_ALG_CBC_BASE:
+ mode = MBEDCRYPTO_MODE_CBC;
+ break;
+ case PSA_ALG_CFB_BASE:
+ mode = MBEDCRYPTO_MODE_CFB;
+ break;
+ case PSA_ALG_OFB_BASE:
+ mode = MBEDCRYPTO_MODE_OFB;
+ break;
+ case PSA_ALG_CTR:
+ mode = MBEDCRYPTO_MODE_CTR;
+ break;
+ case PSA_ALG_CCM:
+ mode = MBEDCRYPTO_MODE_CCM;
+ break;
+ case PSA_ALG_GCM:
+ mode = MBEDCRYPTO_MODE_GCM;
+ break;
+ default:
+ return( NULL );
+ }
+ }
+ else if( alg == PSA_ALG_CMAC )
+ mode = MBEDCRYPTO_MODE_ECB;
+ else if( alg == PSA_ALG_GMAC )
+ mode = MBEDCRYPTO_MODE_GCM;
+ else
+ return( NULL );
+
+ switch( key_type )
+ {
+ case PSA_KEY_TYPE_AES:
+ cipher_id_tmp = MBEDCRYPTO_CIPHER_ID_AES;
+ break;
+ case PSA_KEY_TYPE_DES:
+ /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
+ * and 192 for three-key Triple-DES. */
+ if( key_bits == 64 )
+ cipher_id_tmp = MBEDCRYPTO_CIPHER_ID_DES;
+ else
+ cipher_id_tmp = MBEDCRYPTO_CIPHER_ID_3DES;
+ /* mbedcrypto doesn't recognize two-key Triple-DES as an algorithm,
+ * but two-key Triple-DES is functionally three-key Triple-DES
+ * with K1=K3, so that's how we present it to mbedcrypto. */
+ if( key_bits == 128 )
+ key_bits = 192;
+ break;
+ case PSA_KEY_TYPE_CAMELLIA:
+ cipher_id_tmp = MBEDCRYPTO_CIPHER_ID_CAMELLIA;
+ break;
+ case PSA_KEY_TYPE_ARC4:
+ cipher_id_tmp = MBEDCRYPTO_CIPHER_ID_ARC4;
+ break;
+ default:
+ return( NULL );
+ }
+ if( cipher_id != NULL )
+ *cipher_id = cipher_id_tmp;
+
+ return( mbedcrypto_cipher_info_from_values( cipher_id_tmp,
+ (int) key_bits, mode ) );
+}
+
+static size_t psa_get_hash_block_size( psa_algorithm_t alg )
+{
+ switch( alg )
+ {
+ case PSA_ALG_MD2:
+ return( 16 );
+ case PSA_ALG_MD4:
+ return( 64 );
+ case PSA_ALG_MD5:
+ return( 64 );
+ case PSA_ALG_RIPEMD160:
+ return( 64 );
+ case PSA_ALG_SHA_1:
+ return( 64 );
+ case PSA_ALG_SHA_224:
+ return( 64 );
+ case PSA_ALG_SHA_256:
+ return( 64 );
+ case PSA_ALG_SHA_384:
+ return( 128 );
+ case PSA_ALG_SHA_512:
+ return( 128 );
+ default:
+ return( 0 );
+ }
+}
+
+/* Initialize the MAC operation structure. Once this function has been
+ * called, psa_mac_abort can run and will do the right thing. */
+static psa_status_t psa_mac_init( psa_mac_operation_t *operation,
+ psa_algorithm_t alg )
+{
+ psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
+
+ operation->alg = alg;
+ operation->key_set = 0;
+ operation->iv_set = 0;
+ operation->iv_required = 0;
+ operation->has_input = 0;
+ operation->is_sign = 0;
+
+#if defined(MBEDCRYPTO_CMAC_C)
+ if( alg == PSA_ALG_CMAC )
+ {
+ operation->iv_required = 0;
+ mbedcrypto_cipher_init( &operation->ctx.cmac );
+ status = PSA_SUCCESS;
+ }
+ else
+#endif /* MBEDCRYPTO_CMAC_C */
+#if defined(MBEDCRYPTO_MD_C)
+ if( PSA_ALG_IS_HMAC( operation->alg ) )
+ {
+ /* We'll set up the hash operation later in psa_hmac_setup_internal. */
+ operation->ctx.hmac.hash_ctx.alg = 0;
+ status = PSA_SUCCESS;
+ }
+ else
+#endif /* MBEDCRYPTO_MD_C */
+ {
+ if( ! PSA_ALG_IS_MAC( alg ) )
+ status = PSA_ERROR_INVALID_ARGUMENT;
+ }
+
+ if( status != PSA_SUCCESS )
+ memset( operation, 0, sizeof( *operation ) );
+ return( status );
+}
+
+#if defined(MBEDCRYPTO_MD_C)
+static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac )
+{
+ mbedcrypto_zeroize( hmac->opad, sizeof( hmac->opad ) );
+ return( psa_hash_abort( &hmac->hash_ctx ) );
+}
+#endif /* MBEDCRYPTO_MD_C */
+
+psa_status_t psa_mac_abort( psa_mac_operation_t *operation )
+{
+ if( operation->alg == 0 )
+ {
+ /* The object has (apparently) been initialized but it is not
+ * in use. It's ok to call abort on such an object, and there's
+ * nothing to do. */
+ return( PSA_SUCCESS );
+ }
+ else
+#if defined(MBEDCRYPTO_CMAC_C)
+ if( operation->alg == PSA_ALG_CMAC )
+ {
+ mbedcrypto_cipher_free( &operation->ctx.cmac );
+ }
+ else
+#endif /* MBEDCRYPTO_CMAC_C */
+#if defined(MBEDCRYPTO_MD_C)
+ if( PSA_ALG_IS_HMAC( operation->alg ) )
+ {
+ psa_hmac_abort_internal( &operation->ctx.hmac );
+ }
+ else
+#endif /* MBEDCRYPTO_MD_C */
+ {
+ /* Sanity check (shouldn't happen: operation->alg should
+ * always have been initialized to a valid value). */
+ goto bad_state;
+ }
+
+ operation->alg = 0;
+ operation->key_set = 0;
+ operation->iv_set = 0;
+ operation->iv_required = 0;
+ operation->has_input = 0;
+ operation->is_sign = 0;
+
+ return( PSA_SUCCESS );
+
+bad_state:
+ /* If abort is called on an uninitialized object, we can't trust
+ * anything. Wipe the object in case it contains confidential data.
+ * This may result in a memory leak if a pointer gets overwritten,
+ * but it's too late to do anything about this. */
+ memset( operation, 0, sizeof( *operation ) );
+ return( PSA_ERROR_BAD_STATE );
+}
+
+#if defined(MBEDCRYPTO_CMAC_C)
+static int psa_cmac_setup( psa_mac_operation_t *operation,
+ size_t key_bits,
+ key_slot_t *slot,
+ const mbedcrypto_cipher_info_t *cipher_info )
+{
+ int ret;
+
+ operation->mac_size = cipher_info->block_size;
+
+ ret = mbedcrypto_cipher_setup( &operation->ctx.cmac, cipher_info );
+ if( ret != 0 )
+ return( ret );
+
+ ret = mbedcrypto_cipher_cmac_starts( &operation->ctx.cmac,
+ slot->data.raw.data,
+ key_bits );
+ return( ret );
+}
+#endif /* MBEDCRYPTO_CMAC_C */
+
+#if defined(MBEDCRYPTO_MD_C)
+static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac,
+ const uint8_t *key,
+ size_t key_length,
+ psa_algorithm_t hash_alg )
+{
+ unsigned char ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+ size_t i;
+ size_t hash_size = PSA_HASH_SIZE( hash_alg );
+ size_t block_size = psa_get_hash_block_size( hash_alg );
+ psa_status_t status;
+
+ /* Sanity checks on block_size, to guarantee that there won't be a buffer
+ * overflow below. This should never trigger if the hash algorithm
+ * is implemented correctly. */
+ /* The size checks against the ipad and opad buffers cannot be written
+ * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )`
+ * because that triggers -Wlogical-op on GCC 7.3. */
+ if( block_size > sizeof( ipad ) )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ if( block_size > sizeof( hmac->opad ) )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ if( block_size < hash_size )
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ if( key_length > block_size )
+ {
+ status = psa_hash_setup( &hmac->hash_ctx, hash_alg );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+ status = psa_hash_update( &hmac->hash_ctx, key, key_length );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+ status = psa_hash_finish( &hmac->hash_ctx,
+ ipad, sizeof( ipad ), &key_length );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+ }
+ /* A 0-length key is not commonly used in HMAC when used as a MAC,
+ * but it is permitted. It is common when HMAC is used in HKDF, for
+ * example. Don't call `memcpy` in the 0-length because `key` could be
+ * an invalid pointer which would make the behavior undefined. */
+ else if( key_length != 0 )
+ memcpy( ipad, key, key_length );
+
+ /* ipad contains the key followed by garbage. Xor and fill with 0x36
+ * to create the ipad value. */
+ for( i = 0; i < key_length; i++ )
+ ipad[i] ^= 0x36;
+ memset( ipad + key_length, 0x36, block_size - key_length );
+
+ /* Copy the key material from ipad to opad, flipping the requisite bits,
+ * and filling the rest of opad with the requisite constant. */
+ for( i = 0; i < key_length; i++ )
+ hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
+ memset( hmac->opad + key_length, 0x5C, block_size - key_length );
+
+ status = psa_hash_setup( &hmac->hash_ctx, hash_alg );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
+
+ status = psa_hash_update( &hmac->hash_ctx, ipad, block_size );
+
+cleanup:
+ mbedcrypto_zeroize( ipad, key_length );
+
+ return( status );
+}
+#endif /* MBEDCRYPTO_MD_C */
+
+static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg,
+ int is_sign )
+{
+ psa_status_t status;
+ key_slot_t *slot;
+ size_t key_bits;
+ psa_key_usage_t usage =
+ is_sign ? PSA_KEY_USAGE_SIGN : PSA_KEY_USAGE_VERIFY;
+
+ status = psa_mac_init( operation, alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+ if( is_sign )
+ operation->is_sign = 1;
+
+ status = psa_get_key_from_slot( key, &slot, usage, alg );
+ if( status != PSA_SUCCESS )
+ goto exit;
+ key_bits = psa_get_key_bits( slot );
+
+#if defined(MBEDCRYPTO_CMAC_C)
+ if( alg == PSA_ALG_CMAC )
+ {
+ const mbedcrypto_cipher_info_t *cipher_info =
+ mbedcrypto_cipher_info_from_psa( alg, slot->type, key_bits, NULL );
+ int ret;
+ if( cipher_info == NULL )
+ {
+ status = PSA_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+ operation->mac_size = cipher_info->block_size;
+ ret = psa_cmac_setup( operation, key_bits, slot, cipher_info );
+ status = mbedcrypto_to_psa_error( ret );
+ }
+ else
+#endif /* MBEDCRYPTO_CMAC_C */
+#if defined(MBEDCRYPTO_MD_C)
+ if( PSA_ALG_IS_HMAC( alg ) )
+ {
+ psa_algorithm_t hash_alg = PSA_ALG_HMAC_HASH( alg );
+ if( hash_alg == 0 )
+ {
+ status = PSA_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+
+ operation->mac_size = PSA_HASH_SIZE( hash_alg );
+ /* Sanity check. This shouldn't fail on a valid configuration. */
+ if( operation->mac_size == 0 ||
+ operation->mac_size > sizeof( operation->ctx.hmac.opad ) )
+ {
+ status = PSA_ERROR_NOT_SUPPORTED;
+ goto exit;
+ }
+
+ if( slot->type != PSA_KEY_TYPE_HMAC )
+ {
+ status = PSA_ERROR_INVALID_ARGUMENT;
+ goto exit;
+ }
+
+ status = psa_hmac_setup_internal( &operation->ctx.hmac,
+ slot->data.raw.data,
+ slot->data.raw.bytes,
+ hash_alg );
+ }
+ else
+#endif /* MBEDCRYPTO_MD_C */
+ {
+ status = PSA_ERROR_NOT_SUPPORTED;
+ }
+
+exit:
+ if( status != PSA_SUCCESS )
+ {
+ psa_mac_abort( operation );
+ }
+ else
+ {
+ operation->key_set = 1;
+ }
+ return( status );
+}
+
+psa_status_t psa_mac_sign_setup( psa_mac_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg )
+{
+ return( psa_mac_setup( operation, key, alg, 1 ) );
+}
+
+psa_status_t psa_mac_verify_setup( psa_mac_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg )
+{
+ return( psa_mac_setup( operation, key, alg, 0 ) );
+}
+
+psa_status_t psa_mac_update( psa_mac_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length )
+{
+ psa_status_t status = PSA_ERROR_BAD_STATE;
+ if( ! operation->key_set )
+ goto cleanup;
+ if( operation->iv_required && ! operation->iv_set )
+ goto cleanup;
+ operation->has_input = 1;
+
+#if defined(MBEDCRYPTO_CMAC_C)
+ if( operation->alg == PSA_ALG_CMAC )
+ {
+ int ret = mbedcrypto_cipher_cmac_update( &operation->ctx.cmac,
+ input, input_length );
+ status = mbedcrypto_to_psa_error( ret );
+ }
+ else
+#endif /* MBEDCRYPTO_CMAC_C */
+#if defined(MBEDCRYPTO_MD_C)
+ if( PSA_ALG_IS_HMAC( operation->alg ) )
+ {
+ status = psa_hash_update( &operation->ctx.hmac.hash_ctx, input,
+ input_length );
+ }
+ else
+#endif /* MBEDCRYPTO_MD_C */
+ {
+ /* This shouldn't happen if `operation` was initialized by
+ * a setup function. */
+ status = PSA_ERROR_BAD_STATE;
+ }
+
+cleanup:
+ if( status != PSA_SUCCESS )
+ psa_mac_abort( operation );
+ return( status );
+}
+
+#if defined(MBEDCRYPTO_MD_C)
+static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac,
+ uint8_t *mac,
+ size_t mac_size )
+{
+ unsigned char tmp[MBEDCRYPTO_MD_MAX_SIZE];
+ psa_algorithm_t hash_alg = hmac->hash_ctx.alg;
+ size_t hash_size = 0;
+ size_t block_size = psa_get_hash_block_size( hash_alg );
+ psa_status_t status;
+
+ status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size );
+ if( status != PSA_SUCCESS )
+ return( status );
+ /* From here on, tmp needs to be wiped. */
+
+ status = psa_hash_setup( &hmac->hash_ctx, hash_alg );
+ if( status != PSA_SUCCESS )
+ goto exit;
+
+ status = psa_hash_update( &hmac->hash_ctx, hmac->opad, block_size );
+ if( status != PSA_SUCCESS )
+ goto exit;
+
+ status = psa_hash_update( &hmac->hash_ctx, tmp, hash_size );
+ if( status != PSA_SUCCESS )
+ goto exit;
+
+ status = psa_hash_finish( &hmac->hash_ctx, mac, mac_size, &hash_size );
+
+exit:
+ mbedcrypto_zeroize( tmp, hash_size );
+ return( status );
+}
+#endif /* MBEDCRYPTO_MD_C */
+
+static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation,
+ uint8_t *mac,
+ size_t mac_size )
+{
+ if( ! operation->key_set )
+ return( PSA_ERROR_BAD_STATE );
+ if( operation->iv_required && ! operation->iv_set )
+ return( PSA_ERROR_BAD_STATE );
+
+ if( mac_size < operation->mac_size )
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+#if defined(MBEDCRYPTO_CMAC_C)
+ if( operation->alg == PSA_ALG_CMAC )
+ {
+ int ret = mbedcrypto_cipher_cmac_finish( &operation->ctx.cmac, mac );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+ else
+#endif /* MBEDCRYPTO_CMAC_C */
+#if defined(MBEDCRYPTO_MD_C)
+ if( PSA_ALG_IS_HMAC( operation->alg ) )
+ {
+ return( psa_hmac_finish_internal( &operation->ctx.hmac,
+ mac, mac_size ) );
+ }
+ else
+#endif /* MBEDCRYPTO_MD_C */
+ {
+ /* This shouldn't happen if `operation` was initialized by
+ * a setup function. */
+ return( PSA_ERROR_BAD_STATE );
+ }
+}
+
+psa_status_t psa_mac_sign_finish( psa_mac_operation_t *operation,
+ uint8_t *mac,
+ size_t mac_size,
+ size_t *mac_length )
+{
+ psa_status_t status;
+
+ /* Fill the output buffer with something that isn't a valid mac
+ * (barring an attack on the mac and deliberately-crafted input),
+ * in case the caller doesn't check the return status properly. */
+ *mac_length = mac_size;
+ /* If mac_size is 0 then mac may be NULL and then the
+ * call to memset would have undefined behavior. */
+ if( mac_size != 0 )
+ memset( mac, '!', mac_size );
+
+ if( ! operation->is_sign )
+ {
+ status = PSA_ERROR_BAD_STATE;
+ goto cleanup;
+ }
+
+ status = psa_mac_finish_internal( operation, mac, mac_size );
+
+cleanup:
+ if( status == PSA_SUCCESS )
+ {
+ status = psa_mac_abort( operation );
+ if( status == PSA_SUCCESS )
+ *mac_length = operation->mac_size;
+ else
+ memset( mac, '!', mac_size );
+ }
+ else
+ psa_mac_abort( operation );
+ return( status );
+}
+
+psa_status_t psa_mac_verify_finish( psa_mac_operation_t *operation,
+ const uint8_t *mac,
+ size_t mac_length )
+{
+ uint8_t actual_mac[PSA_MAC_MAX_SIZE];
+ psa_status_t status;
+
+ if( operation->is_sign )
+ {
+ status = PSA_ERROR_BAD_STATE;
+ goto cleanup;
+ }
+ if( operation->mac_size != mac_length )
+ {
+ status = PSA_ERROR_INVALID_SIGNATURE;
+ goto cleanup;
+ }
+
+ status = psa_mac_finish_internal( operation,
+ actual_mac, sizeof( actual_mac ) );
+
+ if( safer_memcmp( mac, actual_mac, mac_length ) != 0 )
+ status = PSA_ERROR_INVALID_SIGNATURE;
+
+cleanup:
+ if( status == PSA_SUCCESS )
+ status = psa_mac_abort( operation );
+ else
+ psa_mac_abort( operation );
+
+ return( status );
+}
+
+
+
+/****************************************************************/
+/* Asymmetric cryptography */
+/****************************************************************/
+
+#if defined(MBEDCRYPTO_RSA_C)
+/* Decode the hash algorithm from alg and store the mbedcrypto encoding in
+ * md_alg. Verify that the hash length is acceptable. */
+static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg,
+ size_t hash_length,
+ mbedcrypto_md_type_t *md_alg )
+{
+ psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
+ const mbedcrypto_md_info_t *md_info = mbedcrypto_md_info_from_psa( hash_alg );
+ *md_alg = mbedcrypto_md_get_type( md_info );
+
+ /* The Mbed Crypto RSA module uses an unsigned int for hash length
+ * parameters. Validate that it fits so that we don't risk an
+ * overflow later. */
+#if SIZE_MAX > UINT_MAX
+ if( hash_length > UINT_MAX )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+#endif
+
+#if defined(MBEDCRYPTO_PKCS1_V15)
+ /* For PKCS#1 v1.5 signature, if using a hash, the hash length
+ * must be correct. */
+ if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) &&
+ alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW )
+ {
+ if( md_info == NULL )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ if( mbedcrypto_md_get_size( md_info ) != hash_length )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ }
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+ /* PSS requires a hash internally. */
+ if( PSA_ALG_IS_RSA_PSS( alg ) )
+ {
+ if( md_info == NULL )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+#endif /* MBEDCRYPTO_PKCS1_V21 */
+
+ return( PSA_SUCCESS );
+}
+
+static psa_status_t psa_rsa_sign( mbedcrypto_rsa_context *rsa,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ uint8_t *signature,
+ size_t signature_size,
+ size_t *signature_length )
+{
+ psa_status_t status;
+ int ret;
+ mbedcrypto_md_type_t md_alg;
+
+ status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( signature_size < mbedcrypto_rsa_get_len( rsa ) )
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+#if defined(MBEDCRYPTO_PKCS1_V15)
+ if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
+ {
+ mbedcrypto_rsa_set_padding( rsa, MBEDCRYPTO_RSA_PKCS_V15,
+ MBEDCRYPTO_MD_NONE );
+ ret = mbedcrypto_rsa_pkcs1_sign( rsa,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg,
+ MBEDCRYPTO_RSA_PRIVATE,
+ md_alg,
+ (unsigned int) hash_length,
+ hash,
+ signature );
+ }
+ else
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+#if defined(MBEDCRYPTO_PKCS1_V21)
+ if( PSA_ALG_IS_RSA_PSS( alg ) )
+ {
+ mbedcrypto_rsa_set_padding( rsa, MBEDCRYPTO_RSA_PKCS_V21, md_alg );
+ ret = mbedcrypto_rsa_rsassa_pss_sign( rsa,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg,
+ MBEDCRYPTO_RSA_PRIVATE,
+ MBEDCRYPTO_MD_NONE,
+ (unsigned int) hash_length,
+ hash,
+ signature );
+ }
+ else
+#endif /* MBEDCRYPTO_PKCS1_V21 */
+ {
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ }
+
+ if( ret == 0 )
+ *signature_length = mbedcrypto_rsa_get_len( rsa );
+ return( mbedcrypto_to_psa_error( ret ) );
+}
+
+static psa_status_t psa_rsa_verify( mbedcrypto_rsa_context *rsa,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ const uint8_t *signature,
+ size_t signature_length )
+{
+ psa_status_t status;
+ int ret;
+ mbedcrypto_md_type_t md_alg;
+
+ status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( signature_length < mbedcrypto_rsa_get_len( rsa ) )
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+#if defined(MBEDCRYPTO_PKCS1_V15)
+ if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
+ {
+ mbedcrypto_rsa_set_padding( rsa, MBEDCRYPTO_RSA_PKCS_V15,
+ MBEDCRYPTO_MD_NONE );
+ ret = mbedcrypto_rsa_pkcs1_verify( rsa,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg,
+ MBEDCRYPTO_RSA_PUBLIC,
+ md_alg,
+ (unsigned int) hash_length,
+ hash,
+ signature );
+ }
+ else
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+#if defined(MBEDCRYPTO_PKCS1_V21)
+ if( PSA_ALG_IS_RSA_PSS( alg ) )
+ {
+ mbedcrypto_rsa_set_padding( rsa, MBEDCRYPTO_RSA_PKCS_V21, md_alg );
+ ret = mbedcrypto_rsa_rsassa_pss_verify( rsa,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg,
+ MBEDCRYPTO_RSA_PUBLIC,
+ MBEDCRYPTO_MD_NONE,
+ (unsigned int) hash_length,
+ hash,
+ signature );
+ }
+ else
+#endif /* MBEDCRYPTO_PKCS1_V21 */
+ {
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ }
+ return( mbedcrypto_to_psa_error( ret ) );
+}
+#endif /* MBEDCRYPTO_RSA_C */
+
+#if defined(MBEDCRYPTO_ECDSA_C)
+/* `ecp` cannot be const because `ecp->grp` needs to be non-const
+ * for mbedcrypto_ecdsa_sign() and mbedcrypto_ecdsa_sign_det()
+ * (even though these functions don't modify it). */
+static psa_status_t psa_ecdsa_sign( mbedcrypto_ecp_keypair *ecp,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ uint8_t *signature,
+ size_t signature_size,
+ size_t *signature_length )
+{
+ int ret;
+ mbedcrypto_mpi r, s;
+ size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
+ mbedcrypto_mpi_init( &r );
+ mbedcrypto_mpi_init( &s );
+
+ if( signature_size < 2 * curve_bytes )
+ {
+ ret = MBEDCRYPTO_ERR_ECP_BUFFER_TOO_SMALL;
+ goto cleanup;
+ }
+
+ if( PSA_ALG_DSA_IS_DETERMINISTIC( alg ) )
+ {
+ psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
+ const mbedcrypto_md_info_t *md_info = mbedcrypto_md_info_from_psa( hash_alg );
+ mbedcrypto_md_type_t md_alg = mbedcrypto_md_get_type( md_info );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecdsa_sign_det( &ecp->grp, &r, &s, &ecp->d,
+ hash, hash_length,
+ md_alg ) );
+ }
+ else
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d,
+ hash, hash_length,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg ) );
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &r,
+ signature,
+ curve_bytes ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &s,
+ signature + curve_bytes,
+ curve_bytes ) );
+
+cleanup:
+ mbedcrypto_mpi_free( &r );
+ mbedcrypto_mpi_free( &s );
+ if( ret == 0 )
+ *signature_length = 2 * curve_bytes;
+ return( mbedcrypto_to_psa_error( ret ) );
+}
+
+static psa_status_t psa_ecdsa_verify( mbedcrypto_ecp_keypair *ecp,
+ const uint8_t *hash,
+ size_t hash_length,
+ const uint8_t *signature,
+ size_t signature_length )
+{
+ int ret;
+ mbedcrypto_mpi r, s;
+ size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
+ mbedcrypto_mpi_init( &r );
+ mbedcrypto_mpi_init( &s );
+
+ if( signature_length != 2 * curve_bytes )
+ return( PSA_ERROR_INVALID_SIGNATURE );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &r,
+ signature,
+ curve_bytes ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &s,
+ signature + curve_bytes,
+ curve_bytes ) );
+
+ ret = mbedcrypto_ecdsa_verify( &ecp->grp, hash, hash_length,
+ &ecp->Q, &r, &s );
+
+cleanup:
+ mbedcrypto_mpi_free( &r );
+ mbedcrypto_mpi_free( &s );
+ return( mbedcrypto_to_psa_error( ret ) );
+}
+#endif /* MBEDCRYPTO_ECDSA_C */
+
+psa_status_t psa_asymmetric_sign( psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ uint8_t *signature,
+ size_t signature_size,
+ size_t *signature_length )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ *signature_length = signature_size;
+
+ status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_SIGN, alg );
+ if( status != PSA_SUCCESS )
+ goto exit;
+ if( ! PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) )
+ {
+ status = PSA_ERROR_INVALID_ARGUMENT;
+ goto exit;
+ }
+
+#if defined(MBEDCRYPTO_RSA_C)
+ if( slot->type == PSA_KEY_TYPE_RSA_KEYPAIR )
+ {
+ status = psa_rsa_sign( slot->data.rsa,
+ alg,
+ hash, hash_length,
+ signature, signature_size,
+ signature_length );
+ }
+ else
+#endif /* defined(MBEDCRYPTO_RSA_C) */
+#if defined(MBEDCRYPTO_ECP_C)
+ if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
+ {
+#if defined(MBEDCRYPTO_ECDSA_C)
+ if( PSA_ALG_IS_ECDSA( alg ) )
+ status = psa_ecdsa_sign( slot->data.ecp,
+ alg,
+ hash, hash_length,
+ signature, signature_size,
+ signature_length );
+ else
+#endif /* defined(MBEDCRYPTO_ECDSA_C) */
+ {
+ status = PSA_ERROR_INVALID_ARGUMENT;
+ }
+ }
+ else
+#endif /* defined(MBEDCRYPTO_ECP_C) */
+ {
+ status = PSA_ERROR_NOT_SUPPORTED;
+ }
+
+exit:
+ /* Fill the unused part of the output buffer (the whole buffer on error,
+ * the trailing part on success) with something that isn't a valid mac
+ * (barring an attack on the mac and deliberately-crafted input),
+ * in case the caller doesn't check the return status properly. */
+ if( status == PSA_SUCCESS )
+ memset( signature + *signature_length, '!',
+ signature_size - *signature_length );
+ else if( signature_size != 0 )
+ memset( signature, '!', signature_size );
+ /* If signature_size is 0 then we have nothing to do. We must not call
+ * memset because signature may be NULL in this case. */
+ return( status );
+}
+
+psa_status_t psa_asymmetric_verify( psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ const uint8_t *signature,
+ size_t signature_length )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_VERIFY, alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+#if defined(MBEDCRYPTO_RSA_C)
+ if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+ {
+ return( psa_rsa_verify( slot->data.rsa,
+ alg,
+ hash, hash_length,
+ signature, signature_length ) );
+ }
+ else
+#endif /* defined(MBEDCRYPTO_RSA_C) */
+#if defined(MBEDCRYPTO_ECP_C)
+ if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
+ {
+#if defined(MBEDCRYPTO_ECDSA_C)
+ if( PSA_ALG_IS_ECDSA( alg ) )
+ return( psa_ecdsa_verify( slot->data.ecp,
+ hash, hash_length,
+ signature, signature_length ) );
+ else
+#endif /* defined(MBEDCRYPTO_ECDSA_C) */
+ {
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ }
+ }
+ else
+#endif /* defined(MBEDCRYPTO_ECP_C) */
+ {
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+}
+
+#if defined(MBEDCRYPTO_RSA_C) && defined(MBEDCRYPTO_PKCS1_V21)
+static void psa_rsa_oaep_set_padding_mode( psa_algorithm_t alg,
+ mbedcrypto_rsa_context *rsa )
+{
+ psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH( alg );
+ const mbedcrypto_md_info_t *md_info = mbedcrypto_md_info_from_psa( hash_alg );
+ mbedcrypto_md_type_t md_alg = mbedcrypto_md_get_type( md_info );
+ mbedcrypto_rsa_set_padding( rsa, MBEDCRYPTO_RSA_PKCS_V21, md_alg );
+}
+#endif /* defined(MBEDCRYPTO_RSA_C) && defined(MBEDCRYPTO_PKCS1_V21) */
+
+psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *input,
+ size_t input_length,
+ const uint8_t *salt,
+ size_t salt_length,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ (void) input;
+ (void) input_length;
+ (void) salt;
+ (void) output;
+ (void) output_size;
+
+ *output_length = 0;
+
+ if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+ if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) ||
+ PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) ) )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+#if defined(MBEDCRYPTO_RSA_C)
+ if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+ {
+ mbedcrypto_rsa_context *rsa = slot->data.rsa;
+ int ret;
+ if( output_size < mbedcrypto_rsa_get_len( rsa ) )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+#if defined(MBEDCRYPTO_PKCS1_V15)
+ if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT )
+ {
+ ret = mbedcrypto_rsa_pkcs1_encrypt( rsa,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg,
+ MBEDCRYPTO_RSA_PUBLIC,
+ input_length,
+ input,
+ output );
+ }
+ else
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+#if defined(MBEDCRYPTO_PKCS1_V21)
+ if( PSA_ALG_IS_RSA_OAEP( alg ) )
+ {
+ psa_rsa_oaep_set_padding_mode( alg, rsa );
+ ret = mbedcrypto_rsa_rsaes_oaep_encrypt( rsa,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg,
+ MBEDCRYPTO_RSA_PUBLIC,
+ salt, salt_length,
+ input_length,
+ input,
+ output );
+ }
+ else
+#endif /* MBEDCRYPTO_PKCS1_V21 */
+ {
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ }
+ if( ret == 0 )
+ *output_length = mbedcrypto_rsa_get_len( rsa );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+ else
+#endif /* defined(MBEDCRYPTO_RSA_C) */
+ {
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+}
+
+psa_status_t psa_asymmetric_decrypt( psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *input,
+ size_t input_length,
+ const uint8_t *salt,
+ size_t salt_length,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ (void) input;
+ (void) input_length;
+ (void) salt;
+ (void) output;
+ (void) output_size;
+
+ *output_length = 0;
+
+ if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DECRYPT, alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+ if( ! PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+#if defined(MBEDCRYPTO_RSA_C)
+ if( slot->type == PSA_KEY_TYPE_RSA_KEYPAIR )
+ {
+ mbedcrypto_rsa_context *rsa = slot->data.rsa;
+ int ret;
+
+ if( input_length != mbedcrypto_rsa_get_len( rsa ) )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+#if defined(MBEDCRYPTO_PKCS1_V15)
+ if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT )
+ {
+ ret = mbedcrypto_rsa_pkcs1_decrypt( rsa,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg,
+ MBEDCRYPTO_RSA_PRIVATE,
+ output_length,
+ input,
+ output,
+ output_size );
+ }
+ else
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+#if defined(MBEDCRYPTO_PKCS1_V21)
+ if( PSA_ALG_IS_RSA_OAEP( alg ) )
+ {
+ psa_rsa_oaep_set_padding_mode( alg, rsa );
+ ret = mbedcrypto_rsa_rsaes_oaep_decrypt( rsa,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg,
+ MBEDCRYPTO_RSA_PRIVATE,
+ salt, salt_length,
+ output_length,
+ input,
+ output,
+ output_size );
+ }
+ else
+#endif /* MBEDCRYPTO_PKCS1_V21 */
+ {
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ }
+
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+ else
+#endif /* defined(MBEDCRYPTO_RSA_C) */
+ {
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+}
+
+
+
+/****************************************************************/
+/* Symmetric cryptography */
+/****************************************************************/
+
+/* Initialize the cipher operation structure. Once this function has been
+ * called, psa_cipher_abort can run and will do the right thing. */
+static psa_status_t psa_cipher_init( psa_cipher_operation_t *operation,
+ psa_algorithm_t alg )
+{
+ if( ! PSA_ALG_IS_CIPHER( alg ) )
+ {
+ memset( operation, 0, sizeof( *operation ) );
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ }
+
+ operation->alg = alg;
+ operation->key_set = 0;
+ operation->iv_set = 0;
+ operation->iv_required = 1;
+ operation->iv_size = 0;
+ operation->block_size = 0;
+ mbedcrypto_cipher_init( &operation->ctx.cipher );
+ return( PSA_SUCCESS );
+}
+
+static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg,
+ mbedcrypto_operation_t cipher_operation )
+{
+ int ret = MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ psa_status_t status;
+ key_slot_t *slot;
+ size_t key_bits;
+ const mbedcrypto_cipher_info_t *cipher_info = NULL;
+ psa_key_usage_t usage = ( cipher_operation == MBEDCRYPTO_ENCRYPT ?
+ PSA_KEY_USAGE_ENCRYPT :
+ PSA_KEY_USAGE_DECRYPT );
+
+ status = psa_cipher_init( operation, alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ status = psa_get_key_from_slot( key, &slot, usage, alg);
+ if( status != PSA_SUCCESS )
+ return( status );
+ key_bits = psa_get_key_bits( slot );
+
+ cipher_info = mbedcrypto_cipher_info_from_psa( alg, slot->type, key_bits, NULL );
+ if( cipher_info == NULL )
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ ret = mbedcrypto_cipher_setup( &operation->ctx.cipher, cipher_info );
+ if( ret != 0 )
+ {
+ psa_cipher_abort( operation );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+
+#if defined(MBEDCRYPTO_DES_C)
+ if( slot->type == PSA_KEY_TYPE_DES && key_bits == 128 )
+ {
+ /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
+ unsigned char keys[24];
+ memcpy( keys, slot->data.raw.data, 16 );
+ memcpy( keys + 16, slot->data.raw.data, 8 );
+ ret = mbedcrypto_cipher_setkey( &operation->ctx.cipher,
+ keys,
+ 192, cipher_operation );
+ }
+ else
+#endif
+ {
+ ret = mbedcrypto_cipher_setkey( &operation->ctx.cipher,
+ slot->data.raw.data,
+ (int) key_bits, cipher_operation );
+ }
+ if( ret != 0 )
+ {
+ psa_cipher_abort( operation );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_WITH_PADDING)
+ if( ( alg & ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK ) == PSA_ALG_CBC_BASE )
+ {
+ psa_algorithm_t padding_mode = alg & PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
+ mbedcrypto_cipher_padding_t mode;
+
+ switch ( padding_mode )
+ {
+ case PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:
+ mode = MBEDCRYPTO_PADDING_PKCS7;
+ break;
+ case PSA_ALG_BLOCK_CIPHER_PAD_NONE:
+ mode = MBEDCRYPTO_PADDING_NONE;
+ break;
+ default:
+ psa_cipher_abort( operation );
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ }
+ ret = mbedcrypto_cipher_set_padding_mode( &operation->ctx.cipher, mode );
+ if( ret != 0 )
+ {
+ psa_cipher_abort( operation );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+ }
+#endif //MBEDCRYPTO_CIPHER_MODE_WITH_PADDING
+
+ operation->key_set = 1;
+ operation->block_size = ( PSA_ALG_IS_BLOCK_CIPHER( alg ) ?
+ PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type ) :
+ 1 );
+ if( PSA_ALG_IS_BLOCK_CIPHER( alg ) || alg == PSA_ALG_CTR )
+ {
+ operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type );
+ }
+
+ return( PSA_SUCCESS );
+}
+
+psa_status_t psa_cipher_encrypt_setup( psa_cipher_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg )
+{
+ return( psa_cipher_setup( operation, key, alg, MBEDCRYPTO_ENCRYPT ) );
+}
+
+psa_status_t psa_cipher_decrypt_setup( psa_cipher_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg )
+{
+ return( psa_cipher_setup( operation, key, alg, MBEDCRYPTO_DECRYPT ) );
+}
+
+psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation,
+ unsigned char *iv,
+ size_t iv_size,
+ size_t *iv_length )
+{
+ int ret = PSA_SUCCESS;
+ if( operation->iv_set || ! operation->iv_required )
+ return( PSA_ERROR_BAD_STATE );
+ if( iv_size < operation->iv_size )
+ {
+ ret = PSA_ERROR_BUFFER_TOO_SMALL;
+ goto exit;
+ }
+ ret = mbedcrypto_ctr_drbg_random( &global_data.ctr_drbg,
+ iv, operation->iv_size );
+ if( ret != 0 )
+ {
+ ret = mbedcrypto_to_psa_error( ret );
+ goto exit;
+ }
+
+ *iv_length = operation->iv_size;
+ ret = psa_cipher_set_iv( operation, iv, *iv_length );
+
+exit:
+ if( ret != PSA_SUCCESS )
+ psa_cipher_abort( operation );
+ return( ret );
+}
+
+psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation,
+ const unsigned char *iv,
+ size_t iv_length )
+{
+ int ret = PSA_SUCCESS;
+ if( operation->iv_set || ! operation->iv_required )
+ return( PSA_ERROR_BAD_STATE );
+ if( iv_length != operation->iv_size )
+ {
+ psa_cipher_abort( operation );
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ }
+ ret = mbedcrypto_cipher_set_iv( &operation->ctx.cipher, iv, iv_length );
+ if( ret != 0 )
+ {
+ psa_cipher_abort( operation );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+
+ operation->iv_set = 1;
+
+ return( PSA_SUCCESS );
+}
+
+psa_status_t psa_cipher_update( psa_cipher_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length,
+ unsigned char *output,
+ size_t output_size,
+ size_t *output_length )
+{
+ int ret = MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ size_t expected_output_size;
+ if( PSA_ALG_IS_BLOCK_CIPHER( operation->alg ) )
+ {
+ /* Take the unprocessed partial block left over from previous
+ * update calls, if any, plus the input to this call. Remove
+ * the last partial block, if any. You get the data that will be
+ * output in this call. */
+ expected_output_size =
+ ( operation->ctx.cipher.unprocessed_len + input_length )
+ / operation->block_size * operation->block_size;
+ }
+ else
+ {
+ expected_output_size = input_length;
+ }
+ if( output_size < expected_output_size )
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+ ret = mbedcrypto_cipher_update( &operation->ctx.cipher, input,
+ input_length, output, output_length );
+ if( ret != 0 )
+ {
+ psa_cipher_abort( operation );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+
+ return( PSA_SUCCESS );
+}
+
+psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length )
+{
+ psa_status_t status = PSA_ERROR_UNKNOWN_ERROR;
+ int cipher_ret = MBEDCRYPTO_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ uint8_t temp_output_buffer[MBEDCRYPTO_MAX_BLOCK_LENGTH];
+
+ if( ! operation->key_set )
+ {
+ status = PSA_ERROR_BAD_STATE;
+ goto error;
+ }
+ if( operation->iv_required && ! operation->iv_set )
+ {
+ status = PSA_ERROR_BAD_STATE;
+ goto error;
+ }
+ if( operation->ctx.cipher.operation == MBEDCRYPTO_ENCRYPT &&
+ PSA_ALG_IS_BLOCK_CIPHER( operation->alg ) )
+ {
+ psa_algorithm_t padding_mode =
+ operation->alg & PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
+ if( operation->ctx.cipher.unprocessed_len >= operation->block_size )
+ {
+ status = PSA_ERROR_TAMPERING_DETECTED;
+ goto error;
+ }
+ if( padding_mode == PSA_ALG_BLOCK_CIPHER_PAD_NONE )
+ {
+ if( operation->ctx.cipher.unprocessed_len != 0 )
+ {
+ status = PSA_ERROR_INVALID_ARGUMENT;
+ goto error;
+ }
+ }
+ }
+
+ cipher_ret = mbedcrypto_cipher_finish( &operation->ctx.cipher,
+ temp_output_buffer,
+ output_length );
+ if( cipher_ret != 0 )
+ {
+ status = mbedcrypto_to_psa_error( cipher_ret );
+ goto error;
+ }
+
+ if( *output_length == 0 )
+ ; /* Nothing to copy. Note that output may be NULL in this case. */
+ else if( output_size >= *output_length )
+ memcpy( output, temp_output_buffer, *output_length );
+ else
+ {
+ status = PSA_ERROR_BUFFER_TOO_SMALL;
+ goto error;
+ }
+
+ mbedcrypto_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) );
+ status = psa_cipher_abort( operation );
+
+ return( status );
+
+error:
+
+ *output_length = 0;
+
+ mbedcrypto_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) );
+ (void) psa_cipher_abort( operation );
+
+ return( status );
+}
+
+psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation )
+{
+ if( operation->alg == 0 )
+ {
+ /* The object has (apparently) been initialized but it is not
+ * in use. It's ok to call abort on such an object, and there's
+ * nothing to do. */
+ return( PSA_SUCCESS );
+ }
+
+ /* Sanity check (shouldn't happen: operation->alg should
+ * always have been initialized to a valid value). */
+ if( ! PSA_ALG_IS_CIPHER( operation->alg ) )
+ return( PSA_ERROR_BAD_STATE );
+
+ mbedcrypto_cipher_free( &operation->ctx.cipher );
+
+ operation->alg = 0;
+ operation->key_set = 0;
+ operation->iv_set = 0;
+ operation->iv_size = 0;
+ operation->block_size = 0;
+ operation->iv_required = 0;
+
+ return( PSA_SUCCESS );
+}
+
+
+
+/****************************************************************/
+/* Key Policy */
+/****************************************************************/
+
+#if !defined(MBEDCRYPTO_PSA_CRYPTO_SPM)
+void psa_key_policy_init( psa_key_policy_t *policy )
+{
+ memset( policy, 0, sizeof( *policy ) );
+}
+
+void psa_key_policy_set_usage( psa_key_policy_t *policy,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ policy->usage = usage;
+ policy->alg = alg;
+}
+
+psa_key_usage_t psa_key_policy_get_usage( const psa_key_policy_t *policy )
+{
+ return( policy->usage );
+}
+
+psa_algorithm_t psa_key_policy_get_algorithm( const psa_key_policy_t *policy )
+{
+ return( policy->alg );
+}
+#endif /* !defined(MBEDCRYPTO_PSA_CRYPTO_SPM) */
+
+psa_status_t psa_set_key_policy( psa_key_slot_t key,
+ const psa_key_policy_t *policy )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ if( policy == NULL )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ status = psa_get_empty_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT |
+ PSA_KEY_USAGE_ENCRYPT |
+ PSA_KEY_USAGE_DECRYPT |
+ PSA_KEY_USAGE_SIGN |
+ PSA_KEY_USAGE_VERIFY |
+ PSA_KEY_USAGE_DERIVE ) ) != 0 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ slot->policy = *policy;
+
+ return( PSA_SUCCESS );
+}
+
+psa_status_t psa_get_key_policy( psa_key_slot_t key,
+ psa_key_policy_t *policy )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ if( policy == NULL )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ status = psa_get_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ *policy = slot->policy;
+
+ return( PSA_SUCCESS );
+}
+
+
+
+/****************************************************************/
+/* Key Lifetime */
+/****************************************************************/
+
+psa_status_t psa_get_key_lifetime( psa_key_slot_t key,
+ psa_key_lifetime_t *lifetime )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ status = psa_get_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ *lifetime = slot->lifetime;
+
+ return( PSA_SUCCESS );
+}
+
+psa_status_t psa_set_key_lifetime( psa_key_slot_t key,
+ psa_key_lifetime_t lifetime )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ if( lifetime != PSA_KEY_LIFETIME_VOLATILE &&
+ lifetime != PSA_KEY_LIFETIME_PERSISTENT &&
+ lifetime != PSA_KEY_LIFETIME_WRITE_ONCE)
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ status = psa_get_empty_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( lifetime != PSA_KEY_LIFETIME_VOLATILE )
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ slot->lifetime = lifetime;
+
+ return( PSA_SUCCESS );
+}
+
+
+
+/****************************************************************/
+/* AEAD */
+/****************************************************************/
+
+psa_status_t psa_aead_encrypt( psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce,
+ size_t nonce_length,
+ const uint8_t *additional_data,
+ size_t additional_data_length,
+ const uint8_t *plaintext,
+ size_t plaintext_length,
+ uint8_t *ciphertext,
+ size_t ciphertext_size,
+ size_t *ciphertext_length )
+{
+ int ret;
+ psa_status_t status;
+ key_slot_t *slot;
+ size_t key_bits;
+ uint8_t *tag;
+ size_t tag_length;
+ mbedcrypto_cipher_id_t cipher_id;
+ const mbedcrypto_cipher_info_t *cipher_info = NULL;
+
+ *ciphertext_length = 0;
+
+ status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+ key_bits = psa_get_key_bits( slot );
+
+ cipher_info = mbedcrypto_cipher_info_from_psa( alg, slot->type,
+ key_bits, &cipher_id );
+ if( cipher_info == NULL )
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ if( ( slot->type & PSA_KEY_TYPE_CATEGORY_MASK ) !=
+ PSA_KEY_TYPE_CATEGORY_SYMMETRIC )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ if( alg == PSA_ALG_GCM )
+ {
+ mbedcrypto_gcm_context gcm;
+ tag_length = 16;
+
+ if( PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type ) != 16 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ //make sure we have place to hold the tag in the ciphertext buffer
+ if( ciphertext_size < ( plaintext_length + tag_length ) )
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+ //update the tag pointer to point to the end of the ciphertext_length
+ tag = ciphertext + plaintext_length;
+
+ mbedcrypto_gcm_init( &gcm );
+ ret = mbedcrypto_gcm_setkey( &gcm, cipher_id,
+ slot->data.raw.data,
+ (unsigned int) key_bits );
+ if( ret != 0 )
+ {
+ mbedcrypto_gcm_free( &gcm );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+ ret = mbedcrypto_gcm_crypt_and_tag( &gcm, MBEDCRYPTO_GCM_ENCRYPT,
+ plaintext_length, nonce,
+ nonce_length, additional_data,
+ additional_data_length, plaintext,
+ ciphertext, tag_length, tag );
+ mbedcrypto_gcm_free( &gcm );
+ }
+ else if( alg == PSA_ALG_CCM )
+ {
+ mbedcrypto_ccm_context ccm;
+ tag_length = 16;
+
+ if( PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type ) != 16 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ if( nonce_length < 7 || nonce_length > 13 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ //make sure we have place to hold the tag in the ciphertext buffer
+ if( ciphertext_size < ( plaintext_length + tag_length ) )
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+ //update the tag pointer to point to the end of the ciphertext_length
+ tag = ciphertext + plaintext_length;
+
+ mbedcrypto_ccm_init( &ccm );
+ ret = mbedcrypto_ccm_setkey( &ccm, cipher_id,
+ slot->data.raw.data,
+ (unsigned int) key_bits );
+ if( ret != 0 )
+ {
+ mbedcrypto_ccm_free( &ccm );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+ ret = mbedcrypto_ccm_encrypt_and_tag( &ccm, plaintext_length,
+ nonce, nonce_length,
+ additional_data,
+ additional_data_length,
+ plaintext, ciphertext,
+ tag, tag_length );
+ mbedcrypto_ccm_free( &ccm );
+ }
+ else
+ {
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+
+ if( ret != 0 )
+ {
+ /* If ciphertext_size is 0 then ciphertext may be NULL and then the
+ * call to memset would have undefined behavior. */
+ if( ciphertext_size != 0 )
+ memset( ciphertext, 0, ciphertext_size );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+
+ *ciphertext_length = plaintext_length + tag_length;
+ return( PSA_SUCCESS );
+}
+
+/* Locate the tag in a ciphertext buffer containing the encrypted data
+ * followed by the tag. Return the length of the part preceding the tag in
+ * *plaintext_length. This is the size of the plaintext in modes where
+ * the encrypted data has the same size as the plaintext, such as
+ * CCM and GCM. */
+static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length,
+ const uint8_t *ciphertext,
+ size_t ciphertext_length,
+ size_t plaintext_size,
+ const uint8_t **p_tag )
+{
+ size_t payload_length;
+ if( tag_length > ciphertext_length )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ payload_length = ciphertext_length - tag_length;
+ if( payload_length > plaintext_size )
+ return( PSA_ERROR_BUFFER_TOO_SMALL );
+ *p_tag = ciphertext + payload_length;
+ return( PSA_SUCCESS );
+}
+
+psa_status_t psa_aead_decrypt( psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce,
+ size_t nonce_length,
+ const uint8_t *additional_data,
+ size_t additional_data_length,
+ const uint8_t *ciphertext,
+ size_t ciphertext_length,
+ uint8_t *plaintext,
+ size_t plaintext_size,
+ size_t *plaintext_length )
+{
+ int ret;
+ psa_status_t status;
+ key_slot_t *slot;
+ size_t key_bits;
+ const uint8_t *tag;
+ size_t tag_length;
+ mbedcrypto_cipher_id_t cipher_id;
+ const mbedcrypto_cipher_info_t *cipher_info = NULL;
+
+ *plaintext_length = 0;
+
+ status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DECRYPT, alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+ key_bits = psa_get_key_bits( slot );
+
+ cipher_info = mbedcrypto_cipher_info_from_psa( alg, slot->type,
+ key_bits, &cipher_id );
+ if( cipher_info == NULL )
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ if( ( slot->type & PSA_KEY_TYPE_CATEGORY_MASK ) !=
+ PSA_KEY_TYPE_CATEGORY_SYMMETRIC )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ if( alg == PSA_ALG_GCM )
+ {
+ mbedcrypto_gcm_context gcm;
+
+ tag_length = 16;
+ status = psa_aead_unpadded_locate_tag( tag_length,
+ ciphertext, ciphertext_length,
+ plaintext_size, &tag );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ mbedcrypto_gcm_init( &gcm );
+ ret = mbedcrypto_gcm_setkey( &gcm, cipher_id,
+ slot->data.raw.data,
+ (unsigned int) key_bits );
+ if( ret != 0 )
+ {
+ mbedcrypto_gcm_free( &gcm );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+
+ ret = mbedcrypto_gcm_auth_decrypt( &gcm,
+ ciphertext_length - tag_length,
+ nonce, nonce_length,
+ additional_data,
+ additional_data_length,
+ tag, tag_length,
+ ciphertext, plaintext );
+ mbedcrypto_gcm_free( &gcm );
+ }
+ else if( alg == PSA_ALG_CCM )
+ {
+ mbedcrypto_ccm_context ccm;
+
+ if( nonce_length < 7 || nonce_length > 13 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ tag_length = 16;
+ status = psa_aead_unpadded_locate_tag( tag_length,
+ ciphertext, ciphertext_length,
+ plaintext_size, &tag );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ mbedcrypto_ccm_init( &ccm );
+ ret = mbedcrypto_ccm_setkey( &ccm, cipher_id,
+ slot->data.raw.data,
+ (unsigned int) key_bits );
+ if( ret != 0 )
+ {
+ mbedcrypto_ccm_free( &ccm );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+ ret = mbedcrypto_ccm_auth_decrypt( &ccm, ciphertext_length - tag_length,
+ nonce, nonce_length,
+ additional_data,
+ additional_data_length,
+ ciphertext, plaintext,
+ tag, tag_length );
+ mbedcrypto_ccm_free( &ccm );
+ }
+ else
+ {
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+
+ if( ret != 0 )
+ {
+ /* If plaintext_size is 0 then plaintext may be NULL and then the
+ * call to memset has undefined behavior. */
+ if( plaintext_size != 0 )
+ memset( plaintext, 0, plaintext_size );
+ }
+ else
+ *plaintext_length = ciphertext_length - tag_length;
+
+ return( mbedcrypto_to_psa_error( ret ) );
+}
+
+
+
+/****************************************************************/
+/* Generators */
+/****************************************************************/
+
+psa_status_t psa_generator_abort( psa_crypto_generator_t *generator )
+{
+ psa_status_t status = PSA_SUCCESS;
+ if( generator->alg == 0 )
+ {
+ /* The object has (apparently) been initialized but it is not
+ * in use. It's ok to call abort on such an object, and there's
+ * nothing to do. */
+ }
+ else
+#if defined(MBEDCRYPTO_MD_C)
+ if( PSA_ALG_IS_HKDF( generator->alg ) )
+ {
+ mbedcrypto_free( generator->ctx.hkdf.info );
+ status = psa_hmac_abort_internal( &generator->ctx.hkdf.hmac );
+ }
+ else
+#endif /* MBEDCRYPTO_MD_C */
+ {
+ status = PSA_ERROR_BAD_STATE;
+ }
+ memset( generator, 0, sizeof( *generator ) );
+ return( status );
+}
+
+
+psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator,
+ size_t *capacity)
+{
+ *capacity = generator->capacity;
+ return( PSA_SUCCESS );
+}
+
+#if defined(MBEDCRYPTO_MD_C)
+/* Read some bytes from an HKDF-based generator. This performs a chunk
+ * of the expand phase of the HKDF algorithm. */
+static psa_status_t psa_generator_hkdf_read( psa_hkdf_generator_t *hkdf,
+ psa_algorithm_t hash_alg,
+ uint8_t *output,
+ size_t output_length )
+{
+ uint8_t hash_length = PSA_HASH_SIZE( hash_alg );
+ psa_status_t status;
+
+ while( output_length != 0 )
+ {
+ /* Copy what remains of the current block */
+ uint8_t n = hash_length - hkdf->offset_in_block;
+ if( n > output_length )
+ n = (uint8_t) output_length;
+ memcpy( output, hkdf->output_block + hkdf->offset_in_block, n );
+ output += n;
+ output_length -= n;
+ hkdf->offset_in_block += n;
+ if( output_length == 0 )
+ break;
+ /* We can't be wanting more output after block 0xff, otherwise
+ * the capacity check in psa_generator_read() would have
+ * prevented this call. It could happen only if the generator
+ * object was corrupted or if this function is called directly
+ * inside the library. */
+ if( hkdf->block_number == 0xff )
+ return( PSA_ERROR_BAD_STATE );
+
+ /* We need a new block */
+ ++hkdf->block_number;
+ hkdf->offset_in_block = 0;
+ status = psa_hmac_setup_internal( &hkdf->hmac,
+ hkdf->prk, hash_length,
+ hash_alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+ if( hkdf->block_number != 1 )
+ {
+ status = psa_hash_update( &hkdf->hmac.hash_ctx,
+ hkdf->output_block,
+ hash_length );
+ if( status != PSA_SUCCESS )
+ return( status );
+ }
+ status = psa_hash_update( &hkdf->hmac.hash_ctx,
+ hkdf->info,
+ hkdf->info_length );
+ if( status != PSA_SUCCESS )
+ return( status );
+ status = psa_hash_update( &hkdf->hmac.hash_ctx,
+ &hkdf->block_number, 1 );
+ if( status != PSA_SUCCESS )
+ return( status );
+ status = psa_hmac_finish_internal( &hkdf->hmac,
+ hkdf->output_block,
+ sizeof( hkdf->output_block ) );
+ if( status != PSA_SUCCESS )
+ return( status );
+ }
+
+ return( PSA_SUCCESS );
+}
+#endif /* MBEDCRYPTO_MD_C */
+
+psa_status_t psa_generator_read( psa_crypto_generator_t *generator,
+ uint8_t *output,
+ size_t output_length )
+{
+ psa_status_t status;
+
+ if( output_length > generator->capacity )
+ {
+ generator->capacity = 0;
+ /* Go through the error path to wipe all confidential data now
+ * that the generator object is useless. */
+ status = PSA_ERROR_INSUFFICIENT_CAPACITY;
+ goto exit;
+ }
+ if( output_length == 0 &&
+ generator->capacity == 0 && generator->alg == 0 )
+ {
+ /* Edge case: this is a blank or finished generator, and 0
+ * bytes were requested. The right error in this case could
+ * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return
+ * INSUFFICIENT_CAPACITY, which is right for a finished
+ * generator, for consistency with the case when
+ * output_length > 0. */
+ return( PSA_ERROR_INSUFFICIENT_CAPACITY );
+ }
+ generator->capacity -= output_length;
+
+#if defined(MBEDCRYPTO_MD_C)
+ if( PSA_ALG_IS_HKDF( generator->alg ) )
+ {
+ psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( generator->alg );
+ status = psa_generator_hkdf_read( &generator->ctx.hkdf, hash_alg,
+ output, output_length );
+ }
+ else
+#endif /* MBEDCRYPTO_MD_C */
+ {
+ return( PSA_ERROR_BAD_STATE );
+ }
+
+exit:
+ if( status != PSA_SUCCESS )
+ {
+ psa_generator_abort( generator );
+ memset( output, '!', output_length );
+ }
+ return( status );
+}
+
+#if defined(MBEDCRYPTO_DES_C)
+static void psa_des_set_key_parity( uint8_t *data, size_t data_size )
+{
+ if( data_size >= 8 )
+ mbedcrypto_des_key_set_parity( data );
+ if( data_size >= 16 )
+ mbedcrypto_des_key_set_parity( data + 8 );
+ if( data_size >= 24 )
+ mbedcrypto_des_key_set_parity( data + 16 );
+}
+#endif /* MBEDCRYPTO_DES_C */
+
+psa_status_t psa_generator_import_key( psa_key_slot_t key,
+ psa_key_type_t type,
+ size_t bits,
+ psa_crypto_generator_t *generator )
+{
+ uint8_t *data = NULL;
+ size_t bytes = PSA_BITS_TO_BYTES( bits );
+ psa_status_t status;
+
+ if( ! key_type_is_raw_bytes( type ) )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ if( bits % 8 != 0 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ data = mbedcrypto_calloc( 1, bytes );
+ if( data == NULL )
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+
+ status = psa_generator_read( generator, data, bytes );
+ if( status != PSA_SUCCESS )
+ goto exit;
+#if defined(MBEDCRYPTO_DES_C)
+ if( type == PSA_KEY_TYPE_DES )
+ psa_des_set_key_parity( data, bytes );
+#endif /* MBEDCRYPTO_DES_C */
+ status = psa_import_key( key, type, data, bytes );
+
+exit:
+ mbedcrypto_free( data );
+ return( status );
+}
+
+
+
+/****************************************************************/
+/* Key derivation */
+/****************************************************************/
+
+/* Set up an HKDF-based generator. This is exactly the extract phase
+ * of the HKDF algorithm. */
+static psa_status_t psa_generator_hkdf_setup( psa_hkdf_generator_t *hkdf,
+ key_slot_t *slot,
+ psa_algorithm_t hash_alg,
+ const uint8_t *salt,
+ size_t salt_length,
+ const uint8_t *label,
+ size_t label_length )
+{
+ psa_status_t status;
+ status = psa_hmac_setup_internal( &hkdf->hmac,
+ salt, salt_length,
+ PSA_ALG_HMAC_HASH( hash_alg ) );
+ if( status != PSA_SUCCESS )
+ return( status );
+ status = psa_hash_update( &hkdf->hmac.hash_ctx,
+ slot->data.raw.data,
+ slot->data.raw.bytes );
+ if( status != PSA_SUCCESS )
+ return( status );
+ status = psa_hmac_finish_internal( &hkdf->hmac,
+ hkdf->prk,
+ sizeof( hkdf->prk ) );
+ if( status != PSA_SUCCESS )
+ return( status );
+ hkdf->offset_in_block = PSA_HASH_SIZE( hash_alg );
+ hkdf->block_number = 0;
+ hkdf->info_length = label_length;
+ if( label_length != 0 )
+ {
+ hkdf->info = mbedcrypto_calloc( 1, label_length );
+ if( hkdf->info == NULL )
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ memcpy( hkdf->info, label, label_length );
+ }
+ return( PSA_SUCCESS );
+}
+
+psa_status_t psa_key_derivation( psa_crypto_generator_t *generator,
+ psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *salt,
+ size_t salt_length,
+ const uint8_t *label,
+ size_t label_length,
+ size_t capacity )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ if( generator->alg != 0 )
+ return( PSA_ERROR_BAD_STATE );
+
+ status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DERIVE, alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+ if( slot->type != PSA_KEY_TYPE_DERIVE )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ if( ! PSA_ALG_IS_KEY_DERIVATION( alg ) )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+#if defined(MBEDCRYPTO_MD_C)
+ if( PSA_ALG_IS_HKDF( alg ) )
+ {
+ psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg );
+ size_t hash_size = PSA_HASH_SIZE( hash_alg );
+ if( hash_size == 0 )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ if( capacity > 255 * hash_size )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ status = psa_generator_hkdf_setup( &generator->ctx.hkdf,
+ slot,
+ hash_alg,
+ salt, salt_length,
+ label, label_length );
+ }
+ else
+#endif
+ {
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+
+ /* Set generator->alg even on failure so that abort knows what to do. */
+ generator->alg = alg;
+ if( status == PSA_SUCCESS )
+ generator->capacity = capacity;
+ else
+ psa_generator_abort( generator );
+ return( status );
+}
+
+
+
+/****************************************************************/
+/* Random generation */
+/****************************************************************/
+
+psa_status_t psa_generate_random( uint8_t *output,
+ size_t output_size )
+{
+ int ret = mbedcrypto_ctr_drbg_random( &global_data.ctr_drbg,
+ output, output_size );
+ return( mbedcrypto_to_psa_error( ret ) );
+}
+
+psa_status_t psa_generate_key( psa_key_slot_t key,
+ psa_key_type_t type,
+ size_t bits,
+ const void *extra,
+ size_t extra_size )
+{
+ key_slot_t *slot;
+ psa_status_t status;
+
+ if( extra == NULL && extra_size != 0 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ status = psa_get_empty_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( key_type_is_raw_bytes( type ) )
+ {
+ status = prepare_raw_data_slot( type, bits, &slot->data.raw );
+ if( status != PSA_SUCCESS )
+ return( status );
+ status = psa_generate_random( slot->data.raw.data,
+ slot->data.raw.bytes );
+ if( status != PSA_SUCCESS )
+ {
+ mbedcrypto_free( slot->data.raw.data );
+ return( status );
+ }
+#if defined(MBEDCRYPTO_DES_C)
+ if( type == PSA_KEY_TYPE_DES )
+ psa_des_set_key_parity( slot->data.raw.data,
+ slot->data.raw.bytes );
+#endif /* MBEDCRYPTO_DES_C */
+ }
+ else
+
+#if defined(MBEDCRYPTO_RSA_C) && defined(MBEDCRYPTO_GENPRIME)
+ if ( type == PSA_KEY_TYPE_RSA_KEYPAIR )
+ {
+ mbedcrypto_rsa_context *rsa;
+ int ret;
+ int exponent = 65537;
+ if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ if( extra != NULL )
+ {
+ const psa_generate_key_extra_rsa *p = extra;
+ if( extra_size != sizeof( *p ) )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+#if INT_MAX < 0xffffffff
+ /* Check that the uint32_t value passed by the caller fits
+ * in the range supported by this implementation. */
+ if( p->e > INT_MAX )
+ return( PSA_ERROR_NOT_SUPPORTED );
+#endif
+ exponent = p->e;
+ }
+ rsa = mbedcrypto_calloc( 1, sizeof( *rsa ) );
+ if( rsa == NULL )
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ mbedcrypto_rsa_init( rsa, MBEDCRYPTO_RSA_PKCS_V15, MBEDCRYPTO_MD_NONE );
+ ret = mbedcrypto_rsa_gen_key( rsa,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg,
+ (unsigned int) bits,
+ exponent );
+ if( ret != 0 )
+ {
+ mbedcrypto_rsa_free( rsa );
+ mbedcrypto_free( rsa );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+ slot->data.rsa = rsa;
+ }
+ else
+#endif /* MBEDCRYPTO_RSA_C && MBEDCRYPTO_GENPRIME */
+
+#if defined(MBEDCRYPTO_ECP_C)
+ if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEYPAIR( type ) )
+ {
+ psa_ecc_curve_t curve = PSA_KEY_TYPE_GET_CURVE( type );
+ mbedcrypto_ecp_group_id grp_id = mbedcrypto_ecc_group_of_psa( curve );
+ const mbedcrypto_ecp_curve_info *curve_info =
+ mbedcrypto_ecp_curve_info_from_grp_id( grp_id );
+ mbedcrypto_ecp_keypair *ecp;
+ int ret;
+ if( extra != NULL )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ if( grp_id == MBEDCRYPTO_ECP_DP_NONE || curve_info == NULL )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ if( curve_info->bit_size != bits )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ ecp = mbedcrypto_calloc( 1, sizeof( *ecp ) );
+ if( ecp == NULL )
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ mbedcrypto_ecp_keypair_init( ecp );
+ ret = mbedcrypto_ecp_gen_key( grp_id, ecp,
+ mbedcrypto_ctr_drbg_random,
+ &global_data.ctr_drbg );
+ if( ret != 0 )
+ {
+ mbedcrypto_ecp_keypair_free( ecp );
+ mbedcrypto_free( ecp );
+ return( mbedcrypto_to_psa_error( ret ) );
+ }
+ slot->data.ecp = ecp;
+ }
+ else
+#endif /* MBEDCRYPTO_ECP_C */
+
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ slot->type = type;
+ return( PSA_SUCCESS );
+}
+
+
+/****************************************************************/
+/* Module setup */
+/****************************************************************/
+
+void mbedcrypto_psa_crypto_free( void )
+{
+ psa_key_slot_t key;
+ for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ )
+ psa_destroy_key( key );
+ mbedcrypto_ctr_drbg_free( &global_data.ctr_drbg );
+ mbedcrypto_entropy_free( &global_data.entropy );
+ mbedcrypto_zeroize( &global_data, sizeof( global_data ) );
+}
+
+psa_status_t psa_crypto_init( void )
+{
+ int ret;
+ const unsigned char drbg_seed[] = "PSA";
+
+ if( global_data.initialized != 0 )
+ return( PSA_SUCCESS );
+
+ mbedcrypto_zeroize( &global_data, sizeof( global_data ) );
+ mbedcrypto_entropy_init( &global_data.entropy );
+ mbedcrypto_ctr_drbg_init( &global_data.ctr_drbg );
+
+ ret = mbedcrypto_ctr_drbg_seed( &global_data.ctr_drbg,
+ mbedcrypto_entropy_func,
+ &global_data.entropy,
+ drbg_seed, sizeof( drbg_seed ) - 1 );
+ if( ret != 0 )
+ goto exit;
+
+ global_data.initialized = 1;
+
+exit:
+ if( ret != 0 )
+ mbedcrypto_psa_crypto_free( );
+ return( mbedcrypto_to_psa_error( ret ) );
+}
+
+#endif /* MBEDCRYPTO_PSA_CRYPTO_C */
diff --git a/library/ripemd160.c b/library/ripemd160.c
new file mode 100644
index 0000000..fc86887
--- /dev/null
+++ b/library/ripemd160.c
@@ -0,0 +1,552 @@
+/*
+ * RIPE MD-160 implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * The RIPEMD-160 algorithm was designed by RIPE in 1996
+ * http://homes.esat.kuleuven.be/~bosselae/mbedcrypto_ripemd160.html
+ * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_RIPEMD160_C)
+
+#include "mbedcrypto/ripemd160.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_RIPEMD160_ALT)
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
+ (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
+ (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
+ (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
+}
+#endif
+
+void mbedcrypto_ripemd160_init( mbedcrypto_ripemd160_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_ripemd160_context ) );
+}
+
+void mbedcrypto_ripemd160_free( mbedcrypto_ripemd160_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_ripemd160_context ) );
+}
+
+void mbedcrypto_ripemd160_clone( mbedcrypto_ripemd160_context *dst,
+ const mbedcrypto_ripemd160_context *src )
+{
+ *dst = *src;
+}
+
+/*
+ * RIPEMD-160 context setup
+ */
+int mbedcrypto_ripemd160_starts_ret( mbedcrypto_ripemd160_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_ripemd160_starts( mbedcrypto_ripemd160_context *ctx )
+{
+ mbedcrypto_ripemd160_starts_ret( ctx );
+}
+#endif
+
+#if !defined(MBEDCRYPTO_RIPEMD160_PROCESS_ALT)
+/*
+ * Process one block
+ */
+int mbedcrypto_internal_ripemd160_process( mbedcrypto_ripemd160_context *ctx,
+ const unsigned char data[64] )
+{
+ uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16];
+
+ GET_UINT32_LE( X[ 0], data, 0 );
+ GET_UINT32_LE( X[ 1], data, 4 );
+ GET_UINT32_LE( X[ 2], data, 8 );
+ GET_UINT32_LE( X[ 3], data, 12 );
+ GET_UINT32_LE( X[ 4], data, 16 );
+ GET_UINT32_LE( X[ 5], data, 20 );
+ GET_UINT32_LE( X[ 6], data, 24 );
+ GET_UINT32_LE( X[ 7], data, 28 );
+ GET_UINT32_LE( X[ 8], data, 32 );
+ GET_UINT32_LE( X[ 9], data, 36 );
+ GET_UINT32_LE( X[10], data, 40 );
+ GET_UINT32_LE( X[11], data, 44 );
+ GET_UINT32_LE( X[12], data, 48 );
+ GET_UINT32_LE( X[13], data, 52 );
+ GET_UINT32_LE( X[14], data, 56 );
+ GET_UINT32_LE( X[15], data, 60 );
+
+ A = Ap = ctx->state[0];
+ B = Bp = ctx->state[1];
+ C = Cp = ctx->state[2];
+ D = Dp = ctx->state[3];
+ E = Ep = ctx->state[4];
+
+#define F1( x, y, z ) ( x ^ y ^ z )
+#define F2( x, y, z ) ( ( x & y ) | ( ~x & z ) )
+#define F3( x, y, z ) ( ( x | ~y ) ^ z )
+#define F4( x, y, z ) ( ( x & z ) | ( y & ~z ) )
+#define F5( x, y, z ) ( x ^ ( y | ~z ) )
+
+#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) )
+
+#define P( a, b, c, d, e, r, s, f, k ) \
+ a += f( b, c, d ) + X[r] + k; \
+ a = S( a, s ) + e; \
+ c = S( c, 10 );
+
+#define P2( a, b, c, d, e, r, s, rp, sp ) \
+ P( a, b, c, d, e, r, s, F, K ); \
+ P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp );
+
+#define F F1
+#define K 0x00000000
+#define Fp F5
+#define Kp 0x50A28BE6
+ P2( A, B, C, D, E, 0, 11, 5, 8 );
+ P2( E, A, B, C, D, 1, 14, 14, 9 );
+ P2( D, E, A, B, C, 2, 15, 7, 9 );
+ P2( C, D, E, A, B, 3, 12, 0, 11 );
+ P2( B, C, D, E, A, 4, 5, 9, 13 );
+ P2( A, B, C, D, E, 5, 8, 2, 15 );
+ P2( E, A, B, C, D, 6, 7, 11, 15 );
+ P2( D, E, A, B, C, 7, 9, 4, 5 );
+ P2( C, D, E, A, B, 8, 11, 13, 7 );
+ P2( B, C, D, E, A, 9, 13, 6, 7 );
+ P2( A, B, C, D, E, 10, 14, 15, 8 );
+ P2( E, A, B, C, D, 11, 15, 8, 11 );
+ P2( D, E, A, B, C, 12, 6, 1, 14 );
+ P2( C, D, E, A, B, 13, 7, 10, 14 );
+ P2( B, C, D, E, A, 14, 9, 3, 12 );
+ P2( A, B, C, D, E, 15, 8, 12, 6 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F F2
+#define K 0x5A827999
+#define Fp F4
+#define Kp 0x5C4DD124
+ P2( E, A, B, C, D, 7, 7, 6, 9 );
+ P2( D, E, A, B, C, 4, 6, 11, 13 );
+ P2( C, D, E, A, B, 13, 8, 3, 15 );
+ P2( B, C, D, E, A, 1, 13, 7, 7 );
+ P2( A, B, C, D, E, 10, 11, 0, 12 );
+ P2( E, A, B, C, D, 6, 9, 13, 8 );
+ P2( D, E, A, B, C, 15, 7, 5, 9 );
+ P2( C, D, E, A, B, 3, 15, 10, 11 );
+ P2( B, C, D, E, A, 12, 7, 14, 7 );
+ P2( A, B, C, D, E, 0, 12, 15, 7 );
+ P2( E, A, B, C, D, 9, 15, 8, 12 );
+ P2( D, E, A, B, C, 5, 9, 12, 7 );
+ P2( C, D, E, A, B, 2, 11, 4, 6 );
+ P2( B, C, D, E, A, 14, 7, 9, 15 );
+ P2( A, B, C, D, E, 11, 13, 1, 13 );
+ P2( E, A, B, C, D, 8, 12, 2, 11 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F F3
+#define K 0x6ED9EBA1
+#define Fp F3
+#define Kp 0x6D703EF3
+ P2( D, E, A, B, C, 3, 11, 15, 9 );
+ P2( C, D, E, A, B, 10, 13, 5, 7 );
+ P2( B, C, D, E, A, 14, 6, 1, 15 );
+ P2( A, B, C, D, E, 4, 7, 3, 11 );
+ P2( E, A, B, C, D, 9, 14, 7, 8 );
+ P2( D, E, A, B, C, 15, 9, 14, 6 );
+ P2( C, D, E, A, B, 8, 13, 6, 6 );
+ P2( B, C, D, E, A, 1, 15, 9, 14 );
+ P2( A, B, C, D, E, 2, 14, 11, 12 );
+ P2( E, A, B, C, D, 7, 8, 8, 13 );
+ P2( D, E, A, B, C, 0, 13, 12, 5 );
+ P2( C, D, E, A, B, 6, 6, 2, 14 );
+ P2( B, C, D, E, A, 13, 5, 10, 13 );
+ P2( A, B, C, D, E, 11, 12, 0, 13 );
+ P2( E, A, B, C, D, 5, 7, 4, 7 );
+ P2( D, E, A, B, C, 12, 5, 13, 5 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F F4
+#define K 0x8F1BBCDC
+#define Fp F2
+#define Kp 0x7A6D76E9
+ P2( C, D, E, A, B, 1, 11, 8, 15 );
+ P2( B, C, D, E, A, 9, 12, 6, 5 );
+ P2( A, B, C, D, E, 11, 14, 4, 8 );
+ P2( E, A, B, C, D, 10, 15, 1, 11 );
+ P2( D, E, A, B, C, 0, 14, 3, 14 );
+ P2( C, D, E, A, B, 8, 15, 11, 14 );
+ P2( B, C, D, E, A, 12, 9, 15, 6 );
+ P2( A, B, C, D, E, 4, 8, 0, 14 );
+ P2( E, A, B, C, D, 13, 9, 5, 6 );
+ P2( D, E, A, B, C, 3, 14, 12, 9 );
+ P2( C, D, E, A, B, 7, 5, 2, 12 );
+ P2( B, C, D, E, A, 15, 6, 13, 9 );
+ P2( A, B, C, D, E, 14, 8, 9, 12 );
+ P2( E, A, B, C, D, 5, 6, 7, 5 );
+ P2( D, E, A, B, C, 6, 5, 10, 15 );
+ P2( C, D, E, A, B, 2, 12, 14, 8 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+#define F F5
+#define K 0xA953FD4E
+#define Fp F1
+#define Kp 0x00000000
+ P2( B, C, D, E, A, 4, 9, 12, 8 );
+ P2( A, B, C, D, E, 0, 15, 15, 5 );
+ P2( E, A, B, C, D, 5, 5, 10, 12 );
+ P2( D, E, A, B, C, 9, 11, 4, 9 );
+ P2( C, D, E, A, B, 7, 6, 1, 12 );
+ P2( B, C, D, E, A, 12, 8, 5, 5 );
+ P2( A, B, C, D, E, 2, 13, 8, 14 );
+ P2( E, A, B, C, D, 10, 12, 7, 6 );
+ P2( D, E, A, B, C, 14, 5, 6, 8 );
+ P2( C, D, E, A, B, 1, 12, 2, 13 );
+ P2( B, C, D, E, A, 3, 13, 13, 6 );
+ P2( A, B, C, D, E, 8, 14, 14, 5 );
+ P2( E, A, B, C, D, 11, 11, 0, 15 );
+ P2( D, E, A, B, C, 6, 8, 3, 13 );
+ P2( C, D, E, A, B, 15, 5, 9, 11 );
+ P2( B, C, D, E, A, 13, 6, 11, 11 );
+#undef F
+#undef K
+#undef Fp
+#undef Kp
+
+ C = ctx->state[1] + C + Dp;
+ ctx->state[1] = ctx->state[2] + D + Ep;
+ ctx->state[2] = ctx->state[3] + E + Ap;
+ ctx->state[3] = ctx->state[4] + A + Bp;
+ ctx->state[4] = ctx->state[0] + B + Cp;
+ ctx->state[0] = C;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_ripemd160_process( mbedcrypto_ripemd160_context *ctx,
+ const unsigned char data[64] )
+{
+ mbedcrypto_internal_ripemd160_process( ctx, data );
+}
+#endif
+#endif /* !MBEDCRYPTO_RIPEMD160_PROCESS_ALT */
+
+/*
+ * RIPEMD-160 process buffer
+ */
+int mbedcrypto_ripemd160_update_ret( mbedcrypto_ripemd160_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ int ret;
+ size_t fill;
+ uint32_t left;
+
+ if( ilen == 0 )
+ return( 0 );
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+
+ if( ( ret = mbedcrypto_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ if( ( ret = mbedcrypto_internal_ripemd160_process( ctx, input ) ) != 0 )
+ return( ret );
+
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+ }
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_ripemd160_update( mbedcrypto_ripemd160_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ mbedcrypto_ripemd160_update_ret( ctx, input, ilen );
+}
+#endif
+
+static const unsigned char ripemd160_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * RIPEMD-160 final digest
+ */
+int mbedcrypto_ripemd160_finish_ret( mbedcrypto_ripemd160_context *ctx,
+ unsigned char output[20] )
+{
+ int ret;
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_LE( low, msglen, 0 );
+ PUT_UINT32_LE( high, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ ret = mbedcrypto_ripemd160_update_ret( ctx, ripemd160_padding, padn );
+ if( ret != 0 )
+ return( ret );
+
+ ret = mbedcrypto_ripemd160_update_ret( ctx, msglen, 8 );
+ if( ret != 0 )
+ return( ret );
+
+ PUT_UINT32_LE( ctx->state[0], output, 0 );
+ PUT_UINT32_LE( ctx->state[1], output, 4 );
+ PUT_UINT32_LE( ctx->state[2], output, 8 );
+ PUT_UINT32_LE( ctx->state[3], output, 12 );
+ PUT_UINT32_LE( ctx->state[4], output, 16 );
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_ripemd160_finish( mbedcrypto_ripemd160_context *ctx,
+ unsigned char output[20] )
+{
+ mbedcrypto_ripemd160_finish_ret( ctx, output );
+}
+#endif
+
+#endif /* ! MBEDCRYPTO_RIPEMD160_ALT */
+
+/*
+ * output = RIPEMD-160( input buffer )
+ */
+int mbedcrypto_ripemd160_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[20] )
+{
+ int ret;
+ mbedcrypto_ripemd160_context ctx;
+
+ mbedcrypto_ripemd160_init( &ctx );
+
+ if( ( ret = mbedcrypto_ripemd160_starts_ret( &ctx ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_ripemd160_finish_ret( &ctx, output ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedcrypto_ripemd160_free( &ctx );
+
+ return( ret );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_ripemd160( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[20] )
+{
+ mbedcrypto_ripemd160_ret( input, ilen, output );
+}
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/*
+ * Test vectors from the RIPEMD-160 paper and
+ * http://homes.esat.kuleuven.be/~bosselae/mbedcrypto_ripemd160.html#HMAC
+ */
+#define TESTS 8
+static const unsigned char ripemd160_test_str[TESTS][81] =
+{
+ { "" },
+ { "a" },
+ { "abc" },
+ { "message digest" },
+ { "abcdefghijklmnopqrstuvwxyz" },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+ { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
+ { "12345678901234567890123456789012345678901234567890123456789012"
+ "345678901234567890" },
+};
+
+static const size_t ripemd160_test_strlen[TESTS] =
+{
+ 0, 1, 3, 14, 26, 56, 62, 80
+};
+
+static const unsigned char ripemd160_test_md[TESTS][20] =
+{
+ { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28,
+ 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 },
+ { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae,
+ 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe },
+ { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04,
+ 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc },
+ { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8,
+ 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 },
+ { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb,
+ 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc },
+ { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05,
+ 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b },
+ { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed,
+ 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 },
+ { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb,
+ 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb },
+};
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_ripemd160_self_test( int verbose )
+{
+ int i, ret = 0;
+ unsigned char output[20];
+
+ memset( output, 0, sizeof output );
+
+ for( i = 0; i < TESTS; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " RIPEMD-160 test #%d: ", i + 1 );
+
+ ret = mbedcrypto_ripemd160_ret( ripemd160_test_str[i],
+ ripemd160_test_strlen[i], output );
+ if( ret != 0 )
+ goto fail;
+
+ if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 )
+ {
+ ret = 1;
+ goto fail;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ return( 0 );
+
+fail:
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_RIPEMD160_C */
diff --git a/library/rsa.c b/library/rsa.c
new file mode 100644
index 0000000..698d1b1
--- /dev/null
+++ b/library/rsa.c
@@ -0,0 +1,2411 @@
+/*
+ * The RSA public-key cryptosystem
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/*
+ * The following sources were referenced in the design of this implementation
+ * of the RSA algorithm:
+ *
+ * [1] A method for obtaining digital signatures and public-key cryptosystems
+ * R Rivest, A Shamir, and L Adleman
+ * http://people.csail.mit.edu/rivest/pubs.html#RSA78
+ *
+ * [2] Handbook of Applied Cryptography - 1997, Chapter 8
+ * Menezes, van Oorschot and Vanstone
+ *
+ * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks
+ * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and
+ * Stefan Mangard
+ * https://arxiv.org/abs/1702.08719v2
+ *
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C)
+
+#include "mbedcrypto/rsa.h"
+#include "mbedcrypto/rsa_internal.h"
+#include "mbedcrypto/oid.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+#include "mbedcrypto/md.h"
+#endif
+
+#if defined(MBEDCRYPTO_PKCS1_V15) && !defined(__OpenBSD__)
+#include <stdlib.h>
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif
+
+#if !defined(MBEDCRYPTO_RSA_ALT)
+
+#if defined(MBEDCRYPTO_PKCS1_V15)
+/* constant-time buffer comparison */
+static inline int mbedcrypto_safer_memcmp( const void *a, const void *b, size_t n )
+{
+ size_t i;
+ const unsigned char *A = (const unsigned char *) a;
+ const unsigned char *B = (const unsigned char *) b;
+ unsigned char diff = 0;
+
+ for( i = 0; i < n; i++ )
+ diff |= A[i] ^ B[i];
+
+ return( diff );
+}
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+
+int mbedcrypto_rsa_import( mbedcrypto_rsa_context *ctx,
+ const mbedcrypto_mpi *N,
+ const mbedcrypto_mpi *P, const mbedcrypto_mpi *Q,
+ const mbedcrypto_mpi *D, const mbedcrypto_mpi *E )
+{
+ int ret;
+
+ if( ( N != NULL && ( ret = mbedcrypto_mpi_copy( &ctx->N, N ) ) != 0 ) ||
+ ( P != NULL && ( ret = mbedcrypto_mpi_copy( &ctx->P, P ) ) != 0 ) ||
+ ( Q != NULL && ( ret = mbedcrypto_mpi_copy( &ctx->Q, Q ) ) != 0 ) ||
+ ( D != NULL && ( ret = mbedcrypto_mpi_copy( &ctx->D, D ) ) != 0 ) ||
+ ( E != NULL && ( ret = mbedcrypto_mpi_copy( &ctx->E, E ) ) != 0 ) )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA + ret );
+ }
+
+ if( N != NULL )
+ ctx->len = mbedcrypto_mpi_size( &ctx->N );
+
+ return( 0 );
+}
+
+int mbedcrypto_rsa_import_raw( mbedcrypto_rsa_context *ctx,
+ unsigned char const *N, size_t N_len,
+ unsigned char const *P, size_t P_len,
+ unsigned char const *Q, size_t Q_len,
+ unsigned char const *D, size_t D_len,
+ unsigned char const *E, size_t E_len )
+{
+ int ret = 0;
+
+ if( N != NULL )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &ctx->N, N, N_len ) );
+ ctx->len = mbedcrypto_mpi_size( &ctx->N );
+ }
+
+ if( P != NULL )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &ctx->P, P, P_len ) );
+
+ if( Q != NULL )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &ctx->Q, Q, Q_len ) );
+
+ if( D != NULL )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &ctx->D, D, D_len ) );
+
+ if( E != NULL )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &ctx->E, E, E_len ) );
+
+cleanup:
+
+ if( ret != 0 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA + ret );
+
+ return( 0 );
+}
+
+/*
+ * Checks whether the context fields are set in such a way
+ * that the RSA primitives will be able to execute without error.
+ * It does *not* make guarantees for consistency of the parameters.
+ */
+static int rsa_check_context( mbedcrypto_rsa_context const *ctx, int is_priv,
+ int blinding_needed )
+{
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ /* blinding_needed is only used for NO_CRT to decide whether
+ * P,Q need to be present or not. */
+ ((void) blinding_needed);
+#endif
+
+ if( ctx->len != mbedcrypto_mpi_size( &ctx->N ) ||
+ ctx->len > MBEDCRYPTO_MPI_MAX_SIZE )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ /*
+ * 1. Modular exponentiation needs positive, odd moduli.
+ */
+
+ /* Modular exponentiation wrt. N is always used for
+ * RSA public key operations. */
+ if( mbedcrypto_mpi_cmp_int( &ctx->N, 0 ) <= 0 ||
+ mbedcrypto_mpi_get_bit( &ctx->N, 0 ) == 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ /* Modular exponentiation for P and Q is only
+ * used for private key operations and if CRT
+ * is used. */
+ if( is_priv &&
+ ( mbedcrypto_mpi_cmp_int( &ctx->P, 0 ) <= 0 ||
+ mbedcrypto_mpi_get_bit( &ctx->P, 0 ) == 0 ||
+ mbedcrypto_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ||
+ mbedcrypto_mpi_get_bit( &ctx->Q, 0 ) == 0 ) )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ }
+#endif /* !MBEDCRYPTO_RSA_NO_CRT */
+
+ /*
+ * 2. Exponents must be positive
+ */
+
+ /* Always need E for public key operations */
+ if( mbedcrypto_mpi_cmp_int( &ctx->E, 0 ) <= 0 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+#if defined(MBEDCRYPTO_RSA_NO_CRT)
+ /* For private key operations, use D or DP & DQ
+ * as (unblinded) exponents. */
+ if( is_priv && mbedcrypto_mpi_cmp_int( &ctx->D, 0 ) <= 0 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+#else
+ if( is_priv &&
+ ( mbedcrypto_mpi_cmp_int( &ctx->DP, 0 ) <= 0 ||
+ mbedcrypto_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ }
+#endif /* MBEDCRYPTO_RSA_NO_CRT */
+
+ /* Blinding shouldn't make exponents negative either,
+ * so check that P, Q >= 1 if that hasn't yet been
+ * done as part of 1. */
+#if defined(MBEDCRYPTO_RSA_NO_CRT)
+ if( is_priv && blinding_needed &&
+ ( mbedcrypto_mpi_cmp_int( &ctx->P, 0 ) <= 0 ||
+ mbedcrypto_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ }
+#endif
+
+ /* It wouldn't lead to an error if it wasn't satisfied,
+ * but check for QP >= 1 nonetheless. */
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ if( is_priv &&
+ mbedcrypto_mpi_cmp_int( &ctx->QP, 0 ) <= 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ }
+#endif
+
+ return( 0 );
+}
+
+int mbedcrypto_rsa_complete( mbedcrypto_rsa_context *ctx )
+{
+ int ret = 0;
+
+ const int have_N = ( mbedcrypto_mpi_cmp_int( &ctx->N, 0 ) != 0 );
+ const int have_P = ( mbedcrypto_mpi_cmp_int( &ctx->P, 0 ) != 0 );
+ const int have_Q = ( mbedcrypto_mpi_cmp_int( &ctx->Q, 0 ) != 0 );
+ const int have_D = ( mbedcrypto_mpi_cmp_int( &ctx->D, 0 ) != 0 );
+ const int have_E = ( mbedcrypto_mpi_cmp_int( &ctx->E, 0 ) != 0 );
+
+ /*
+ * Check whether provided parameters are enough
+ * to deduce all others. The following incomplete
+ * parameter sets for private keys are supported:
+ *
+ * (1) P, Q missing.
+ * (2) D and potentially N missing.
+ *
+ */
+
+ const int n_missing = have_P && have_Q && have_D && have_E;
+ const int pq_missing = have_N && !have_P && !have_Q && have_D && have_E;
+ const int d_missing = have_P && have_Q && !have_D && have_E;
+ const int is_pub = have_N && !have_P && !have_Q && !have_D && have_E;
+
+ /* These three alternatives are mutually exclusive */
+ const int is_priv = n_missing || pq_missing || d_missing;
+
+ if( !is_priv && !is_pub )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ /*
+ * Step 1: Deduce N if P, Q are provided.
+ */
+
+ if( !have_N && have_P && have_Q )
+ {
+ if( ( ret = mbedcrypto_mpi_mul_mpi( &ctx->N, &ctx->P,
+ &ctx->Q ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA + ret );
+ }
+
+ ctx->len = mbedcrypto_mpi_size( &ctx->N );
+ }
+
+ /*
+ * Step 2: Deduce and verify all remaining core parameters.
+ */
+
+ if( pq_missing )
+ {
+ ret = mbedcrypto_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D,
+ &ctx->P, &ctx->Q );
+ if( ret != 0 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA + ret );
+
+ }
+ else if( d_missing )
+ {
+ if( ( ret = mbedcrypto_rsa_deduce_private_exponent( &ctx->P,
+ &ctx->Q,
+ &ctx->E,
+ &ctx->D ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA + ret );
+ }
+ }
+
+ /*
+ * Step 3: Deduce all additional parameters specific
+ * to our current RSA implementation.
+ */
+
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ if( is_priv )
+ {
+ ret = mbedcrypto_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
+ &ctx->DP, &ctx->DQ, &ctx->QP );
+ if( ret != 0 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA + ret );
+ }
+#endif /* MBEDCRYPTO_RSA_NO_CRT */
+
+ /*
+ * Step 3: Basic sanity checks
+ */
+
+ return( rsa_check_context( ctx, is_priv, 1 ) );
+}
+
+int mbedcrypto_rsa_export_raw( const mbedcrypto_rsa_context *ctx,
+ unsigned char *N, size_t N_len,
+ unsigned char *P, size_t P_len,
+ unsigned char *Q, size_t Q_len,
+ unsigned char *D, size_t D_len,
+ unsigned char *E, size_t E_len )
+{
+ int ret = 0;
+
+ /* Check if key is private or public */
+ const int is_priv =
+ mbedcrypto_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->E, 0 ) != 0;
+
+ if( !is_priv )
+ {
+ /* If we're trying to export private parameters for a public key,
+ * something must be wrong. */
+ if( P != NULL || Q != NULL || D != NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ }
+
+ if( N != NULL )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &ctx->N, N, N_len ) );
+
+ if( P != NULL )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &ctx->P, P, P_len ) );
+
+ if( Q != NULL )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &ctx->Q, Q, Q_len ) );
+
+ if( D != NULL )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &ctx->D, D, D_len ) );
+
+ if( E != NULL )
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &ctx->E, E, E_len ) );
+
+cleanup:
+
+ return( ret );
+}
+
+int mbedcrypto_rsa_export( const mbedcrypto_rsa_context *ctx,
+ mbedcrypto_mpi *N, mbedcrypto_mpi *P, mbedcrypto_mpi *Q,
+ mbedcrypto_mpi *D, mbedcrypto_mpi *E )
+{
+ int ret;
+
+ /* Check if key is private or public */
+ int is_priv =
+ mbedcrypto_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->E, 0 ) != 0;
+
+ if( !is_priv )
+ {
+ /* If we're trying to export private parameters for a public key,
+ * something must be wrong. */
+ if( P != NULL || Q != NULL || D != NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ }
+
+ /* Export all requested core parameters. */
+
+ if( ( N != NULL && ( ret = mbedcrypto_mpi_copy( N, &ctx->N ) ) != 0 ) ||
+ ( P != NULL && ( ret = mbedcrypto_mpi_copy( P, &ctx->P ) ) != 0 ) ||
+ ( Q != NULL && ( ret = mbedcrypto_mpi_copy( Q, &ctx->Q ) ) != 0 ) ||
+ ( D != NULL && ( ret = mbedcrypto_mpi_copy( D, &ctx->D ) ) != 0 ) ||
+ ( E != NULL && ( ret = mbedcrypto_mpi_copy( E, &ctx->E ) ) != 0 ) )
+ {
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Export CRT parameters
+ * This must also be implemented if CRT is not used, for being able to
+ * write DER encoded RSA keys. The helper function mbedcrypto_rsa_deduce_crt
+ * can be used in this case.
+ */
+int mbedcrypto_rsa_export_crt( const mbedcrypto_rsa_context *ctx,
+ mbedcrypto_mpi *DP, mbedcrypto_mpi *DQ, mbedcrypto_mpi *QP )
+{
+ int ret;
+
+ /* Check if key is private or public */
+ int is_priv =
+ mbedcrypto_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
+ mbedcrypto_mpi_cmp_int( &ctx->E, 0 ) != 0;
+
+ if( !is_priv )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ /* Export all requested blinding parameters. */
+ if( ( DP != NULL && ( ret = mbedcrypto_mpi_copy( DP, &ctx->DP ) ) != 0 ) ||
+ ( DQ != NULL && ( ret = mbedcrypto_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) ||
+ ( QP != NULL && ( ret = mbedcrypto_mpi_copy( QP, &ctx->QP ) ) != 0 ) )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA + ret );
+ }
+#else
+ if( ( ret = mbedcrypto_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
+ DP, DQ, QP ) ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA + ret );
+ }
+#endif
+
+ return( 0 );
+}
+
+/*
+ * Initialize an RSA context
+ */
+void mbedcrypto_rsa_init( mbedcrypto_rsa_context *ctx,
+ int padding,
+ int hash_id )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_rsa_context ) );
+
+ mbedcrypto_rsa_set_padding( ctx, padding, hash_id );
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_mutex_init( &ctx->mutex );
+#endif
+}
+
+/*
+ * Set padding for an existing RSA context
+ */
+void mbedcrypto_rsa_set_padding( mbedcrypto_rsa_context *ctx, int padding, int hash_id )
+{
+ ctx->padding = padding;
+ ctx->hash_id = hash_id;
+}
+
+/*
+ * Get length in bytes of RSA modulus
+ */
+size_t mbedcrypto_rsa_get_len( const mbedcrypto_rsa_context *ctx )
+{
+ return( ctx->len );
+}
+
+/*
+ * Get length in bits of RSA modulus
+ */
+size_t mbedcrypto_rsa_get_bitlen( const mbedcrypto_rsa_context *ctx )
+{
+ return( mbedcrypto_mpi_bitlen( &ctx->N ) );
+}
+
+
+#if defined(MBEDCRYPTO_GENPRIME)
+
+/*
+ * Generate an RSA keypair
+ *
+ * This generation method follows the RSA key pair generation procedure of
+ * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072.
+ */
+int mbedcrypto_rsa_gen_key( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ unsigned int nbits, int exponent )
+{
+ int ret;
+ mbedcrypto_mpi H, G, L;
+
+ if( f_rng == NULL || nbits < 128 || exponent < 3 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ if( nbits % 2 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ mbedcrypto_mpi_init( &H );
+ mbedcrypto_mpi_init( &G );
+ mbedcrypto_mpi_init( &L );
+
+ /*
+ * find primes P and Q with Q < P so that:
+ * 1. |P-Q| > 2^( nbits / 2 - 100 )
+ * 2. GCD( E, (P-1)*(Q-1) ) == 1
+ * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 )
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_lset( &ctx->E, exponent ) );
+
+ do
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_gen_prime( &ctx->P, nbits >> 1, 0,
+ f_rng, p_rng ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_gen_prime( &ctx->Q, nbits >> 1, 0,
+ f_rng, p_rng ) );
+
+ /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) );
+ if( mbedcrypto_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) )
+ continue;
+
+ /* not required by any standards, but some users rely on the fact that P > Q */
+ if( H.s < 0 )
+ mbedcrypto_mpi_swap( &ctx->P, &ctx->Q );
+
+ /* Temporarily replace P,Q by P-1, Q-1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &ctx->P, &ctx->P, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) );
+
+ /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_gcd( &G, &ctx->E, &H ) );
+ if( mbedcrypto_mpi_cmp_int( &G, 1 ) != 0 )
+ continue;
+
+ /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_gcd( &G, &ctx->P, &ctx->Q ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_div_mpi( &L, NULL, &H, &G ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_inv_mod( &ctx->D, &ctx->E, &L ) );
+
+ if( mbedcrypto_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a))
+ continue;
+
+ break;
+ }
+ while( 1 );
+
+ /* Restore P,Q */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_int( &ctx->P, &ctx->P, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
+
+ ctx->len = mbedcrypto_mpi_size( &ctx->N );
+
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ /*
+ * DP = D mod (P - 1)
+ * DQ = D mod (Q - 1)
+ * QP = Q^-1 mod P
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
+ &ctx->DP, &ctx->DQ, &ctx->QP ) );
+#endif /* MBEDCRYPTO_RSA_NO_CRT */
+
+ /* Double-check */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_rsa_check_privkey( ctx ) );
+
+cleanup:
+
+ mbedcrypto_mpi_free( &H );
+ mbedcrypto_mpi_free( &G );
+ mbedcrypto_mpi_free( &L );
+
+ if( ret != 0 )
+ {
+ mbedcrypto_rsa_free( ctx );
+ return( MBEDCRYPTO_ERR_RSA_KEY_GEN_FAILED + ret );
+ }
+
+ return( 0 );
+}
+
+#endif /* MBEDCRYPTO_GENPRIME */
+
+/*
+ * Check a public RSA key
+ */
+int mbedcrypto_rsa_check_pubkey( const mbedcrypto_rsa_context *ctx )
+{
+ if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 )
+ return( MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED );
+
+ if( mbedcrypto_mpi_bitlen( &ctx->N ) < 128 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED );
+ }
+
+ if( mbedcrypto_mpi_get_bit( &ctx->E, 0 ) == 0 ||
+ mbedcrypto_mpi_bitlen( &ctx->E ) < 2 ||
+ mbedcrypto_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Check for the consistency of all fields in an RSA private key context
+ */
+int mbedcrypto_rsa_check_privkey( const mbedcrypto_rsa_context *ctx )
+{
+ if( mbedcrypto_rsa_check_pubkey( ctx ) != 0 ||
+ rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED );
+ }
+
+ if( mbedcrypto_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q,
+ &ctx->D, &ctx->E, NULL, NULL ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED );
+ }
+
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ else if( mbedcrypto_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D,
+ &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED );
+ }
+#endif
+
+ return( 0 );
+}
+
+/*
+ * Check if contexts holding a public and private key match
+ */
+int mbedcrypto_rsa_check_pub_priv( const mbedcrypto_rsa_context *pub,
+ const mbedcrypto_rsa_context *prv )
+{
+ if( mbedcrypto_rsa_check_pubkey( pub ) != 0 ||
+ mbedcrypto_rsa_check_privkey( prv ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED );
+ }
+
+ if( mbedcrypto_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 ||
+ mbedcrypto_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Do an RSA public key operation
+ */
+int mbedcrypto_rsa_public( mbedcrypto_rsa_context *ctx,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ size_t olen;
+ mbedcrypto_mpi T;
+
+ if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ mbedcrypto_mpi_init( &T );
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( ( ret = mbedcrypto_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &T, input, ctx->len ) );
+
+ if( mbedcrypto_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+ {
+ ret = MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+ olen = ctx->len;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( mbedcrypto_mutex_unlock( &ctx->mutex ) != 0 )
+ return( MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+ mbedcrypto_mpi_free( &T );
+
+ if( ret != 0 )
+ return( MBEDCRYPTO_ERR_RSA_PUBLIC_FAILED + ret );
+
+ return( 0 );
+}
+
+/*
+ * Generate or update blinding values, see section 10 of:
+ * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
+ * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
+ * Berlin Heidelberg, 1996. p. 104-113.
+ */
+static int rsa_prepare_blinding( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ int ret, count = 0;
+
+ if( ctx->Vf.p != NULL )
+ {
+ /* We already have blinding values, just update them by squaring */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) );
+
+ goto cleanup;
+ }
+
+ /* Unblinding value: Vf = random number, invertible mod N */
+ do {
+ if( count++ > 10 )
+ return( MBEDCRYPTO_ERR_RSA_RNG_FAILED );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) );
+ } while( mbedcrypto_mpi_cmp_int( &ctx->Vi, 1 ) != 0 );
+
+ /* Blinding value: Vi = Vf^(-e) mod N */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) );
+
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Exponent blinding supposed to prevent side-channel attacks using multiple
+ * traces of measurements to recover the RSA key. The more collisions are there,
+ * the more bits of the key can be recovered. See [3].
+ *
+ * Collecting n collisions with m bit long blinding value requires 2^(m-m/n)
+ * observations on avarage.
+ *
+ * For example with 28 byte blinding to achieve 2 collisions the adversary has
+ * to make 2^112 observations on avarage.
+ *
+ * (With the currently (as of 2017 April) known best algorithms breaking 2048
+ * bit RSA requires approximately as much time as trying out 2^112 random keys.
+ * Thus in this sense with 28 byte blinding the security is not reduced by
+ * side-channel attacks like the one in [3])
+ *
+ * This countermeasure does not help if the key recovery is possible with a
+ * single trace.
+ */
+#define RSA_EXPONENT_BLINDING 28
+
+/*
+ * Do an RSA private key operation
+ */
+int mbedcrypto_rsa_private( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ size_t olen;
+
+ /* Temporary holding the result */
+ mbedcrypto_mpi T;
+
+ /* Temporaries holding P-1, Q-1 and the
+ * exponent blinding factor, respectively. */
+ mbedcrypto_mpi P1, Q1, R;
+
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ /* Temporaries holding the results mod p resp. mod q. */
+ mbedcrypto_mpi TP, TQ;
+
+ /* Temporaries holding the blinded exponents for
+ * the mod p resp. mod q computation (if used). */
+ mbedcrypto_mpi DP_blind, DQ_blind;
+
+ /* Pointers to actual exponents to be used - either the unblinded
+ * or the blinded ones, depending on the presence of a PRNG. */
+ mbedcrypto_mpi *DP = &ctx->DP;
+ mbedcrypto_mpi *DQ = &ctx->DQ;
+#else
+ /* Temporary holding the blinded exponent (if used). */
+ mbedcrypto_mpi D_blind;
+
+ /* Pointer to actual exponent to be used - either the unblinded
+ * or the blinded one, depending on the presence of a PRNG. */
+ mbedcrypto_mpi *D = &ctx->D;
+#endif /* MBEDCRYPTO_RSA_NO_CRT */
+
+ /* Temporaries holding the initial input and the double
+ * checked result; should be the same in the end. */
+ mbedcrypto_mpi I, C;
+
+ if( rsa_check_context( ctx, 1 /* private key checks */,
+ f_rng != NULL /* blinding y/n */ ) != 0 )
+ {
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( ( ret = mbedcrypto_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ /* MPI Initialization */
+ mbedcrypto_mpi_init( &T );
+
+ mbedcrypto_mpi_init( &P1 );
+ mbedcrypto_mpi_init( &Q1 );
+ mbedcrypto_mpi_init( &R );
+
+ if( f_rng != NULL )
+ {
+#if defined(MBEDCRYPTO_RSA_NO_CRT)
+ mbedcrypto_mpi_init( &D_blind );
+#else
+ mbedcrypto_mpi_init( &DP_blind );
+ mbedcrypto_mpi_init( &DQ_blind );
+#endif
+ }
+
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ mbedcrypto_mpi_init( &TP ); mbedcrypto_mpi_init( &TQ );
+#endif
+
+ mbedcrypto_mpi_init( &I );
+ mbedcrypto_mpi_init( &C );
+
+ /* End of MPI initialization */
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_binary( &T, input, ctx->len ) );
+ if( mbedcrypto_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+ {
+ ret = MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &I, &T ) );
+
+ if( f_rng != NULL )
+ {
+ /*
+ * Blinding
+ * T = T * Vi mod N
+ */
+ MBEDCRYPTO_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T, &T, &ctx->Vi ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &T, &T, &ctx->N ) );
+
+ /*
+ * Exponent blinding
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &P1, &ctx->P, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+
+#if defined(MBEDCRYPTO_RSA_NO_CRT)
+ /*
+ * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( &R, RSA_EXPONENT_BLINDING,
+ f_rng, p_rng ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &D_blind, &P1, &Q1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &D_blind, &D_blind, &R ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) );
+
+ D = &D_blind;
+#else
+ /*
+ * DP_blind = ( P - 1 ) * R + DP
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( &R, RSA_EXPONENT_BLINDING,
+ f_rng, p_rng ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &DP_blind, &P1, &R ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &DP_blind, &DP_blind,
+ &ctx->DP ) );
+
+ DP = &DP_blind;
+
+ /*
+ * DQ_blind = ( Q - 1 ) * R + DQ
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_fill_random( &R, RSA_EXPONENT_BLINDING,
+ f_rng, p_rng ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &DQ_blind, &Q1, &R ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &DQ_blind, &DQ_blind,
+ &ctx->DQ ) );
+
+ DQ = &DQ_blind;
+#endif /* MBEDCRYPTO_RSA_NO_CRT */
+ }
+
+#if defined(MBEDCRYPTO_RSA_NO_CRT)
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) );
+#else
+ /*
+ * Faster decryption using the CRT
+ *
+ * TP = input ^ dP mod P
+ * TQ = input ^ dQ mod Q
+ */
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) );
+
+ /*
+ * T = (TP - TQ) * (Q^-1 mod P) mod P
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &T, &TP, &TQ ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &TP, &T, &ctx->QP ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &T, &TP, &ctx->P ) );
+
+ /*
+ * T = TQ + T * Q
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &TP, &T, &ctx->Q ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_mpi( &T, &TQ, &TP ) );
+#endif /* MBEDCRYPTO_RSA_NO_CRT */
+
+ if( f_rng != NULL )
+ {
+ /*
+ * Unblind
+ * T = T * Vf mod N
+ */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T, &T, &ctx->Vf ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &T, &T, &ctx->N ) );
+ }
+
+ /* Verify the result to prevent glitching attacks. */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_exp_mod( &C, &T, &ctx->E,
+ &ctx->N, &ctx->RN ) );
+ if( mbedcrypto_mpi_cmp_mpi( &C, &I ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_VERIFY_FAILED;
+ goto cleanup;
+ }
+
+ olen = ctx->len;
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+#if defined(MBEDCRYPTO_THREADING_C)
+ if( mbedcrypto_mutex_unlock( &ctx->mutex ) != 0 )
+ return( MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+ mbedcrypto_mpi_free( &P1 );
+ mbedcrypto_mpi_free( &Q1 );
+ mbedcrypto_mpi_free( &R );
+
+ if( f_rng != NULL )
+ {
+#if defined(MBEDCRYPTO_RSA_NO_CRT)
+ mbedcrypto_mpi_free( &D_blind );
+#else
+ mbedcrypto_mpi_free( &DP_blind );
+ mbedcrypto_mpi_free( &DQ_blind );
+#endif
+ }
+
+ mbedcrypto_mpi_free( &T );
+
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ mbedcrypto_mpi_free( &TP ); mbedcrypto_mpi_free( &TQ );
+#endif
+
+ mbedcrypto_mpi_free( &C );
+ mbedcrypto_mpi_free( &I );
+
+ if( ret != 0 )
+ return( MBEDCRYPTO_ERR_RSA_PRIVATE_FAILED + ret );
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+/**
+ * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.
+ *
+ * \param dst buffer to mask
+ * \param dlen length of destination buffer
+ * \param src source of the mask generation
+ * \param slen length of the source buffer
+ * \param md_ctx message digest context to use
+ */
+static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src,
+ size_t slen, mbedcrypto_md_context_t *md_ctx )
+{
+ unsigned char mask[MBEDCRYPTO_MD_MAX_SIZE];
+ unsigned char counter[4];
+ unsigned char *p;
+ unsigned int hlen;
+ size_t i, use_len;
+ int ret = 0;
+
+ memset( mask, 0, MBEDCRYPTO_MD_MAX_SIZE );
+ memset( counter, 0, 4 );
+
+ hlen = mbedcrypto_md_get_size( md_ctx->md_info );
+
+ /* Generate and apply dbMask */
+ p = dst;
+
+ while( dlen > 0 )
+ {
+ use_len = hlen;
+ if( dlen < hlen )
+ use_len = dlen;
+
+ if( ( ret = mbedcrypto_md_starts( md_ctx ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md_update( md_ctx, src, slen ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md_update( md_ctx, counter, 4 ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md_finish( md_ctx, mask ) ) != 0 )
+ goto exit;
+
+ for( i = 0; i < use_len; ++i )
+ *p++ ^= mask[i];
+
+ counter[3]++;
+
+ dlen -= use_len;
+ }
+
+exit:
+ mbedcrypto_platform_zeroize( mask, sizeof( mask ) );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_PKCS1_V21 */
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function
+ */
+int mbedcrypto_rsa_rsaes_oaep_encrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ const unsigned char *label, size_t label_len,
+ size_t ilen,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ size_t olen;
+ int ret;
+ unsigned char *p = output;
+ unsigned int hlen;
+ const mbedcrypto_md_info_t *md_info;
+ mbedcrypto_md_context_t md_ctx;
+
+ if( mode == MBEDCRYPTO_RSA_PRIVATE && ctx->padding != MBEDCRYPTO_RSA_PKCS_V21 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ if( f_rng == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ md_info = mbedcrypto_md_info_from_type( (mbedcrypto_md_type_t) ctx->hash_id );
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ olen = ctx->len;
+ hlen = mbedcrypto_md_get_size( md_info );
+
+ /* first comparison checks for overflow */
+ if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ memset( output, 0, olen );
+
+ *p++ = 0;
+
+ /* Generate a random octet string seed */
+ if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 )
+ return( MBEDCRYPTO_ERR_RSA_RNG_FAILED + ret );
+
+ p += hlen;
+
+ /* Construct DB */
+ if( ( ret = mbedcrypto_md( md_info, label, label_len, p ) ) != 0 )
+ return( ret );
+ p += hlen;
+ p += olen - 2 * hlen - 2 - ilen;
+ *p++ = 1;
+ if( ilen != 0 )
+ memcpy( p, input, ilen );
+
+ mbedcrypto_md_init( &md_ctx );
+ if( ( ret = mbedcrypto_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
+ goto exit;
+
+ /* maskedDB: Apply dbMask to DB */
+ if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,
+ &md_ctx ) ) != 0 )
+ goto exit;
+
+ /* maskedSeed: Apply seedMask to seed */
+ if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
+ &md_ctx ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedcrypto_md_free( &md_ctx );
+
+ if( ret != 0 )
+ return( ret );
+
+ return( ( mode == MBEDCRYPTO_RSA_PUBLIC )
+ ? mbedcrypto_rsa_public( ctx, output, output )
+ : mbedcrypto_rsa_private( ctx, f_rng, p_rng, output, output ) );
+}
+#endif /* MBEDCRYPTO_PKCS1_V21 */
+
+#if defined(MBEDCRYPTO_PKCS1_V15)
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function
+ */
+int mbedcrypto_rsa_rsaes_pkcs1_v15_encrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t ilen,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ size_t nb_pad, olen;
+ int ret;
+ unsigned char *p = output;
+
+ if( mode == MBEDCRYPTO_RSA_PRIVATE && ctx->padding != MBEDCRYPTO_RSA_PKCS_V15 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ // We don't check p_rng because it won't be dereferenced here
+ if( f_rng == NULL || output == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ if( ilen != 0 && input == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ olen = ctx->len;
+
+ /* first comparison checks for overflow */
+ if( ilen + 11 < ilen || olen < ilen + 11 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ nb_pad = olen - 3 - ilen;
+
+ *p++ = 0;
+ if( mode == MBEDCRYPTO_RSA_PUBLIC )
+ {
+ *p++ = MBEDCRYPTO_RSA_CRYPT;
+
+ while( nb_pad-- > 0 )
+ {
+ int rng_dl = 100;
+
+ do {
+ ret = f_rng( p_rng, p, 1 );
+ } while( *p == 0 && --rng_dl && ret == 0 );
+
+ /* Check if RNG failed to generate data */
+ if( rng_dl == 0 || ret != 0 )
+ return( MBEDCRYPTO_ERR_RSA_RNG_FAILED + ret );
+
+ p++;
+ }
+ }
+ else
+ {
+ *p++ = MBEDCRYPTO_RSA_SIGN;
+
+ while( nb_pad-- > 0 )
+ *p++ = 0xFF;
+ }
+
+ *p++ = 0;
+ if( ilen != 0 )
+ memcpy( p, input, ilen );
+
+ return( ( mode == MBEDCRYPTO_RSA_PUBLIC )
+ ? mbedcrypto_rsa_public( ctx, output, output )
+ : mbedcrypto_rsa_private( ctx, f_rng, p_rng, output, output ) );
+}
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+
+/*
+ * Add the message padding, then do an RSA operation
+ */
+int mbedcrypto_rsa_pkcs1_encrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t ilen,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ switch( ctx->padding )
+ {
+#if defined(MBEDCRYPTO_PKCS1_V15)
+ case MBEDCRYPTO_RSA_PKCS_V15:
+ return mbedcrypto_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen,
+ input, output );
+#endif
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+ case MBEDCRYPTO_RSA_PKCS_V21:
+ return mbedcrypto_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0,
+ ilen, input, output );
+#endif
+
+ default:
+ return( MBEDCRYPTO_ERR_RSA_INVALID_PADDING );
+ }
+}
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function
+ */
+int mbedcrypto_rsa_rsaes_oaep_decrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ const unsigned char *label, size_t label_len,
+ size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len )
+{
+ int ret;
+ size_t ilen, i, pad_len;
+ unsigned char *p, bad, pad_done;
+ unsigned char buf[MBEDCRYPTO_MPI_MAX_SIZE];
+ unsigned char lhash[MBEDCRYPTO_MD_MAX_SIZE];
+ unsigned int hlen;
+ const mbedcrypto_md_info_t *md_info;
+ mbedcrypto_md_context_t md_ctx;
+
+ /*
+ * Parameters sanity checks
+ */
+ if( mode == MBEDCRYPTO_RSA_PRIVATE && ctx->padding != MBEDCRYPTO_RSA_PKCS_V21 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ ilen = ctx->len;
+
+ if( ilen < 16 || ilen > sizeof( buf ) )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ md_info = mbedcrypto_md_info_from_type( (mbedcrypto_md_type_t) ctx->hash_id );
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ hlen = mbedcrypto_md_get_size( md_info );
+
+ // checking for integer underflow
+ if( 2 * hlen + 2 > ilen )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ /*
+ * RSA operation
+ */
+ ret = ( mode == MBEDCRYPTO_RSA_PUBLIC )
+ ? mbedcrypto_rsa_public( ctx, input, buf )
+ : mbedcrypto_rsa_private( ctx, f_rng, p_rng, input, buf );
+
+ if( ret != 0 )
+ goto cleanup;
+
+ /*
+ * Unmask data and generate lHash
+ */
+ mbedcrypto_md_init( &md_ctx );
+ if( ( ret = mbedcrypto_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
+ {
+ mbedcrypto_md_free( &md_ctx );
+ goto cleanup;
+ }
+
+ /* seed: Apply seedMask to maskedSeed */
+ if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
+ &md_ctx ) ) != 0 ||
+ /* DB: Apply dbMask to maskedDB */
+ ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
+ &md_ctx ) ) != 0 )
+ {
+ mbedcrypto_md_free( &md_ctx );
+ goto cleanup;
+ }
+
+ mbedcrypto_md_free( &md_ctx );
+
+ /* Generate lHash */
+ if( ( ret = mbedcrypto_md( md_info, label, label_len, lhash ) ) != 0 )
+ goto cleanup;
+
+ /*
+ * Check contents, in "constant-time"
+ */
+ p = buf;
+ bad = 0;
+
+ bad |= *p++; /* First byte must be 0 */
+
+ p += hlen; /* Skip seed */
+
+ /* Check lHash */
+ for( i = 0; i < hlen; i++ )
+ bad |= lhash[i] ^ *p++;
+
+ /* Get zero-padding len, but always read till end of buffer
+ * (minus one, for the 01 byte) */
+ pad_len = 0;
+ pad_done = 0;
+ for( i = 0; i < ilen - 2 * hlen - 2; i++ )
+ {
+ pad_done |= p[i];
+ pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
+ }
+
+ p += pad_len;
+ bad |= *p++ ^ 0x01;
+
+ /*
+ * The only information "leaked" is whether the padding was correct or not
+ * (eg, no data is copied if it was not correct). This meets the
+ * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between
+ * the different error conditions.
+ */
+ if( bad != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_INVALID_PADDING;
+ goto cleanup;
+ }
+
+ if( ilen - ( p - buf ) > output_max_len )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE;
+ goto cleanup;
+ }
+
+ *olen = ilen - (p - buf);
+ if( *olen != 0 )
+ memcpy( output, p, *olen );
+ ret = 0;
+
+cleanup:
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+ mbedcrypto_platform_zeroize( lhash, sizeof( lhash ) );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_PKCS1_V21 */
+
+#if defined(MBEDCRYPTO_PKCS1_V15)
+/*
+ * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
+ */
+int mbedcrypto_rsa_rsaes_pkcs1_v15_decrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len)
+{
+ int ret;
+ size_t ilen, pad_count = 0, i;
+ unsigned char *p, bad, pad_done = 0;
+ unsigned char buf[MBEDCRYPTO_MPI_MAX_SIZE];
+
+ if( mode == MBEDCRYPTO_RSA_PRIVATE && ctx->padding != MBEDCRYPTO_RSA_PKCS_V15 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ ilen = ctx->len;
+
+ if( ilen < 16 || ilen > sizeof( buf ) )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = ( mode == MBEDCRYPTO_RSA_PUBLIC )
+ ? mbedcrypto_rsa_public( ctx, input, buf )
+ : mbedcrypto_rsa_private( ctx, f_rng, p_rng, input, buf );
+
+ if( ret != 0 )
+ goto cleanup;
+
+ p = buf;
+ bad = 0;
+
+ /*
+ * Check and get padding len in "constant-time"
+ */
+ bad |= *p++; /* First byte must be 0 */
+
+ /* This test does not depend on secret data */
+ if( mode == MBEDCRYPTO_RSA_PRIVATE )
+ {
+ bad |= *p++ ^ MBEDCRYPTO_RSA_CRYPT;
+
+ /* Get padding len, but always read till end of buffer
+ * (minus one, for the 00 byte) */
+ for( i = 0; i < ilen - 3; i++ )
+ {
+ pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1;
+ pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
+ }
+
+ p += pad_count;
+ bad |= *p++; /* Must be zero */
+ }
+ else
+ {
+ bad |= *p++ ^ MBEDCRYPTO_RSA_SIGN;
+
+ /* Get padding len, but always read till end of buffer
+ * (minus one, for the 00 byte) */
+ for( i = 0; i < ilen - 3; i++ )
+ {
+ pad_done |= ( p[i] != 0xFF );
+ pad_count += ( pad_done == 0 );
+ }
+
+ p += pad_count;
+ bad |= *p++; /* Must be zero */
+ }
+
+ bad |= ( pad_count < 8 );
+
+ if( bad )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_INVALID_PADDING;
+ goto cleanup;
+ }
+
+ if( ilen - ( p - buf ) > output_max_len )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_OUTPUT_TOO_LARGE;
+ goto cleanup;
+ }
+
+ *olen = ilen - (p - buf);
+ if( *olen != 0 )
+ memcpy( output, p, *olen );
+ ret = 0;
+
+cleanup:
+ mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+
+/*
+ * Do an RSA operation, then remove the message padding
+ */
+int mbedcrypto_rsa_pkcs1_decrypt( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len)
+{
+ switch( ctx->padding )
+ {
+#if defined(MBEDCRYPTO_PKCS1_V15)
+ case MBEDCRYPTO_RSA_PKCS_V15:
+ return mbedcrypto_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen,
+ input, output, output_max_len );
+#endif
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+ case MBEDCRYPTO_RSA_PKCS_V21:
+ return mbedcrypto_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0,
+ olen, input, output,
+ output_max_len );
+#endif
+
+ default:
+ return( MBEDCRYPTO_ERR_RSA_INVALID_PADDING );
+ }
+}
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
+ */
+int mbedcrypto_rsa_rsassa_pss_sign( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ size_t olen;
+ unsigned char *p = sig;
+ unsigned char salt[MBEDCRYPTO_MD_MAX_SIZE];
+ unsigned int slen, hlen, offset = 0;
+ int ret;
+ size_t msb;
+ const mbedcrypto_md_info_t *md_info;
+ mbedcrypto_md_context_t md_ctx;
+
+ if( mode == MBEDCRYPTO_RSA_PRIVATE && ctx->padding != MBEDCRYPTO_RSA_PKCS_V21 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ if( f_rng == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ olen = ctx->len;
+
+ if( md_alg != MBEDCRYPTO_MD_NONE )
+ {
+ /* Gather length of hash to sign */
+ md_info = mbedcrypto_md_info_from_type( md_alg );
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ hashlen = mbedcrypto_md_get_size( md_info );
+ }
+
+ md_info = mbedcrypto_md_info_from_type( (mbedcrypto_md_type_t) ctx->hash_id );
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ hlen = mbedcrypto_md_get_size( md_info );
+ slen = hlen;
+
+ if( olen < hlen + slen + 2 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ memset( sig, 0, olen );
+
+ /* Generate salt of length slen */
+ if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
+ return( MBEDCRYPTO_ERR_RSA_RNG_FAILED + ret );
+
+ /* Note: EMSA-PSS encoding is over the length of N - 1 bits */
+ msb = mbedcrypto_mpi_bitlen( &ctx->N ) - 1;
+ p += olen - hlen * 2 - 2;
+ *p++ = 0x01;
+ memcpy( p, salt, slen );
+ p += slen;
+
+ mbedcrypto_md_init( &md_ctx );
+ if( ( ret = mbedcrypto_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
+ goto exit;
+
+ /* Generate H = Hash( M' ) */
+ if( ( ret = mbedcrypto_md_starts( &md_ctx ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md_update( &md_ctx, p, 8 ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md_update( &md_ctx, hash, hashlen ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md_update( &md_ctx, salt, slen ) ) != 0 )
+ goto exit;
+ if( ( ret = mbedcrypto_md_finish( &md_ctx, p ) ) != 0 )
+ goto exit;
+
+ /* Compensate for boundary condition when applying mask */
+ if( msb % 8 == 0 )
+ offset = 1;
+
+ /* maskedDB: Apply dbMask to DB */
+ if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen,
+ &md_ctx ) ) != 0 )
+ goto exit;
+
+ msb = mbedcrypto_mpi_bitlen( &ctx->N ) - 1;
+ sig[0] &= 0xFF >> ( olen * 8 - msb );
+
+ p += hlen;
+ *p++ = 0xBC;
+
+ mbedcrypto_platform_zeroize( salt, sizeof( salt ) );
+
+exit:
+ mbedcrypto_md_free( &md_ctx );
+
+ if( ret != 0 )
+ return( ret );
+
+ return( ( mode == MBEDCRYPTO_RSA_PUBLIC )
+ ? mbedcrypto_rsa_public( ctx, sig, sig )
+ : mbedcrypto_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
+}
+#endif /* MBEDCRYPTO_PKCS1_V21 */
+
+#if defined(MBEDCRYPTO_PKCS1_V15)
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function
+ */
+
+/* Construct a PKCS v1.5 encoding of a hashed message
+ *
+ * This is used both for signature generation and verification.
+ *
+ * Parameters:
+ * - md_alg: Identifies the hash algorithm used to generate the given hash;
+ * MBEDCRYPTO_MD_NONE if raw data is signed.
+ * - hashlen: Length of hash in case hashlen is MBEDCRYPTO_MD_NONE.
+ * - hash: Buffer containing the hashed message or the raw data.
+ * - dst_len: Length of the encoded message.
+ * - dst: Buffer to hold the encoded message.
+ *
+ * Assumptions:
+ * - hash has size hashlen if md_alg == MBEDCRYPTO_MD_NONE.
+ * - hash has size corresponding to md_alg if md_alg != MBEDCRYPTO_MD_NONE.
+ * - dst points to a buffer of size at least dst_len.
+ *
+ */
+static int rsa_rsassa_pkcs1_v15_encode( mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ size_t dst_len,
+ unsigned char *dst )
+{
+ size_t oid_size = 0;
+ size_t nb_pad = dst_len;
+ unsigned char *p = dst;
+ const char *oid = NULL;
+
+ /* Are we signing hashed or raw data? */
+ if( md_alg != MBEDCRYPTO_MD_NONE )
+ {
+ const mbedcrypto_md_info_t *md_info = mbedcrypto_md_info_from_type( md_alg );
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ if( mbedcrypto_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ hashlen = mbedcrypto_md_get_size( md_info );
+
+ /* Double-check that 8 + hashlen + oid_size can be used as a
+ * 1-byte ASN.1 length encoding and that there's no overflow. */
+ if( 8 + hashlen + oid_size >= 0x80 ||
+ 10 + hashlen < hashlen ||
+ 10 + hashlen + oid_size < 10 + hashlen )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ /*
+ * Static bounds check:
+ * - Need 10 bytes for five tag-length pairs.
+ * (Insist on 1-byte length encodings to protect against variants of
+ * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification)
+ * - Need hashlen bytes for hash
+ * - Need oid_size bytes for hash alg OID.
+ */
+ if( nb_pad < 10 + hashlen + oid_size )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ nb_pad -= 10 + hashlen + oid_size;
+ }
+ else
+ {
+ if( nb_pad < hashlen )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ nb_pad -= hashlen;
+ }
+
+ /* Need space for signature header and padding delimiter (3 bytes),
+ * and 8 bytes for the minimal padding */
+ if( nb_pad < 3 + 8 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ nb_pad -= 3;
+
+ /* Now nb_pad is the amount of memory to be filled
+ * with padding, and at least 8 bytes long. */
+
+ /* Write signature header and padding */
+ *p++ = 0;
+ *p++ = MBEDCRYPTO_RSA_SIGN;
+ memset( p, 0xFF, nb_pad );
+ p += nb_pad;
+ *p++ = 0;
+
+ /* Are we signing raw data? */
+ if( md_alg == MBEDCRYPTO_MD_NONE )
+ {
+ memcpy( p, hash, hashlen );
+ return( 0 );
+ }
+
+ /* Signing hashed data, add corresponding ASN.1 structure
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * digest Digest }
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ * Digest ::= OCTET STRING
+ *
+ * Schematic:
+ * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ]
+ * TAG-NULL + LEN [ NULL ] ]
+ * TAG-OCTET + LEN [ HASH ] ]
+ */
+ *p++ = MBEDCRYPTO_ASN1_SEQUENCE | MBEDCRYPTO_ASN1_CONSTRUCTED;
+ *p++ = (unsigned char)( 0x08 + oid_size + hashlen );
+ *p++ = MBEDCRYPTO_ASN1_SEQUENCE | MBEDCRYPTO_ASN1_CONSTRUCTED;
+ *p++ = (unsigned char)( 0x04 + oid_size );
+ *p++ = MBEDCRYPTO_ASN1_OID;
+ *p++ = (unsigned char) oid_size;
+ memcpy( p, oid, oid_size );
+ p += oid_size;
+ *p++ = MBEDCRYPTO_ASN1_NULL;
+ *p++ = 0x00;
+ *p++ = MBEDCRYPTO_ASN1_OCTET_STRING;
+ *p++ = (unsigned char) hashlen;
+ memcpy( p, hash, hashlen );
+ p += hashlen;
+
+ /* Just a sanity-check, should be automatic
+ * after the initial bounds check. */
+ if( p != dst + dst_len )
+ {
+ mbedcrypto_platform_zeroize( dst, dst_len );
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Do an RSA operation to sign the message digest
+ */
+int mbedcrypto_rsa_rsassa_pkcs1_v15_sign( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ int ret;
+ unsigned char *sig_try = NULL, *verif = NULL;
+
+ if( mode == MBEDCRYPTO_RSA_PRIVATE && ctx->padding != MBEDCRYPTO_RSA_PKCS_V15 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ /*
+ * Prepare PKCS1-v1.5 encoding (padding and hash identifier)
+ */
+
+ if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash,
+ ctx->len, sig ) ) != 0 )
+ return( ret );
+
+ /*
+ * Call respective RSA primitive
+ */
+
+ if( mode == MBEDCRYPTO_RSA_PUBLIC )
+ {
+ /* Skip verification on a public key operation */
+ return( mbedcrypto_rsa_public( ctx, sig, sig ) );
+ }
+
+ /* Private key operation
+ *
+ * In order to prevent Lenstra's attack, make the signature in a
+ * temporary buffer and check it before returning it.
+ */
+
+ sig_try = mbedcrypto_calloc( 1, ctx->len );
+ if( sig_try == NULL )
+ return( MBEDCRYPTO_ERR_MPI_ALLOC_FAILED );
+
+ verif = mbedcrypto_calloc( 1, ctx->len );
+ if( verif == NULL )
+ {
+ mbedcrypto_free( sig_try );
+ return( MBEDCRYPTO_ERR_MPI_ALLOC_FAILED );
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_rsa_public( ctx, sig_try, verif ) );
+
+ if( mbedcrypto_safer_memcmp( verif, sig, ctx->len ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_PRIVATE_FAILED;
+ goto cleanup;
+ }
+
+ memcpy( sig, sig_try, ctx->len );
+
+cleanup:
+ mbedcrypto_free( sig_try );
+ mbedcrypto_free( verif );
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+
+/*
+ * Do an RSA operation to sign the message digest
+ */
+int mbedcrypto_rsa_pkcs1_sign( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig )
+{
+ switch( ctx->padding )
+ {
+#if defined(MBEDCRYPTO_PKCS1_V15)
+ case MBEDCRYPTO_RSA_PKCS_V15:
+ return mbedcrypto_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg,
+ hashlen, hash, sig );
+#endif
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+ case MBEDCRYPTO_RSA_PKCS_V21:
+ return mbedcrypto_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg,
+ hashlen, hash, sig );
+#endif
+
+ default:
+ return( MBEDCRYPTO_ERR_RSA_INVALID_PADDING );
+ }
+}
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function
+ */
+int mbedcrypto_rsa_rsassa_pss_verify_ext( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ mbedcrypto_md_type_t mgf1_hash_id,
+ int expected_salt_len,
+ const unsigned char *sig )
+{
+ int ret;
+ size_t siglen;
+ unsigned char *p;
+ unsigned char *hash_start;
+ unsigned char result[MBEDCRYPTO_MD_MAX_SIZE];
+ unsigned char zeros[8];
+ unsigned int hlen;
+ size_t observed_salt_len, msb;
+ const mbedcrypto_md_info_t *md_info;
+ mbedcrypto_md_context_t md_ctx;
+ unsigned char buf[MBEDCRYPTO_MPI_MAX_SIZE];
+
+ if( mode == MBEDCRYPTO_RSA_PRIVATE && ctx->padding != MBEDCRYPTO_RSA_PKCS_V21 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ siglen = ctx->len;
+
+ if( siglen < 16 || siglen > sizeof( buf ) )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ ret = ( mode == MBEDCRYPTO_RSA_PUBLIC )
+ ? mbedcrypto_rsa_public( ctx, sig, buf )
+ : mbedcrypto_rsa_private( ctx, f_rng, p_rng, sig, buf );
+
+ if( ret != 0 )
+ return( ret );
+
+ p = buf;
+
+ if( buf[siglen - 1] != 0xBC )
+ return( MBEDCRYPTO_ERR_RSA_INVALID_PADDING );
+
+ if( md_alg != MBEDCRYPTO_MD_NONE )
+ {
+ /* Gather length of hash to sign */
+ md_info = mbedcrypto_md_info_from_type( md_alg );
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ hashlen = mbedcrypto_md_get_size( md_info );
+ }
+
+ md_info = mbedcrypto_md_info_from_type( mgf1_hash_id );
+ if( md_info == NULL )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ hlen = mbedcrypto_md_get_size( md_info );
+
+ memset( zeros, 0, 8 );
+
+ /*
+ * Note: EMSA-PSS verification is over the length of N - 1 bits
+ */
+ msb = mbedcrypto_mpi_bitlen( &ctx->N ) - 1;
+
+ if( buf[0] >> ( 8 - siglen * 8 + msb ) )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ /* Compensate for boundary condition when applying mask */
+ if( msb % 8 == 0 )
+ {
+ p++;
+ siglen -= 1;
+ }
+
+ if( siglen < hlen + 2 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+ hash_start = p + siglen - hlen - 1;
+
+ mbedcrypto_md_init( &md_ctx );
+ if( ( ret = mbedcrypto_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
+ goto exit;
+
+ ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx );
+ if( ret != 0 )
+ goto exit;
+
+ buf[0] &= 0xFF >> ( siglen * 8 - msb );
+
+ while( p < hash_start - 1 && *p == 0 )
+ p++;
+
+ if( *p++ != 0x01 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_INVALID_PADDING;
+ goto exit;
+ }
+
+ observed_salt_len = hash_start - p;
+
+ if( expected_salt_len != MBEDCRYPTO_RSA_SALT_LEN_ANY &&
+ observed_salt_len != (size_t) expected_salt_len )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_INVALID_PADDING;
+ goto exit;
+ }
+
+ /*
+ * Generate H = Hash( M' )
+ */
+ ret = mbedcrypto_md_starts( &md_ctx );
+ if ( ret != 0 )
+ goto exit;
+ ret = mbedcrypto_md_update( &md_ctx, zeros, 8 );
+ if ( ret != 0 )
+ goto exit;
+ ret = mbedcrypto_md_update( &md_ctx, hash, hashlen );
+ if ( ret != 0 )
+ goto exit;
+ ret = mbedcrypto_md_update( &md_ctx, p, observed_salt_len );
+ if ( ret != 0 )
+ goto exit;
+ ret = mbedcrypto_md_finish( &md_ctx, result );
+ if ( ret != 0 )
+ goto exit;
+
+ if( memcmp( hash_start, result, hlen ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_VERIFY_FAILED;
+ goto exit;
+ }
+
+exit:
+ mbedcrypto_md_free( &md_ctx );
+
+ return( ret );
+}
+
+/*
+ * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function
+ */
+int mbedcrypto_rsa_rsassa_pss_verify( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ const unsigned char *sig )
+{
+ mbedcrypto_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDCRYPTO_MD_NONE )
+ ? (mbedcrypto_md_type_t) ctx->hash_id
+ : md_alg;
+
+ return( mbedcrypto_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode,
+ md_alg, hashlen, hash,
+ mgf1_hash_id, MBEDCRYPTO_RSA_SALT_LEN_ANY,
+ sig ) );
+
+}
+#endif /* MBEDCRYPTO_PKCS1_V21 */
+
+#if defined(MBEDCRYPTO_PKCS1_V15)
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function
+ */
+int mbedcrypto_rsa_rsassa_pkcs1_v15_verify( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ const unsigned char *sig )
+{
+ int ret = 0;
+ const size_t sig_len = ctx->len;
+ unsigned char *encoded = NULL, *encoded_expected = NULL;
+
+ if( mode == MBEDCRYPTO_RSA_PRIVATE && ctx->padding != MBEDCRYPTO_RSA_PKCS_V15 )
+ return( MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA );
+
+ /*
+ * Prepare expected PKCS1 v1.5 encoding of hash.
+ */
+
+ if( ( encoded = mbedcrypto_calloc( 1, sig_len ) ) == NULL ||
+ ( encoded_expected = mbedcrypto_calloc( 1, sig_len ) ) == NULL )
+ {
+ ret = MBEDCRYPTO_ERR_MPI_ALLOC_FAILED;
+ goto cleanup;
+ }
+
+ if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len,
+ encoded_expected ) ) != 0 )
+ goto cleanup;
+
+ /*
+ * Apply RSA primitive to get what should be PKCS1 encoded hash.
+ */
+
+ ret = ( mode == MBEDCRYPTO_RSA_PUBLIC )
+ ? mbedcrypto_rsa_public( ctx, sig, encoded )
+ : mbedcrypto_rsa_private( ctx, f_rng, p_rng, sig, encoded );
+ if( ret != 0 )
+ goto cleanup;
+
+ /*
+ * Compare
+ */
+
+ if( ( ret = mbedcrypto_safer_memcmp( encoded, encoded_expected,
+ sig_len ) ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_VERIFY_FAILED;
+ goto cleanup;
+ }
+
+cleanup:
+
+ if( encoded != NULL )
+ {
+ mbedcrypto_platform_zeroize( encoded, sig_len );
+ mbedcrypto_free( encoded );
+ }
+
+ if( encoded_expected != NULL )
+ {
+ mbedcrypto_platform_zeroize( encoded_expected, sig_len );
+ mbedcrypto_free( encoded_expected );
+ }
+
+ return( ret );
+}
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+
+/*
+ * Do an RSA operation and check the message digest
+ */
+int mbedcrypto_rsa_pkcs1_verify( mbedcrypto_rsa_context *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ int mode,
+ mbedcrypto_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ const unsigned char *sig )
+{
+ switch( ctx->padding )
+ {
+#if defined(MBEDCRYPTO_PKCS1_V15)
+ case MBEDCRYPTO_RSA_PKCS_V15:
+ return mbedcrypto_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg,
+ hashlen, hash, sig );
+#endif
+
+#if defined(MBEDCRYPTO_PKCS1_V21)
+ case MBEDCRYPTO_RSA_PKCS_V21:
+ return mbedcrypto_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg,
+ hashlen, hash, sig );
+#endif
+
+ default:
+ return( MBEDCRYPTO_ERR_RSA_INVALID_PADDING );
+ }
+}
+
+/*
+ * Copy the components of an RSA key
+ */
+int mbedcrypto_rsa_copy( mbedcrypto_rsa_context *dst, const mbedcrypto_rsa_context *src )
+{
+ int ret;
+
+ dst->ver = src->ver;
+ dst->len = src->len;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->N, &src->N ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->E, &src->E ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->D, &src->D ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->P, &src->P ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->Q, &src->Q ) );
+
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->DP, &src->DP ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->DQ, &src->DQ ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->QP, &src->QP ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->RP, &src->RP ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->RQ, &src->RQ ) );
+#endif
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->RN, &src->RN ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->Vi, &src->Vi ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_copy( &dst->Vf, &src->Vf ) );
+
+ dst->padding = src->padding;
+ dst->hash_id = src->hash_id;
+
+cleanup:
+ if( ret != 0 )
+ mbedcrypto_rsa_free( dst );
+
+ return( ret );
+}
+
+/*
+ * Free the components of an RSA key
+ */
+void mbedcrypto_rsa_free( mbedcrypto_rsa_context *ctx )
+{
+ mbedcrypto_mpi_free( &ctx->Vi ); mbedcrypto_mpi_free( &ctx->Vf );
+ mbedcrypto_mpi_free( &ctx->RN ); mbedcrypto_mpi_free( &ctx->D );
+ mbedcrypto_mpi_free( &ctx->Q ); mbedcrypto_mpi_free( &ctx->P );
+ mbedcrypto_mpi_free( &ctx->E ); mbedcrypto_mpi_free( &ctx->N );
+
+#if !defined(MBEDCRYPTO_RSA_NO_CRT)
+ mbedcrypto_mpi_free( &ctx->RQ ); mbedcrypto_mpi_free( &ctx->RP );
+ mbedcrypto_mpi_free( &ctx->QP ); mbedcrypto_mpi_free( &ctx->DQ );
+ mbedcrypto_mpi_free( &ctx->DP );
+#endif /* MBEDCRYPTO_RSA_NO_CRT */
+
+#if defined(MBEDCRYPTO_THREADING_C)
+ mbedcrypto_mutex_free( &ctx->mutex );
+#endif
+}
+
+#endif /* !MBEDCRYPTO_RSA_ALT */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+#include "mbedcrypto/sha1.h"
+
+/*
+ * Example RSA-1024 keypair, for test purposes
+ */
+#define KEY_LEN 128
+
+#define RSA_N "9292758453063D803DD603D5E777D788" \
+ "8ED1D5BF35786190FA2F23EBC0848AEA" \
+ "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
+ "7130B9CED7ACDF54CFC7555AC14EEBAB" \
+ "93A89813FBF3C4F8066D2D800F7C38A8" \
+ "1AE31942917403FF4946B0A83D3D3E05" \
+ "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
+ "5E94BB77B07507233A0BC7BAC8F90F79"
+
+#define RSA_E "10001"
+
+#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
+ "66CA472BC44D253102F8B4A9D3BFA750" \
+ "91386C0077937FE33FA3252D28855837" \
+ "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
+ "DF79C5CE07EE72C7F123142198164234" \
+ "CABB724CF78B8173B9F880FC86322407" \
+ "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
+ "071513A1E85B5DFA031F21ECAE91A34D"
+
+#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
+ "2C01CAD19EA484A87EA4377637E75500" \
+ "FCB2005C5C7DD6EC4AC023CDA285D796" \
+ "C3D9E75E1EFC42488BB4F1D13AC30A57"
+
+#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
+ "E211C2B9E5DB1ED0BF61D0D9899620F4" \
+ "910E4168387E3C30AA1E00C339A79508" \
+ "8452DD96A9A5EA5D9DCA68DA636032AF"
+
+#define PT_LEN 24
+#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
+ "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
+
+#if defined(MBEDCRYPTO_PKCS1_V15)
+static int myrand( void *rng_state, unsigned char *output, size_t len )
+{
+#if !defined(__OpenBSD__)
+ size_t i;
+
+ if( rng_state != NULL )
+ rng_state = NULL;
+
+ for( i = 0; i < len; ++i )
+ output[i] = rand();
+#else
+ if( rng_state != NULL )
+ rng_state = NULL;
+
+ arc4random_buf( output, len );
+#endif /* !OpenBSD */
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_rsa_self_test( int verbose )
+{
+ int ret = 0;
+#if defined(MBEDCRYPTO_PKCS1_V15)
+ size_t len;
+ mbedcrypto_rsa_context rsa;
+ unsigned char rsa_plaintext[PT_LEN];
+ unsigned char rsa_decrypted[PT_LEN];
+ unsigned char rsa_ciphertext[KEY_LEN];
+#if defined(MBEDCRYPTO_SHA1_C)
+ unsigned char sha1sum[20];
+#endif
+
+ mbedcrypto_mpi K;
+
+ mbedcrypto_mpi_init( &K );
+ mbedcrypto_rsa_init( &rsa, MBEDCRYPTO_RSA_PKCS_V15, 0 );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &K, 16, RSA_N ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &K, 16, RSA_P ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &K, 16, RSA_Q ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &K, 16, RSA_D ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_read_string( &K, 16, RSA_E ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) );
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_rsa_complete( &rsa ) );
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " RSA key validation: " );
+
+ if( mbedcrypto_rsa_check_pubkey( &rsa ) != 0 ||
+ mbedcrypto_rsa_check_privkey( &rsa ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto cleanup;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n PKCS#1 encryption : " );
+
+ memcpy( rsa_plaintext, RSA_PT, PT_LEN );
+
+ if( mbedcrypto_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDCRYPTO_RSA_PUBLIC,
+ PT_LEN, rsa_plaintext,
+ rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto cleanup;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n PKCS#1 decryption : " );
+
+ if( mbedcrypto_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDCRYPTO_RSA_PRIVATE,
+ &len, rsa_ciphertext, rsa_decrypted,
+ sizeof(rsa_decrypted) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto cleanup;
+ }
+
+ if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto cleanup;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+
+#if defined(MBEDCRYPTO_SHA1_C)
+ if( verbose != 0 )
+ mbedcrypto_printf( " PKCS#1 data sign : " );
+
+ if( mbedcrypto_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ return( 1 );
+ }
+
+ if( mbedcrypto_rsa_pkcs1_sign( &rsa, myrand, NULL,
+ MBEDCRYPTO_RSA_PRIVATE, MBEDCRYPTO_MD_SHA1, 0,
+ sha1sum, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto cleanup;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n PKCS#1 sig. verify: " );
+
+ if( mbedcrypto_rsa_pkcs1_verify( &rsa, NULL, NULL,
+ MBEDCRYPTO_RSA_PUBLIC, MBEDCRYPTO_MD_SHA1, 0,
+ sha1sum, rsa_ciphertext ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto cleanup;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+#endif /* MBEDCRYPTO_SHA1_C */
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+cleanup:
+ mbedcrypto_mpi_free( &K );
+ mbedcrypto_rsa_free( &rsa );
+#else /* MBEDCRYPTO_PKCS1_V15 */
+ ((void) verbose);
+#endif /* MBEDCRYPTO_PKCS1_V15 */
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_RSA_C */
diff --git a/library/rsa_internal.c b/library/rsa_internal.c
new file mode 100644
index 0000000..a46b7f4
--- /dev/null
+++ b/library/rsa_internal.c
@@ -0,0 +1,487 @@
+/*
+ * Helper functions for the RSA module
+ *
+ * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ *
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_RSA_C)
+
+#include "mbedcrypto/rsa.h"
+#include "mbedcrypto/bignum.h"
+#include "mbedcrypto/rsa_internal.h"
+
+/*
+ * Compute RSA prime factors from public and private exponents
+ *
+ * Summary of algorithm:
+ * Setting F := lcm(P-1,Q-1), the idea is as follows:
+ *
+ * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2)
+ * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the
+ * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four
+ * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1)
+ * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime
+ * factors of N.
+ *
+ * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same
+ * construction still applies since (-)^K is the identity on the set of
+ * roots of 1 in Z/NZ.
+ *
+ * The public and private key primitives (-)^E and (-)^D are mutually inverse
+ * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e.
+ * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L.
+ * Splitting L = 2^t * K with K odd, we have
+ *
+ * DE - 1 = FL = (F/2) * (2^(t+1)) * K,
+ *
+ * so (F / 2) * K is among the numbers
+ *
+ * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord
+ *
+ * where ord is the order of 2 in (DE - 1).
+ * We can therefore iterate through these numbers apply the construction
+ * of (a) and (b) above to attempt to factor N.
+ *
+ */
+int mbedcrypto_rsa_deduce_primes( mbedcrypto_mpi const *N,
+ mbedcrypto_mpi const *E, mbedcrypto_mpi const *D,
+ mbedcrypto_mpi *P, mbedcrypto_mpi *Q )
+{
+ int ret = 0;
+
+ uint16_t attempt; /* Number of current attempt */
+ uint16_t iter; /* Number of squares computed in the current attempt */
+
+ uint16_t order; /* Order of 2 in DE - 1 */
+
+ mbedcrypto_mpi T; /* Holds largest odd divisor of DE - 1 */
+ mbedcrypto_mpi K; /* Temporary holding the current candidate */
+
+ const unsigned char primes[] = { 2,
+ 3, 5, 7, 11, 13, 17, 19, 23,
+ 29, 31, 37, 41, 43, 47, 53, 59,
+ 61, 67, 71, 73, 79, 83, 89, 97,
+ 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179,
+ 181, 191, 193, 197, 199, 211, 223, 227,
+ 229, 233, 239, 241, 251
+ };
+
+ const size_t num_primes = sizeof( primes ) / sizeof( *primes );
+
+ if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ if( mbedcrypto_mpi_cmp_int( N, 0 ) <= 0 ||
+ mbedcrypto_mpi_cmp_int( D, 1 ) <= 0 ||
+ mbedcrypto_mpi_cmp_mpi( D, N ) >= 0 ||
+ mbedcrypto_mpi_cmp_int( E, 1 ) <= 0 ||
+ mbedcrypto_mpi_cmp_mpi( E, N ) >= 0 )
+ {
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+ }
+
+ /*
+ * Initializations and temporary changes
+ */
+
+ mbedcrypto_mpi_init( &K );
+ mbedcrypto_mpi_init( &T );
+
+ /* T := DE - 1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &T, D, E ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &T, &T, 1 ) );
+
+ if( ( order = (uint16_t) mbedcrypto_mpi_lsb( &T ) ) == 0 )
+ {
+ ret = MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+ /* After this operation, T holds the largest odd divisor of DE - 1. */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_shift_r( &T, order ) );
+
+ /*
+ * Actual work
+ */
+
+ /* Skip trying 2 if N == 1 mod 8 */
+ attempt = 0;
+ if( N->p[0] % 8 == 1 )
+ attempt = 1;
+
+ for( ; attempt < num_primes; ++attempt )
+ {
+ mbedcrypto_mpi_lset( &K, primes[attempt] );
+
+ /* Check if gcd(K,N) = 1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_gcd( P, &K, N ) );
+ if( mbedcrypto_mpi_cmp_int( P, 1 ) != 0 )
+ continue;
+
+ /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ...
+ * and check whether they have nontrivial GCD with N. */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_exp_mod( &K, &K, &T, N,
+ Q /* temporarily use Q for storing Montgomery
+ * multiplication helper values */ ) );
+
+ for( iter = 1; iter <= order; ++iter )
+ {
+ /* If we reach 1 prematurely, there's no point
+ * in continuing to square K */
+ if( mbedcrypto_mpi_cmp_int( &K, 1 ) == 0 )
+ break;
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_add_int( &K, &K, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_gcd( P, &K, N ) );
+
+ if( mbedcrypto_mpi_cmp_int( P, 1 ) == 1 &&
+ mbedcrypto_mpi_cmp_mpi( P, N ) == -1 )
+ {
+ /*
+ * Have found a nontrivial divisor P of N.
+ * Set Q := N / P.
+ */
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_div_mpi( Q, NULL, N, P ) );
+ goto cleanup;
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &K, &K, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &K, &K, &K ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &K, &K, N ) );
+ }
+
+ /*
+ * If we get here, then either we prematurely aborted the loop because
+ * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must
+ * be 1 if D,E,N were consistent.
+ * Check if that's the case and abort if not, to avoid very long,
+ * yet eventually failing, computations if N,D,E were not sane.
+ */
+ if( mbedcrypto_mpi_cmp_int( &K, 1 ) != 0 )
+ {
+ break;
+ }
+ }
+
+ ret = MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA;
+
+cleanup:
+
+ mbedcrypto_mpi_free( &K );
+ mbedcrypto_mpi_free( &T );
+ return( ret );
+}
+
+/*
+ * Given P, Q and the public exponent E, deduce D.
+ * This is essentially a modular inversion.
+ */
+int mbedcrypto_rsa_deduce_private_exponent( mbedcrypto_mpi const *P,
+ mbedcrypto_mpi const *Q,
+ mbedcrypto_mpi const *E,
+ mbedcrypto_mpi *D )
+{
+ int ret = 0;
+ mbedcrypto_mpi K, L;
+
+ if( D == NULL || mbedcrypto_mpi_cmp_int( D, 0 ) != 0 )
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+
+ if( mbedcrypto_mpi_cmp_int( P, 1 ) <= 0 ||
+ mbedcrypto_mpi_cmp_int( Q, 1 ) <= 0 ||
+ mbedcrypto_mpi_cmp_int( E, 0 ) == 0 )
+ {
+ return( MBEDCRYPTO_ERR_MPI_BAD_INPUT_DATA );
+ }
+
+ mbedcrypto_mpi_init( &K );
+ mbedcrypto_mpi_init( &L );
+
+ /* Temporarily put K := P-1 and L := Q-1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &K, P, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &L, Q, 1 ) );
+
+ /* Temporarily put D := gcd(P-1, Q-1) */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_gcd( D, &K, &L ) );
+
+ /* K := LCM(P-1, Q-1) */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &K, &K, &L ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_div_mpi( &K, NULL, &K, D ) );
+
+ /* Compute modular inverse of E in LCM(P-1, Q-1) */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_inv_mod( D, E, &K ) );
+
+cleanup:
+
+ mbedcrypto_mpi_free( &K );
+ mbedcrypto_mpi_free( &L );
+
+ return( ret );
+}
+
+/*
+ * Check that RSA CRT parameters are in accordance with core parameters.
+ */
+int mbedcrypto_rsa_validate_crt( const mbedcrypto_mpi *P, const mbedcrypto_mpi *Q,
+ const mbedcrypto_mpi *D, const mbedcrypto_mpi *DP,
+ const mbedcrypto_mpi *DQ, const mbedcrypto_mpi *QP )
+{
+ int ret = 0;
+
+ mbedcrypto_mpi K, L;
+ mbedcrypto_mpi_init( &K );
+ mbedcrypto_mpi_init( &L );
+
+ /* Check that DP - D == 0 mod P - 1 */
+ if( DP != NULL )
+ {
+ if( P == NULL )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &K, P, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &L, DP, D ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &L, &L, &K ) );
+
+ if( mbedcrypto_mpi_cmp_int( &L, 0 ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ goto cleanup;
+ }
+ }
+
+ /* Check that DQ - D == 0 mod Q - 1 */
+ if( DQ != NULL )
+ {
+ if( Q == NULL )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &K, Q, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_mpi( &L, DQ, D ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &L, &L, &K ) );
+
+ if( mbedcrypto_mpi_cmp_int( &L, 0 ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ goto cleanup;
+ }
+ }
+
+ /* Check that QP * Q - 1 == 0 mod P */
+ if( QP != NULL )
+ {
+ if( P == NULL || Q == NULL )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &K, QP, Q ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &K, &K, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &K, &K, P ) );
+ if( mbedcrypto_mpi_cmp_int( &K, 0 ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ /* Wrap MPI error codes by RSA check failure error code */
+ if( ret != 0 &&
+ ret != MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED &&
+ ret != MBEDCRYPTO_ERR_RSA_BAD_INPUT_DATA )
+ {
+ ret += MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ }
+
+ mbedcrypto_mpi_free( &K );
+ mbedcrypto_mpi_free( &L );
+
+ return( ret );
+}
+
+/*
+ * Check that core RSA parameters are sane.
+ */
+int mbedcrypto_rsa_validate_params( const mbedcrypto_mpi *N, const mbedcrypto_mpi *P,
+ const mbedcrypto_mpi *Q, const mbedcrypto_mpi *D,
+ const mbedcrypto_mpi *E,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret = 0;
+ mbedcrypto_mpi K, L;
+
+ mbedcrypto_mpi_init( &K );
+ mbedcrypto_mpi_init( &L );
+
+ /*
+ * Step 1: If PRNG provided, check that P and Q are prime
+ */
+
+#if defined(MBEDCRYPTO_GENPRIME)
+ if( f_rng != NULL && P != NULL &&
+ ( ret = mbedcrypto_mpi_is_prime( P, f_rng, p_rng ) ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ goto cleanup;
+ }
+
+ if( f_rng != NULL && Q != NULL &&
+ ( ret = mbedcrypto_mpi_is_prime( Q, f_rng, p_rng ) ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ goto cleanup;
+ }
+#else
+ ((void) f_rng);
+ ((void) p_rng);
+#endif /* MBEDCRYPTO_GENPRIME */
+
+ /*
+ * Step 2: Check that 1 < N = P * Q
+ */
+
+ if( P != NULL && Q != NULL && N != NULL )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &K, P, Q ) );
+ if( mbedcrypto_mpi_cmp_int( N, 1 ) <= 0 ||
+ mbedcrypto_mpi_cmp_mpi( &K, N ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Step 3: Check and 1 < D, E < N if present.
+ */
+
+ if( N != NULL && D != NULL && E != NULL )
+ {
+ if ( mbedcrypto_mpi_cmp_int( D, 1 ) <= 0 ||
+ mbedcrypto_mpi_cmp_int( E, 1 ) <= 0 ||
+ mbedcrypto_mpi_cmp_mpi( D, N ) >= 0 ||
+ mbedcrypto_mpi_cmp_mpi( E, N ) >= 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Step 4: Check that D, E are inverse modulo P-1 and Q-1
+ */
+
+ if( P != NULL && Q != NULL && D != NULL && E != NULL )
+ {
+ if( mbedcrypto_mpi_cmp_int( P, 1 ) <= 0 ||
+ mbedcrypto_mpi_cmp_int( Q, 1 ) <= 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ goto cleanup;
+ }
+
+ /* Compute DE-1 mod P-1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &K, D, E ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &K, &K, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &L, P, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &K, &K, &L ) );
+ if( mbedcrypto_mpi_cmp_int( &K, 0 ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ goto cleanup;
+ }
+
+ /* Compute DE-1 mod Q-1 */
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mul_mpi( &K, D, E ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &K, &K, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &L, Q, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( &K, &K, &L ) );
+ if( mbedcrypto_mpi_cmp_int( &K, 0 ) != 0 )
+ {
+ ret = MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ mbedcrypto_mpi_free( &K );
+ mbedcrypto_mpi_free( &L );
+
+ /* Wrap MPI error codes by RSA check failure error code */
+ if( ret != 0 && ret != MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED )
+ {
+ ret += MBEDCRYPTO_ERR_RSA_KEY_CHECK_FAILED;
+ }
+
+ return( ret );
+}
+
+int mbedcrypto_rsa_deduce_crt( const mbedcrypto_mpi *P, const mbedcrypto_mpi *Q,
+ const mbedcrypto_mpi *D, mbedcrypto_mpi *DP,
+ mbedcrypto_mpi *DQ, mbedcrypto_mpi *QP )
+{
+ int ret = 0;
+ mbedcrypto_mpi K;
+ mbedcrypto_mpi_init( &K );
+
+ /* DP = D mod P-1 */
+ if( DP != NULL )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &K, P, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( DP, D, &K ) );
+ }
+
+ /* DQ = D mod Q-1 */
+ if( DQ != NULL )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_sub_int( &K, Q, 1 ) );
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_mod_mpi( DQ, D, &K ) );
+ }
+
+ /* QP = Q^{-1} mod P */
+ if( QP != NULL )
+ {
+ MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_inv_mod( QP, Q, P ) );
+ }
+
+cleanup:
+ mbedcrypto_mpi_free( &K );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_RSA_C */
diff --git a/library/sha1.c b/library/sha1.c
new file mode 100644
index 0000000..d0f3757
--- /dev/null
+++ b/library/sha1.c
@@ -0,0 +1,532 @@
+/*
+ * FIPS-180-1 compliant SHA-1 implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The SHA-1 standard was published by NIST in 1993.
+ *
+ * http://www.itl.nist.gov/fipspubs/fip180-1.htm
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_SHA1_C)
+
+#include "mbedcrypto/sha1.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_SHA1_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+void mbedcrypto_sha1_init( mbedcrypto_sha1_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_sha1_context ) );
+}
+
+void mbedcrypto_sha1_free( mbedcrypto_sha1_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_sha1_context ) );
+}
+
+void mbedcrypto_sha1_clone( mbedcrypto_sha1_context *dst,
+ const mbedcrypto_sha1_context *src )
+{
+ *dst = *src;
+}
+
+/*
+ * SHA-1 context setup
+ */
+int mbedcrypto_sha1_starts_ret( mbedcrypto_sha1_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha1_starts( mbedcrypto_sha1_context *ctx )
+{
+ mbedcrypto_sha1_starts_ret( ctx );
+}
+#endif
+
+#if !defined(MBEDCRYPTO_SHA1_PROCESS_ALT)
+int mbedcrypto_internal_sha1_process( mbedcrypto_sha1_context *ctx,
+ const unsigned char data[64] )
+{
+ uint32_t temp, W[16], A, B, C, D, E;
+
+ GET_UINT32_BE( W[ 0], data, 0 );
+ GET_UINT32_BE( W[ 1], data, 4 );
+ GET_UINT32_BE( W[ 2], data, 8 );
+ GET_UINT32_BE( W[ 3], data, 12 );
+ GET_UINT32_BE( W[ 4], data, 16 );
+ GET_UINT32_BE( W[ 5], data, 20 );
+ GET_UINT32_BE( W[ 6], data, 24 );
+ GET_UINT32_BE( W[ 7], data, 28 );
+ GET_UINT32_BE( W[ 8], data, 32 );
+ GET_UINT32_BE( W[ 9], data, 36 );
+ GET_UINT32_BE( W[10], data, 40 );
+ GET_UINT32_BE( W[11], data, 44 );
+ GET_UINT32_BE( W[12], data, 48 );
+ GET_UINT32_BE( W[13], data, 52 );
+ GET_UINT32_BE( W[14], data, 56 );
+ GET_UINT32_BE( W[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t) \
+( \
+ temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
+ W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
+ ( W[t & 0x0F] = S(temp,1) ) \
+)
+
+#define P(a,b,c,d,e,x) \
+{ \
+ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P( A, B, C, D, E, W[0] );
+ P( E, A, B, C, D, W[1] );
+ P( D, E, A, B, C, W[2] );
+ P( C, D, E, A, B, W[3] );
+ P( B, C, D, E, A, W[4] );
+ P( A, B, C, D, E, W[5] );
+ P( E, A, B, C, D, W[6] );
+ P( D, E, A, B, C, W[7] );
+ P( C, D, E, A, B, W[8] );
+ P( B, C, D, E, A, W[9] );
+ P( A, B, C, D, E, W[10] );
+ P( E, A, B, C, D, W[11] );
+ P( D, E, A, B, C, W[12] );
+ P( C, D, E, A, B, W[13] );
+ P( B, C, D, E, A, W[14] );
+ P( A, B, C, D, E, W[15] );
+ P( E, A, B, C, D, R(16) );
+ P( D, E, A, B, C, R(17) );
+ P( C, D, E, A, B, R(18) );
+ P( B, C, D, E, A, R(19) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P( A, B, C, D, E, R(20) );
+ P( E, A, B, C, D, R(21) );
+ P( D, E, A, B, C, R(22) );
+ P( C, D, E, A, B, R(23) );
+ P( B, C, D, E, A, R(24) );
+ P( A, B, C, D, E, R(25) );
+ P( E, A, B, C, D, R(26) );
+ P( D, E, A, B, C, R(27) );
+ P( C, D, E, A, B, R(28) );
+ P( B, C, D, E, A, R(29) );
+ P( A, B, C, D, E, R(30) );
+ P( E, A, B, C, D, R(31) );
+ P( D, E, A, B, C, R(32) );
+ P( C, D, E, A, B, R(33) );
+ P( B, C, D, E, A, R(34) );
+ P( A, B, C, D, E, R(35) );
+ P( E, A, B, C, D, R(36) );
+ P( D, E, A, B, C, R(37) );
+ P( C, D, E, A, B, R(38) );
+ P( B, C, D, E, A, R(39) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P( A, B, C, D, E, R(40) );
+ P( E, A, B, C, D, R(41) );
+ P( D, E, A, B, C, R(42) );
+ P( C, D, E, A, B, R(43) );
+ P( B, C, D, E, A, R(44) );
+ P( A, B, C, D, E, R(45) );
+ P( E, A, B, C, D, R(46) );
+ P( D, E, A, B, C, R(47) );
+ P( C, D, E, A, B, R(48) );
+ P( B, C, D, E, A, R(49) );
+ P( A, B, C, D, E, R(50) );
+ P( E, A, B, C, D, R(51) );
+ P( D, E, A, B, C, R(52) );
+ P( C, D, E, A, B, R(53) );
+ P( B, C, D, E, A, R(54) );
+ P( A, B, C, D, E, R(55) );
+ P( E, A, B, C, D, R(56) );
+ P( D, E, A, B, C, R(57) );
+ P( C, D, E, A, B, R(58) );
+ P( B, C, D, E, A, R(59) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P( A, B, C, D, E, R(60) );
+ P( E, A, B, C, D, R(61) );
+ P( D, E, A, B, C, R(62) );
+ P( C, D, E, A, B, R(63) );
+ P( B, C, D, E, A, R(64) );
+ P( A, B, C, D, E, R(65) );
+ P( E, A, B, C, D, R(66) );
+ P( D, E, A, B, C, R(67) );
+ P( C, D, E, A, B, R(68) );
+ P( B, C, D, E, A, R(69) );
+ P( A, B, C, D, E, R(70) );
+ P( E, A, B, C, D, R(71) );
+ P( D, E, A, B, C, R(72) );
+ P( C, D, E, A, B, R(73) );
+ P( B, C, D, E, A, R(74) );
+ P( A, B, C, D, E, R(75) );
+ P( E, A, B, C, D, R(76) );
+ P( D, E, A, B, C, R(77) );
+ P( C, D, E, A, B, R(78) );
+ P( B, C, D, E, A, R(79) );
+
+#undef K
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha1_process( mbedcrypto_sha1_context *ctx,
+ const unsigned char data[64] )
+{
+ mbedcrypto_internal_sha1_process( ctx, data );
+}
+#endif
+#endif /* !MBEDCRYPTO_SHA1_PROCESS_ALT */
+
+/*
+ * SHA-1 process buffer
+ */
+int mbedcrypto_sha1_update_ret( mbedcrypto_sha1_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ int ret;
+ size_t fill;
+ uint32_t left;
+
+ if( ilen == 0 )
+ return( 0 );
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+
+ if( ( ret = mbedcrypto_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ if( ( ret = mbedcrypto_internal_sha1_process( ctx, input ) ) != 0 )
+ return( ret );
+
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha1_update( mbedcrypto_sha1_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ mbedcrypto_sha1_update_ret( ctx, input, ilen );
+}
+#endif
+
+static const unsigned char sha1_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-1 final digest
+ */
+int mbedcrypto_sha1_finish_ret( mbedcrypto_sha1_context *ctx,
+ unsigned char output[20] )
+{
+ int ret;
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_BE( high, msglen, 0 );
+ PUT_UINT32_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ if( ( ret = mbedcrypto_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 )
+ return( ret );
+ if( ( ret = mbedcrypto_sha1_update_ret( ctx, msglen, 8 ) ) != 0 )
+ return( ret );
+
+ PUT_UINT32_BE( ctx->state[0], output, 0 );
+ PUT_UINT32_BE( ctx->state[1], output, 4 );
+ PUT_UINT32_BE( ctx->state[2], output, 8 );
+ PUT_UINT32_BE( ctx->state[3], output, 12 );
+ PUT_UINT32_BE( ctx->state[4], output, 16 );
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha1_finish( mbedcrypto_sha1_context *ctx,
+ unsigned char output[20] )
+{
+ mbedcrypto_sha1_finish_ret( ctx, output );
+}
+#endif
+
+#endif /* !MBEDCRYPTO_SHA1_ALT */
+
+/*
+ * output = SHA-1( input buffer )
+ */
+int mbedcrypto_sha1_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[20] )
+{
+ int ret;
+ mbedcrypto_sha1_context ctx;
+
+ mbedcrypto_sha1_init( &ctx );
+
+ if( ( ret = mbedcrypto_sha1_starts_ret( &ctx ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_sha1_update_ret( &ctx, input, ilen ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_sha1_finish_ret( &ctx, output ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedcrypto_sha1_free( &ctx );
+
+ return( ret );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha1( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[20] )
+{
+ mbedcrypto_sha1_ret( input, ilen, output );
+}
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/*
+ * FIPS-180-1 test vectors
+ */
+static const unsigned char sha1_test_buf[3][57] =
+{
+ { "abc" },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+ { "" }
+};
+
+static const size_t sha1_test_buflen[3] =
+{
+ 3, 56, 1000
+};
+
+static const unsigned char sha1_test_sum[3][20] =
+{
+ { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
+ 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D },
+ { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
+ 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 },
+ { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
+ 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_sha1_self_test( int verbose )
+{
+ int i, j, buflen, ret = 0;
+ unsigned char buf[1024];
+ unsigned char sha1sum[20];
+ mbedcrypto_sha1_context ctx;
+
+ mbedcrypto_sha1_init( &ctx );
+
+ /*
+ * SHA-1
+ */
+ for( i = 0; i < 3; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " SHA-1 test #%d: ", i + 1 );
+
+ if( ( ret = mbedcrypto_sha1_starts_ret( &ctx ) ) != 0 )
+ goto fail;
+
+ if( i == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ {
+ ret = mbedcrypto_sha1_update_ret( &ctx, buf, buflen );
+ if( ret != 0 )
+ goto fail;
+ }
+ }
+ else
+ {
+ ret = mbedcrypto_sha1_update_ret( &ctx, sha1_test_buf[i],
+ sha1_test_buflen[i] );
+ if( ret != 0 )
+ goto fail;
+ }
+
+ if( ( ret = mbedcrypto_sha1_finish_ret( &ctx, sha1sum ) ) != 0 )
+ goto fail;
+
+ if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
+ {
+ ret = 1;
+ goto fail;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ goto exit;
+
+fail:
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+exit:
+ mbedcrypto_sha1_free( &ctx );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_SHA1_C */
diff --git a/library/sha256.c b/library/sha256.c
new file mode 100644
index 0000000..d04a424
--- /dev/null
+++ b/library/sha256.c
@@ -0,0 +1,546 @@
+/*
+ * FIPS-180-2 compliant SHA-256 implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The SHA-256 Secure Hash Standard was published by NIST in 2002.
+ *
+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_SHA256_C)
+
+#include "mbedcrypto/sha256.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedcrypto_printf printf
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_SHA256_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+do { \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+} while( 0 )
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+do { \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+} while( 0 )
+#endif
+
+void mbedcrypto_sha256_init( mbedcrypto_sha256_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_sha256_context ) );
+}
+
+void mbedcrypto_sha256_free( mbedcrypto_sha256_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_sha256_context ) );
+}
+
+void mbedcrypto_sha256_clone( mbedcrypto_sha256_context *dst,
+ const mbedcrypto_sha256_context *src )
+{
+ *dst = *src;
+}
+
+/*
+ * SHA-256 context setup
+ */
+int mbedcrypto_sha256_starts_ret( mbedcrypto_sha256_context *ctx, int is224 )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ if( is224 == 0 )
+ {
+ /* SHA-256 */
+ ctx->state[0] = 0x6A09E667;
+ ctx->state[1] = 0xBB67AE85;
+ ctx->state[2] = 0x3C6EF372;
+ ctx->state[3] = 0xA54FF53A;
+ ctx->state[4] = 0x510E527F;
+ ctx->state[5] = 0x9B05688C;
+ ctx->state[6] = 0x1F83D9AB;
+ ctx->state[7] = 0x5BE0CD19;
+ }
+ else
+ {
+ /* SHA-224 */
+ ctx->state[0] = 0xC1059ED8;
+ ctx->state[1] = 0x367CD507;
+ ctx->state[2] = 0x3070DD17;
+ ctx->state[3] = 0xF70E5939;
+ ctx->state[4] = 0xFFC00B31;
+ ctx->state[5] = 0x68581511;
+ ctx->state[6] = 0x64F98FA7;
+ ctx->state[7] = 0xBEFA4FA4;
+ }
+
+ ctx->is224 = is224;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha256_starts( mbedcrypto_sha256_context *ctx,
+ int is224 )
+{
+ mbedcrypto_sha256_starts_ret( ctx, is224 );
+}
+#endif
+
+#if !defined(MBEDCRYPTO_SHA256_PROCESS_ALT)
+static const uint32_t K[] =
+{
+ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+ 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+ 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+ 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+ 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+ 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+ 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+ 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+ 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+ 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+ 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+ 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+ 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+ 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+ 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+ 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
+};
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+int mbedcrypto_internal_sha256_process( mbedcrypto_sha256_context *ctx,
+ const unsigned char data[64] )
+{
+ uint32_t temp1, temp2, W[64];
+ uint32_t A[8];
+ unsigned int i;
+
+ for( i = 0; i < 8; i++ )
+ A[i] = ctx->state[i];
+
+#if defined(MBEDCRYPTO_SHA256_SMALLER)
+ for( i = 0; i < 64; i++ )
+ {
+ if( i < 16 )
+ GET_UINT32_BE( W[i], data, 4 * i );
+ else
+ R( i );
+
+ P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
+
+ temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
+ A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
+ }
+#else /* MBEDCRYPTO_SHA256_SMALLER */
+ for( i = 0; i < 16; i++ )
+ GET_UINT32_BE( W[i], data, 4 * i );
+
+ for( i = 0; i < 16; i += 8 )
+ {
+ P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
+ P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
+ P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
+ P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] );
+ P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] );
+ P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] );
+ P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] );
+ P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
+ }
+
+ for( i = 16; i < 64; i += 8 )
+ {
+ P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
+ P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
+ P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
+ P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] );
+ P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] );
+ P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] );
+ P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] );
+ P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] );
+ }
+#endif /* MBEDCRYPTO_SHA256_SMALLER */
+
+ for( i = 0; i < 8; i++ )
+ ctx->state[i] += A[i];
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha256_process( mbedcrypto_sha256_context *ctx,
+ const unsigned char data[64] )
+{
+ mbedcrypto_internal_sha256_process( ctx, data );
+}
+#endif
+#endif /* !MBEDCRYPTO_SHA256_PROCESS_ALT */
+
+/*
+ * SHA-256 process buffer
+ */
+int mbedcrypto_sha256_update_ret( mbedcrypto_sha256_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ int ret;
+ size_t fill;
+ uint32_t left;
+
+ if( ilen == 0 )
+ return( 0 );
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+
+ if( ( ret = mbedcrypto_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ if( ( ret = mbedcrypto_internal_sha256_process( ctx, input ) ) != 0 )
+ return( ret );
+
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha256_update( mbedcrypto_sha256_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ mbedcrypto_sha256_update_ret( ctx, input, ilen );
+}
+#endif
+
+static const unsigned char sha256_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-256 final digest
+ */
+int mbedcrypto_sha256_finish_ret( mbedcrypto_sha256_context *ctx,
+ unsigned char output[32] )
+{
+ int ret;
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_BE( high, msglen, 0 );
+ PUT_UINT32_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ if( ( ret = mbedcrypto_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_sha256_update_ret( ctx, msglen, 8 ) ) != 0 )
+ return( ret );
+
+ PUT_UINT32_BE( ctx->state[0], output, 0 );
+ PUT_UINT32_BE( ctx->state[1], output, 4 );
+ PUT_UINT32_BE( ctx->state[2], output, 8 );
+ PUT_UINT32_BE( ctx->state[3], output, 12 );
+ PUT_UINT32_BE( ctx->state[4], output, 16 );
+ PUT_UINT32_BE( ctx->state[5], output, 20 );
+ PUT_UINT32_BE( ctx->state[6], output, 24 );
+
+ if( ctx->is224 == 0 )
+ PUT_UINT32_BE( ctx->state[7], output, 28 );
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha256_finish( mbedcrypto_sha256_context *ctx,
+ unsigned char output[32] )
+{
+ mbedcrypto_sha256_finish_ret( ctx, output );
+}
+#endif
+
+#endif /* !MBEDCRYPTO_SHA256_ALT */
+
+/*
+ * output = SHA-256( input buffer )
+ */
+int mbedcrypto_sha256_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[32],
+ int is224 )
+{
+ int ret;
+ mbedcrypto_sha256_context ctx;
+
+ mbedcrypto_sha256_init( &ctx );
+
+ if( ( ret = mbedcrypto_sha256_starts_ret( &ctx, is224 ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_sha256_update_ret( &ctx, input, ilen ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_sha256_finish_ret( &ctx, output ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedcrypto_sha256_free( &ctx );
+
+ return( ret );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha256( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[32],
+ int is224 )
+{
+ mbedcrypto_sha256_ret( input, ilen, output, is224 );
+}
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+/*
+ * FIPS-180-2 test vectors
+ */
+static const unsigned char sha256_test_buf[3][57] =
+{
+ { "abc" },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+ { "" }
+};
+
+static const size_t sha256_test_buflen[3] =
+{
+ 3, 56, 1000
+};
+
+static const unsigned char sha256_test_sum[6][32] =
+{
+ /*
+ * SHA-224 test vectors
+ */
+ { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
+ 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
+ 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
+ 0xE3, 0x6C, 0x9D, 0xA7 },
+ { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
+ 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
+ 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
+ 0x52, 0x52, 0x25, 0x25 },
+ { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
+ 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
+ 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
+ 0x4E, 0xE7, 0xAD, 0x67 },
+
+ /*
+ * SHA-256 test vectors
+ */
+ { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
+ 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
+ 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
+ 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
+ { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
+ 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
+ 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
+ 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
+ { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
+ 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
+ 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
+ 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_sha256_self_test( int verbose )
+{
+ int i, j, k, buflen, ret = 0;
+ unsigned char *buf;
+ unsigned char sha256sum[32];
+ mbedcrypto_sha256_context ctx;
+
+ buf = mbedcrypto_calloc( 1024, sizeof(unsigned char) );
+ if( NULL == buf )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "Buffer allocation failed\n" );
+
+ return( 1 );
+ }
+
+ mbedcrypto_sha256_init( &ctx );
+
+ for( i = 0; i < 6; i++ )
+ {
+ j = i % 3;
+ k = i < 3;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+
+ if( ( ret = mbedcrypto_sha256_starts_ret( &ctx, k ) ) != 0 )
+ goto fail;
+
+ if( j == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ {
+ ret = mbedcrypto_sha256_update_ret( &ctx, buf, buflen );
+ if( ret != 0 )
+ goto fail;
+ }
+
+ }
+ else
+ {
+ ret = mbedcrypto_sha256_update_ret( &ctx, sha256_test_buf[j],
+ sha256_test_buflen[j] );
+ if( ret != 0 )
+ goto fail;
+ }
+
+ if( ( ret = mbedcrypto_sha256_finish_ret( &ctx, sha256sum ) ) != 0 )
+ goto fail;
+
+
+ if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 )
+ {
+ ret = 1;
+ goto fail;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ goto exit;
+
+fail:
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+exit:
+ mbedcrypto_sha256_free( &ctx );
+ mbedcrypto_free( buf );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_SHA256_C */
diff --git a/library/sha512.c b/library/sha512.c
new file mode 100644
index 0000000..10aac33
--- /dev/null
+++ b/library/sha512.c
@@ -0,0 +1,600 @@
+/*
+ * FIPS-180-2 compliant SHA-384/512 implementation
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+/*
+ * The SHA-512 Secure Hash Standard was published by NIST in 2002.
+ *
+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_SHA512_C)
+
+#include "mbedcrypto/sha512.h"
+#include "mbedcrypto/platform_util.h"
+
+#if defined(_MSC_VER) || defined(__WATCOMC__)
+ #define UL64(x) x##ui64
+#else
+ #define UL64(x) x##ULL
+#endif
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedcrypto_printf printf
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_SHA512_ALT)
+
+/*
+ * 64-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT64_BE
+#define GET_UINT64_BE(n,b,i) \
+{ \
+ (n) = ( (uint64_t) (b)[(i) ] << 56 ) \
+ | ( (uint64_t) (b)[(i) + 1] << 48 ) \
+ | ( (uint64_t) (b)[(i) + 2] << 40 ) \
+ | ( (uint64_t) (b)[(i) + 3] << 32 ) \
+ | ( (uint64_t) (b)[(i) + 4] << 24 ) \
+ | ( (uint64_t) (b)[(i) + 5] << 16 ) \
+ | ( (uint64_t) (b)[(i) + 6] << 8 ) \
+ | ( (uint64_t) (b)[(i) + 7] ); \
+}
+#endif /* GET_UINT64_BE */
+
+#ifndef PUT_UINT64_BE
+#define PUT_UINT64_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
+ (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 7] = (unsigned char) ( (n) ); \
+}
+#endif /* PUT_UINT64_BE */
+
+void mbedcrypto_sha512_init( mbedcrypto_sha512_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_sha512_context ) );
+}
+
+void mbedcrypto_sha512_free( mbedcrypto_sha512_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_sha512_context ) );
+}
+
+void mbedcrypto_sha512_clone( mbedcrypto_sha512_context *dst,
+ const mbedcrypto_sha512_context *src )
+{
+ *dst = *src;
+}
+
+/*
+ * SHA-512 context setup
+ */
+int mbedcrypto_sha512_starts_ret( mbedcrypto_sha512_context *ctx, int is384 )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ if( is384 == 0 )
+ {
+ /* SHA-512 */
+ ctx->state[0] = UL64(0x6A09E667F3BCC908);
+ ctx->state[1] = UL64(0xBB67AE8584CAA73B);
+ ctx->state[2] = UL64(0x3C6EF372FE94F82B);
+ ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
+ ctx->state[4] = UL64(0x510E527FADE682D1);
+ ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
+ ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
+ ctx->state[7] = UL64(0x5BE0CD19137E2179);
+ }
+ else
+ {
+ /* SHA-384 */
+ ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
+ ctx->state[1] = UL64(0x629A292A367CD507);
+ ctx->state[2] = UL64(0x9159015A3070DD17);
+ ctx->state[3] = UL64(0x152FECD8F70E5939);
+ ctx->state[4] = UL64(0x67332667FFC00B31);
+ ctx->state[5] = UL64(0x8EB44A8768581511);
+ ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
+ ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
+ }
+
+ ctx->is384 = is384;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha512_starts( mbedcrypto_sha512_context *ctx,
+ int is384 )
+{
+ mbedcrypto_sha512_starts_ret( ctx, is384 );
+}
+#endif
+
+#if !defined(MBEDCRYPTO_SHA512_PROCESS_ALT)
+
+/*
+ * Round constants
+ */
+static const uint64_t K[80] =
+{
+ UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
+ UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
+ UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
+ UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
+ UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
+ UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
+ UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
+ UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
+ UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
+ UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
+ UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
+ UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
+ UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
+ UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
+ UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
+ UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
+ UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
+ UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
+ UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
+ UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
+ UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
+ UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
+ UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
+ UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
+ UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
+ UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
+ UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
+ UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
+ UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
+ UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
+ UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
+ UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
+ UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
+ UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
+ UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
+ UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
+ UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
+ UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
+ UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
+ UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
+};
+
+int mbedcrypto_internal_sha512_process( mbedcrypto_sha512_context *ctx,
+ const unsigned char data[128] )
+{
+ int i;
+ uint64_t temp1, temp2, W[80];
+ uint64_t A, B, C, D, E, F, G, H;
+
+#define SHR(x,n) (x >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
+
+#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
+#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
+
+#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
+#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ for( i = 0; i < 16; i++ )
+ {
+ GET_UINT64_BE( W[i], data, i << 3 );
+ }
+
+ for( ; i < 80; i++ )
+ {
+ W[i] = S1(W[i - 2]) + W[i - 7] +
+ S0(W[i - 15]) + W[i - 16];
+ }
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+ i = 0;
+
+ do
+ {
+ P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
+ P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
+ P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
+ P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
+ P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
+ P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
+ P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
+ P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
+ }
+ while( i < 80 );
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha512_process( mbedcrypto_sha512_context *ctx,
+ const unsigned char data[128] )
+{
+ mbedcrypto_internal_sha512_process( ctx, data );
+}
+#endif
+#endif /* !MBEDCRYPTO_SHA512_PROCESS_ALT */
+
+/*
+ * SHA-512 process buffer
+ */
+int mbedcrypto_sha512_update_ret( mbedcrypto_sha512_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ int ret;
+ size_t fill;
+ unsigned int left;
+
+ if( ilen == 0 )
+ return( 0 );
+
+ left = (unsigned int) (ctx->total[0] & 0x7F);
+ fill = 128 - left;
+
+ ctx->total[0] += (uint64_t) ilen;
+
+ if( ctx->total[0] < (uint64_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+
+ if( ( ret = mbedcrypto_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 128 )
+ {
+ if( ( ret = mbedcrypto_internal_sha512_process( ctx, input ) ) != 0 )
+ return( ret );
+
+ input += 128;
+ ilen -= 128;
+ }
+
+ if( ilen > 0 )
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha512_update( mbedcrypto_sha512_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ mbedcrypto_sha512_update_ret( ctx, input, ilen );
+}
+#endif
+
+static const unsigned char sha512_padding[128] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-512 final digest
+ */
+int mbedcrypto_sha512_finish_ret( mbedcrypto_sha512_context *ctx,
+ unsigned char output[64] )
+{
+ int ret;
+ size_t last, padn;
+ uint64_t high, low;
+ unsigned char msglen[16];
+
+ high = ( ctx->total[0] >> 61 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT64_BE( high, msglen, 0 );
+ PUT_UINT64_BE( low, msglen, 8 );
+
+ last = (size_t)( ctx->total[0] & 0x7F );
+ padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
+
+ if( ( ret = mbedcrypto_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedcrypto_sha512_update_ret( ctx, msglen, 16 ) ) != 0 )
+ return( ret );
+
+ PUT_UINT64_BE( ctx->state[0], output, 0 );
+ PUT_UINT64_BE( ctx->state[1], output, 8 );
+ PUT_UINT64_BE( ctx->state[2], output, 16 );
+ PUT_UINT64_BE( ctx->state[3], output, 24 );
+ PUT_UINT64_BE( ctx->state[4], output, 32 );
+ PUT_UINT64_BE( ctx->state[5], output, 40 );
+
+ if( ctx->is384 == 0 )
+ {
+ PUT_UINT64_BE( ctx->state[6], output, 48 );
+ PUT_UINT64_BE( ctx->state[7], output, 56 );
+ }
+
+ return( 0 );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha512_finish( mbedcrypto_sha512_context *ctx,
+ unsigned char output[64] )
+{
+ mbedcrypto_sha512_finish_ret( ctx, output );
+}
+#endif
+
+#endif /* !MBEDCRYPTO_SHA512_ALT */
+
+/*
+ * output = SHA-512( input buffer )
+ */
+int mbedcrypto_sha512_ret( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[64],
+ int is384 )
+{
+ int ret;
+ mbedcrypto_sha512_context ctx;
+
+ mbedcrypto_sha512_init( &ctx );
+
+ if( ( ret = mbedcrypto_sha512_starts_ret( &ctx, is384 ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_sha512_update_ret( &ctx, input, ilen ) ) != 0 )
+ goto exit;
+
+ if( ( ret = mbedcrypto_sha512_finish_ret( &ctx, output ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedcrypto_sha512_free( &ctx );
+
+ return( ret );
+}
+
+#if !defined(MBEDCRYPTO_DEPRECATED_REMOVED)
+void mbedcrypto_sha512( const unsigned char *input,
+ size_t ilen,
+ unsigned char output[64],
+ int is384 )
+{
+ mbedcrypto_sha512_ret( input, ilen, output, is384 );
+}
+#endif
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+/*
+ * FIPS-180-2 test vectors
+ */
+static const unsigned char sha512_test_buf[3][113] =
+{
+ { "abc" },
+ { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
+ { "" }
+};
+
+static const size_t sha512_test_buflen[3] =
+{
+ 3, 112, 1000
+};
+
+static const unsigned char sha512_test_sum[6][64] =
+{
+ /*
+ * SHA-384 test vectors
+ */
+ { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
+ 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
+ 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
+ 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
+ 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
+ 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
+ { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
+ 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
+ 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
+ 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
+ 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
+ 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
+ { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
+ 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
+ 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
+ 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
+ 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
+ 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
+
+ /*
+ * SHA-512 test vectors
+ */
+ { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
+ 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
+ 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
+ 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
+ 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
+ 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
+ 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
+ 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
+ { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
+ 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
+ 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
+ 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
+ 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
+ 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
+ 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
+ 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
+ { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
+ 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
+ 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
+ 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
+ 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
+ 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
+ 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
+ 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_sha512_self_test( int verbose )
+{
+ int i, j, k, buflen, ret = 0;
+ unsigned char *buf;
+ unsigned char sha512sum[64];
+ mbedcrypto_sha512_context ctx;
+
+ buf = mbedcrypto_calloc( 1024, sizeof(unsigned char) );
+ if( NULL == buf )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "Buffer allocation failed\n" );
+
+ return( 1 );
+ }
+
+ mbedcrypto_sha512_init( &ctx );
+
+ for( i = 0; i < 6; i++ )
+ {
+ j = i % 3;
+ k = i < 3;
+
+ if( verbose != 0 )
+ mbedcrypto_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+
+ if( ( ret = mbedcrypto_sha512_starts_ret( &ctx, k ) ) != 0 )
+ goto fail;
+
+ if( j == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ {
+ ret = mbedcrypto_sha512_update_ret( &ctx, buf, buflen );
+ if( ret != 0 )
+ goto fail;
+ }
+ }
+ else
+ {
+ ret = mbedcrypto_sha512_update_ret( &ctx, sha512_test_buf[j],
+ sha512_test_buflen[j] );
+ if( ret != 0 )
+ goto fail;
+ }
+
+ if( ( ret = mbedcrypto_sha512_finish_ret( &ctx, sha512sum ) ) != 0 )
+ goto fail;
+
+ if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
+ {
+ ret = 1;
+ goto fail;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+ goto exit;
+
+fail:
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+exit:
+ mbedcrypto_sha512_free( &ctx );
+ mbedcrypto_free( buf );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_SHA512_C */
diff --git a/library/xtea.c b/library/xtea.c
new file mode 100644
index 0000000..aa45819
--- /dev/null
+++ b/library/xtea.c
@@ -0,0 +1,277 @@
+/*
+ * An 32-bit implementation of the XTEA algorithm
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_XTEA_C)
+
+#include "mbedcrypto/xtea.h"
+#include "mbedcrypto/platform_util.h"
+
+#include <string.h>
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif /* MBEDCRYPTO_PLATFORM_C */
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#if !defined(MBEDCRYPTO_XTEA_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+void mbedcrypto_xtea_init( mbedcrypto_xtea_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedcrypto_xtea_context ) );
+}
+
+void mbedcrypto_xtea_free( mbedcrypto_xtea_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_xtea_context ) );
+}
+
+/*
+ * XTEA key schedule
+ */
+void mbedcrypto_xtea_setup( mbedcrypto_xtea_context *ctx, const unsigned char key[16] )
+{
+ int i;
+
+ memset( ctx, 0, sizeof(mbedcrypto_xtea_context) );
+
+ for( i = 0; i < 4; i++ )
+ {
+ GET_UINT32_BE( ctx->k[i], key, i << 2 );
+ }
+}
+
+/*
+ * XTEA encrypt function
+ */
+int mbedcrypto_xtea_crypt_ecb( mbedcrypto_xtea_context *ctx, int mode,
+ const unsigned char input[8], unsigned char output[8])
+{
+ uint32_t *k, v0, v1, i;
+
+ k = ctx->k;
+
+ GET_UINT32_BE( v0, input, 0 );
+ GET_UINT32_BE( v1, input, 4 );
+
+ if( mode == MBEDCRYPTO_XTEA_ENCRYPT )
+ {
+ uint32_t sum = 0, delta = 0x9E3779B9;
+
+ for( i = 0; i < 32; i++ )
+ {
+ v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
+ sum += delta;
+ v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
+ }
+ }
+ else /* MBEDCRYPTO_XTEA_DECRYPT */
+ {
+ uint32_t delta = 0x9E3779B9, sum = delta * 32;
+
+ for( i = 0; i < 32; i++ )
+ {
+ v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
+ sum -= delta;
+ v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
+ }
+ }
+
+ PUT_UINT32_BE( v0, output, 0 );
+ PUT_UINT32_BE( v1, output, 4 );
+
+ return( 0 );
+}
+
+#if defined(MBEDCRYPTO_CIPHER_MODE_CBC)
+/*
+ * XTEA-CBC buffer encryption/decryption
+ */
+int mbedcrypto_xtea_crypt_cbc( mbedcrypto_xtea_context *ctx, int mode, size_t length,
+ unsigned char iv[8], const unsigned char *input,
+ unsigned char *output)
+{
+ int i;
+ unsigned char temp[8];
+
+ if( length % 8 )
+ return( MBEDCRYPTO_ERR_XTEA_INVALID_INPUT_LENGTH );
+
+ if( mode == MBEDCRYPTO_XTEA_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, 8 );
+ mbedcrypto_xtea_crypt_ecb( ctx, mode, input, output );
+
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < 8; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ mbedcrypto_xtea_crypt_ecb( ctx, mode, output, output );
+ memcpy( iv, output, 8 );
+
+ input += 8;
+ output += 8;
+ length -= 8;
+ }
+ }
+
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_CIPHER_MODE_CBC */
+#endif /* !MBEDCRYPTO_XTEA_ALT */
+
+#if defined(MBEDCRYPTO_SELF_TEST)
+
+/*
+ * XTEA tests vectors (non-official)
+ */
+
+static const unsigned char xtea_test_key[6][16] =
+{
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const unsigned char xtea_test_pt[6][8] =
+{
+ { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+ { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f },
+ { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+ { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }
+};
+
+static const unsigned char xtea_test_ct[6][8] =
+{
+ { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 },
+ { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+ { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 },
+ { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d },
+ { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedcrypto_xtea_self_test( int verbose )
+{
+ int i, ret = 0;
+ unsigned char buf[8];
+ mbedcrypto_xtea_context ctx;
+
+ mbedcrypto_xtea_init( &ctx );
+ for( i = 0; i < 6; i++ )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( " XTEA test #%d: ", i + 1 );
+
+ memcpy( buf, xtea_test_pt[i], 8 );
+
+ mbedcrypto_xtea_setup( &ctx, xtea_test_key[i] );
+ mbedcrypto_xtea_crypt_ecb( &ctx, MBEDCRYPTO_XTEA_ENCRYPT, buf, buf );
+
+ if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedcrypto_printf( "failed\n" );
+
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedcrypto_printf( "\n" );
+
+exit:
+ mbedcrypto_xtea_free( &ctx );
+
+ return( ret );
+}
+
+#endif /* MBEDCRYPTO_SELF_TEST */
+
+#endif /* MBEDCRYPTO_XTEA_C */
diff --git a/programs/Makefile b/programs/Makefile
new file mode 100644
index 0000000..093b43d
--- /dev/null
+++ b/programs/Makefile
@@ -0,0 +1,51 @@
+CFLAGS ?= -O2 -I../include
+WARNING_CFLAGS ?= \
+ -Werror -Wall -Wextra \
+ -Wno-unused-function \
+ -Wno-overlength-strings \
+ -Wdeclaration-after-statement \
+# Don't delete this line.
+
+LDFLAGS ?= -L../library -lmbedcrypto
+
+DEP := ../library/libmbedcrypto.a
+
+APPS := \
+ psa/crypto_examples \
+ psa/key_ladder_demo \
+ psa/psa_constant_names \
+# Don't delete this line.
+
+EXTRA_GENERATED := \
+ psa/psa_constant_names_generated.c \
+# Don't delete this line.
+
+.SILENT:
+
+.PHONY: all clean list
+
+all: $(APPS)
+
+$(DEP):
+ $(MAKE) -C ../library
+
+psa/crypto_examples: psa/crypto_examples.c $(DEP)
+ echo " CC psa/crypto_examples.c"
+ $(CC) $(LOCAL_CFLAGS) $(CFLAGS) psa/crypto_examples.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
+psa/key_ladder_demo: psa/key_ladder_demo.c $(DEP)
+ echo " CC psa/key_ladder_demo.c"
+ $(CC) $(LOCAL_CFLAGS) $(CFLAGS) psa/key_ladder_demo.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
+psa/psa_constant_names_generated.c: ../scripts/generate_psa_constants.py ../include/psa/crypto.h
+ ../scripts/generate_psa_constants.py
+
+psa/psa_constant_names: psa/psa_constant_names_generated.c psa/psa_constant_names.c $(DEP)
+ echo " CC psa/psa_constant_names.c"
+ $(CC) $(LOCAL_CFLAGS) $(CFLAGS) psa/psa_constant_names.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
+clean:
+ rm -f $(APPS) $(EXTRA_GENERATED)
+
+list:
+ echo $(APPS)
diff --git a/programs/psa/crypto_examples.c b/programs/psa/crypto_examples.c
new file mode 100644
index 0000000..b755b11
--- /dev/null
+++ b/programs/psa/crypto_examples.c
@@ -0,0 +1,331 @@
+#include "psa/crypto.h"
+#include <string.h>
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_printf printf
+#endif
+
+#define ASSERT( predicate ) \
+ do \
+ { \
+ if( ! ( predicate ) ) \
+ { \
+ mbedcrypto_printf( "\tassertion failed at %s:%d - '%s'\r\n", \
+ __FILE__, __LINE__, #predicate); \
+ goto exit; \
+ } \
+ } while ( 0 )
+
+#define ASSERT_STATUS( actual, expected ) \
+ do \
+ { \
+ if( ( actual ) != ( expected ) ) \
+ { \
+ mbedcrypto_printf( "\tassertion failed at %s:%d - " \
+ "actual:%d expected:%d\r\n", __FILE__, __LINE__, \
+ (psa_status_t) actual, (psa_status_t) expected ); \
+ goto exit; \
+ } \
+ } while ( 0 )
+
+#if !defined(MBEDCRYPTO_PSA_CRYPTO_C) || !defined(MBEDCRYPTO_AES_C) || \
+ !defined(MBEDCRYPTO_CIPHER_MODE_CBC) || !defined(MBEDCRYPTO_CIPHER_MODE_CTR) || \
+ !defined(MBEDCRYPTO_CIPHER_MODE_WITH_PADDING)
+int main( void )
+{
+ mbedcrypto_printf( "MBEDCRYPTO_PSA_CRYPTO_C and/or MBEDCRYPTO_AES_C and/or "
+ "MBEDCRYPTO_CIPHER_MODE_CBC and/or MBEDCRYPTO_CIPHER_MODE_CTR "
+ "and/or MBEDCRYPTO_CIPHER_MODE_WITH_PADDING "
+ "not defined.\r\n" );
+ return( 0 );
+}
+#else
+
+/* Use key slot 1 for our cipher key. Key slot 0 is reserved as unused. */
+static const psa_key_slot_t key_slot_cipher = 1;
+
+static psa_status_t set_key_policy( psa_key_slot_t key_slot,
+ psa_key_usage_t key_usage,
+ psa_algorithm_t alg )
+{
+ psa_status_t status;
+ psa_key_policy_t policy;
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, key_usage, alg );
+ status = psa_set_key_policy( key_slot, &policy );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+exit:
+ return( status );
+}
+
+static psa_status_t cipher_operation( psa_cipher_operation_t *operation,
+ const uint8_t * input,
+ size_t input_size,
+ size_t part_size,
+ uint8_t * output,
+ size_t output_size,
+ size_t *output_len )
+{
+ psa_status_t status;
+ size_t bytes_to_write = 0, bytes_written = 0, len = 0;
+
+ *output_len = 0;
+ while( bytes_written != input_size )
+ {
+ bytes_to_write = ( input_size - bytes_written > part_size ?
+ part_size :
+ input_size - bytes_written );
+
+ status = psa_cipher_update( operation, input + bytes_written,
+ bytes_to_write, output + *output_len,
+ output_size - *output_len, &len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ bytes_written += bytes_to_write;
+ *output_len += len;
+ }
+
+ status = psa_cipher_finish( operation, output + *output_len,
+ output_size - *output_len, &len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+ *output_len += len;
+
+exit:
+ return( status );
+}
+
+static psa_status_t cipher_encrypt( psa_key_slot_t key_slot,
+ psa_algorithm_t alg,
+ uint8_t * iv,
+ size_t iv_size,
+ const uint8_t * input,
+ size_t input_size,
+ size_t part_size,
+ uint8_t * output,
+ size_t output_size,
+ size_t *output_len )
+{
+ psa_status_t status;
+ psa_cipher_operation_t operation;
+ size_t iv_len = 0;
+
+ memset( &operation, 0, sizeof( operation ) );
+ status = psa_cipher_encrypt_setup( &operation, key_slot, alg );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = psa_cipher_generate_iv( &operation, iv, iv_size, &iv_len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = cipher_operation( &operation, input, input_size, part_size,
+ output, output_size, output_len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+exit:
+ psa_cipher_abort( &operation );
+ return( status );
+}
+
+static psa_status_t cipher_decrypt( psa_key_slot_t key_slot,
+ psa_algorithm_t alg,
+ const uint8_t * iv,
+ size_t iv_size,
+ const uint8_t * input,
+ size_t input_size,
+ size_t part_size,
+ uint8_t * output,
+ size_t output_size,
+ size_t *output_len )
+{
+ psa_status_t status;
+ psa_cipher_operation_t operation;
+
+ memset( &operation, 0, sizeof( operation ) );
+ status = psa_cipher_decrypt_setup( &operation, key_slot, alg );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = psa_cipher_set_iv( &operation, iv, iv_size );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = cipher_operation( &operation, input, input_size, part_size,
+ output, output_size, output_len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+exit:
+ psa_cipher_abort( &operation );
+ return( status );
+}
+
+static psa_status_t
+cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( void )
+{
+ enum {
+ block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
+ key_bits = 256,
+ part_size = block_size,
+ };
+ const psa_algorithm_t alg = PSA_ALG_CBC_BASE |
+ PSA_ALG_BLOCK_CIPHER_PAD_NONE;
+
+ psa_status_t status;
+ size_t output_len = 0;
+ uint8_t iv[block_size];
+ uint8_t input[block_size];
+ uint8_t encrypt[block_size];
+ uint8_t decrypt[block_size];
+
+ status = psa_generate_random( input, sizeof( input ) );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = set_key_policy( key_slot_cipher,
+ PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
+ alg );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
+ NULL, 0 );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+ input, sizeof( input ), part_size,
+ encrypt, sizeof( encrypt ), &output_len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+ encrypt, output_len, part_size,
+ decrypt, sizeof( decrypt ), &output_len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = memcmp( input, decrypt, sizeof( input ) );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+exit:
+ psa_destroy_key( key_slot_cipher );
+ return( status );
+}
+
+static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( void )
+{
+ enum {
+ block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
+ key_bits = 256,
+ input_size = 100,
+ part_size = 10,
+ };
+
+ const psa_algorithm_t alg = PSA_ALG_CBC_BASE |
+ PSA_ALG_BLOCK_CIPHER_PAD_PKCS7;
+
+ psa_status_t status;
+ size_t output_len = 0;
+ uint8_t iv[block_size], input[input_size],
+ encrypt[input_size + block_size], decrypt[input_size + block_size];
+
+ status = psa_generate_random( input, sizeof( input ) );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = set_key_policy( key_slot_cipher,
+ PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
+ alg );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
+ NULL, 0 );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+ input, sizeof( input ), part_size,
+ encrypt, sizeof( encrypt ), &output_len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+ encrypt, output_len, part_size,
+ decrypt, sizeof( decrypt ), &output_len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = memcmp( input, decrypt, sizeof( input ) );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+exit:
+ psa_destroy_key( key_slot_cipher );
+ return( status );
+}
+
+static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi( void )
+{
+ enum {
+ block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
+ key_bits = 256,
+ input_size = 100,
+ part_size = 10,
+ };
+ const psa_algorithm_t alg = PSA_ALG_CTR;
+
+ psa_status_t status;
+ size_t output_len = 0;
+ uint8_t iv[block_size], input[input_size], encrypt[input_size],
+ decrypt[input_size];
+
+ status = psa_generate_random( input, sizeof( input ) );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = set_key_policy( key_slot_cipher,
+ PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
+ alg );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
+ NULL, 0 );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+ input, sizeof( input ), part_size,
+ encrypt, sizeof( encrypt ), &output_len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+ encrypt, output_len, part_size,
+ decrypt, sizeof( decrypt ), &output_len );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+ status = memcmp( input, decrypt, sizeof( input ) );
+ ASSERT_STATUS( status, PSA_SUCCESS );
+
+exit:
+ psa_destroy_key( key_slot_cipher );
+ return( status );
+}
+
+static void cipher_examples( void )
+{
+ psa_status_t status;
+
+ mbedcrypto_printf( "cipher encrypt/decrypt AES CBC no padding:\r\n" );
+ status = cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( );
+ if( status == PSA_SUCCESS )
+ mbedcrypto_printf( "\tsuccess!\r\n" );
+
+ mbedcrypto_printf( "cipher encrypt/decrypt AES CBC PKCS7 multipart:\r\n" );
+ status = cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( );
+ if( status == PSA_SUCCESS )
+ mbedcrypto_printf( "\tsuccess!\r\n" );
+
+ mbedcrypto_printf( "cipher encrypt/decrypt AES CTR multipart:\r\n" );
+ status = cipher_example_encrypt_decrypt_aes_ctr_multi( );
+ if( status == PSA_SUCCESS )
+ mbedcrypto_printf( "\tsuccess!\r\n" );
+}
+
+int main( void )
+{
+ ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+ cipher_examples( );
+exit:
+ mbedcrypto_psa_crypto_free( );
+ return( 0 );
+}
+#endif /* MBEDCRYPTO_PSA_CRYPTO_C && MBEDCRYPTO_AES_C && MBEDCRYPTO_CIPHER_MODE_CBC &&
+ MBEDCRYPTO_CIPHER_MODE_CTR && MBEDCRYPTO_CIPHER_MODE_WITH_PADDING */
diff --git a/programs/psa/key_ladder_demo.c b/programs/psa/key_ladder_demo.c
new file mode 100644
index 0000000..af91bec
--- /dev/null
+++ b/programs/psa/key_ladder_demo.c
@@ -0,0 +1,682 @@
+/**
+ * PSA API key derivation demonstration
+ *
+ * This program calculates a key ladder: a chain of secret material, each
+ * derived from the previous one in a deterministic way based on a label.
+ * Two keys are identical if and only if they are derived from the same key
+ * using the same label.
+ *
+ * The initial key is called the master key. The master key is normally
+ * randomly generated, but it could itself be derived from another key.
+ *
+ * This program derives a series of keys called intermediate keys.
+ * The first intermediate key is derived from the master key using the
+ * first label passed on the command line. Each subsequent intermediate
+ * key is derived from the previous one using the next label passed
+ * on the command line.
+ *
+ * This program has four modes of operation:
+ *
+ * - "generate": generate a random master key.
+ * - "wrap": derive a wrapping key from the last intermediate key,
+ * and use that key to encrypt-and-authenticate some data.
+ * - "unwrap": derive a wrapping key from the last intermediate key,
+ * and use that key to decrypt-and-authenticate some
+ * ciphertext created by wrap mode.
+ * - "save": save the last intermediate key so that it can be reused as
+ * the master key in another run of the program.
+ *
+ * See the usage() output for the command line usage. See the file
+ * `key_ladder_demo.sh` for an example run.
+ */
+
+/* Copyright (C) 2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+/* First include Mbed Crypto headers to get the Mbed Crypto configuration and
+ * platform definitions that we'll use in this program. Also include
+ * standard C headers for functions we'll use here. */
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include "mbedcrypto/config.h"
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdlib.h>
+#define MBEDCRYPTO_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDCRYPTO_EXIT_FAILURE EXIT_FAILURE
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#define mbedcrypto_printf printf
+#endif
+#include <stdio.h>
+#include <string.h>
+
+#include "mbedcrypto/platform_util.h" // for mbedcrypto_platform_zeroize
+
+/* If the build options we need are not enabled, compile a placeholder. */
+#if !defined(MBEDCRYPTO_SHA256_C) || !defined(MBEDCRYPTO_MD_C) || \
+ !defined(MBEDCRYPTO_AES_C) || !defined(MBEDCRYPTO_CCM_C) || \
+ !defined(MBEDCRYPTO_PSA_CRYPTO_C) || !defined(MBEDCRYPTO_FS_IO)
+int main( void )
+{
+ mbedcrypto_printf("MBEDCRYPTO_SHA256_C and/or MBEDCRYPTO_MD_C and/or "
+ "MBEDCRYPTO_AES_C and/or MBEDCRYPTO_CCM_C and/or "
+ "MBEDCRYPTO_PSA_CRYPTO_C and/or MBEDCRYPTO_FS_IO not defined.\n");
+ return( 0 );
+}
+#else
+
+/* The real program starts here. */
+
+
+
+#include <psa/crypto.h>
+
+/* Run a system function and bail out if it fails. */
+#define SYS_CHECK( expr ) \
+ do \
+ { \
+ if( ! ( expr ) ) \
+ { \
+ perror( #expr ); \
+ status = DEMO_ERROR; \
+ goto exit; \
+ } \
+ } \
+ while( 0 )
+
+/* Run a PSA function and bail out if it fails. */
+#define PSA_CHECK( expr ) \
+ do \
+ { \
+ status = ( expr ); \
+ if( status != PSA_SUCCESS ) \
+ { \
+ mbedcrypto_printf( "Error %d at line %u: %s\n", \
+ (int) status, \
+ __LINE__, \
+ #expr ); \
+ goto exit; \
+ } \
+ } \
+ while( 0 )
+
+/* To report operational errors in this program, use an error code that is
+ * different from every PSA error code. */
+#define DEMO_ERROR 120
+
+/* The maximum supported key ladder depth. */
+#define MAX_LADDER_DEPTH 10
+
+/* Salt to use when deriving an intermediate key. */
+#define DERIVE_KEY_SALT ( (uint8_t *) "key_ladder_demo.derive" )
+#define DERIVE_KEY_SALT_LENGTH ( strlen( (const char*) DERIVE_KEY_SALT ) )
+
+/* Salt to use when deriving a wrapping key. */
+#define WRAPPING_KEY_SALT ( (uint8_t *) "key_ladder_demo.wrap" )
+#define WRAPPING_KEY_SALT_LENGTH ( strlen( (const char*) WRAPPING_KEY_SALT ) )
+
+/* Size of the key derivation keys (applies both to the master key and
+ * to intermediate keys). */
+#define KEY_SIZE_BYTES 40
+
+/* Algorithm for key derivation. */
+#define KDF_ALG PSA_ALG_HKDF( PSA_ALG_SHA_256 )
+
+/* Type and size of the key used to wrap data. */
+#define WRAPPING_KEY_TYPE PSA_KEY_TYPE_AES
+#define WRAPPING_KEY_BITS 128
+
+/* Cipher mode used to wrap data. */
+#define WRAPPING_ALG PSA_ALG_CCM
+
+/* Nonce size used to wrap data. */
+#define WRAPPING_IV_SIZE 13
+
+/* Header used in files containing wrapped data. We'll save this header
+ * directly without worrying about data representation issues such as
+ * integer sizes and endianness, because the data is meant to be read
+ * back by the same program on the same machine. */
+#define WRAPPED_DATA_MAGIC "key_ladder_demo" // including trailing null byte
+#define WRAPPED_DATA_MAGIC_LENGTH ( sizeof( WRAPPED_DATA_MAGIC ) )
+typedef struct
+{
+ char magic[WRAPPED_DATA_MAGIC_LENGTH];
+ size_t ad_size; /* Size of the additional data, which is this header. */
+ size_t payload_size; /* Size of the encrypted data. */
+ /* Store the IV inside the additional data. It's convenient. */
+ uint8_t iv[WRAPPING_IV_SIZE];
+} wrapped_data_header_t;
+
+/* This program uses three key slots: one for the master key, one to
+ * derive intermediate keys, and one for the wrapping key. We use a
+ * single slot for all the intermediate keys because they are only
+ * needed successively, so each time we derive an intermediate key,
+ * we destroy the previous one. */
+static const psa_key_slot_t master_key_slot = 1;
+static const psa_key_slot_t derived_key_slot = 2;
+static const psa_key_slot_t wrapping_key_slot = 3;
+
+/* The modes that this program can operate in (see usage). */
+enum program_mode
+{
+ MODE_GENERATE,
+ MODE_SAVE,
+ MODE_UNWRAP,
+ MODE_WRAP
+};
+
+/* Save a key to a file. In the real world, you may want to export a derived
+ * key sometimes, to share it with another party. */
+static psa_status_t save_key( psa_key_slot_t key_slot,
+ const char *output_file_name )
+{
+ psa_status_t status = PSA_SUCCESS;
+ uint8_t key_data[KEY_SIZE_BYTES];
+ size_t key_size;
+ FILE *key_file = NULL;
+
+ PSA_CHECK( psa_export_key( key_slot,
+ key_data, sizeof( key_data ),
+ &key_size ) );
+ SYS_CHECK( ( key_file = fopen( output_file_name, "wb" ) ) != NULL );
+ SYS_CHECK( fwrite( key_data, 1, key_size, key_file ) == key_size );
+ SYS_CHECK( fclose( key_file ) == 0 );
+ key_file = NULL;
+
+exit:
+ if( key_file != NULL)
+ fclose( key_file );
+ return( status );
+}
+
+/* Generate a master key for use in this demo.
+ *
+ * Normally a master key would be non-exportable. For the purpose of this
+ * demo, we want to save it to a file, to avoid relying on the keystore
+ * capability of the PSA crypto library. */
+static psa_status_t generate( const char *key_file_name )
+{
+ psa_status_t status = PSA_SUCCESS;
+ psa_key_policy_t policy;
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy,
+ PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT,
+ KDF_ALG );
+ PSA_CHECK( psa_set_key_policy( master_key_slot, &policy ) );
+
+ PSA_CHECK( psa_generate_key( master_key_slot,
+ PSA_KEY_TYPE_DERIVE,
+ PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ),
+ NULL, 0 ) );
+
+ PSA_CHECK( save_key( master_key_slot, key_file_name ) );
+
+exit:
+ return( status );
+}
+
+/* Load the master key from a file.
+ *
+ * In the real world, this master key would be stored in an internal memory
+ * and the storage would be managed by the keystore capability of the PSA
+ * crypto library. */
+static psa_status_t import_key_from_file( psa_key_slot_t key_slot,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg,
+ const char *key_file_name )
+{
+ psa_status_t status = PSA_SUCCESS;
+ psa_key_policy_t policy;
+ uint8_t key_data[KEY_SIZE_BYTES];
+ size_t key_size;
+ FILE *key_file = NULL;
+ unsigned char extra_byte;
+
+ SYS_CHECK( ( key_file = fopen( key_file_name, "rb" ) ) != NULL );
+ SYS_CHECK( ( key_size = fread( key_data, 1, sizeof( key_data ),
+ key_file ) ) != 0 );
+ if( fread( &extra_byte, 1, 1, key_file ) != 0 )
+ {
+ mbedcrypto_printf( "Key file too large (max: %u).\n",
+ (unsigned) sizeof( key_data ) );
+ status = DEMO_ERROR;
+ goto exit;
+ }
+ SYS_CHECK( fclose( key_file ) == 0 );
+ key_file = NULL;
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, usage, alg );
+ PSA_CHECK( psa_set_key_policy( key_slot, &policy ) );
+ PSA_CHECK( psa_import_key( key_slot,
+ PSA_KEY_TYPE_DERIVE,
+ key_data, key_size ) );
+exit:
+ if( key_file != NULL )
+ fclose( key_file );
+ mbedcrypto_platform_zeroize( key_data, sizeof( key_data ) );
+ return( status );
+}
+
+/* Derive the intermediate keys, using the list of labels provided on
+ * the command line. */
+static psa_status_t derive_key_ladder( const char *ladder[],
+ size_t ladder_depth )
+{
+ psa_status_t status = PSA_SUCCESS;
+ psa_key_policy_t policy;
+ psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ /* We'll derive the first intermediate key from the master key, then
+ * each subsequent intemediate key from the previous intemediate key. */
+ psa_key_slot_t parent_key_slot = master_key_slot;
+ size_t i;
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy,
+ PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT,
+ KDF_ALG );
+
+ /* For each label in turn, ... */
+ for( i = 0; i < ladder_depth; i++ )
+ {
+ /* Start deriving material from the master key (if i=0) or from
+ * the current intermediate key (if i>0). */
+ PSA_CHECK( psa_key_derivation(
+ &generator,
+ parent_key_slot,
+ KDF_ALG,
+ DERIVE_KEY_SALT, DERIVE_KEY_SALT_LENGTH,
+ (uint8_t*) ladder[i], strlen( ladder[i] ),
+ KEY_SIZE_BYTES ) );
+ /* When the parent key is not the master key, destroy it,
+ * since it is no longer needed. */
+ if( i != 0 )
+ PSA_CHECK( psa_destroy_key( derived_key_slot ) );
+ PSA_CHECK( psa_set_key_policy( derived_key_slot, &policy ) );
+ /* Use the generator obtained from the parent key to create
+ * the next intermediate key. */
+ PSA_CHECK( psa_generator_import_key(
+ derived_key_slot,
+ PSA_KEY_TYPE_DERIVE,
+ PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ),
+ &generator ) );
+ PSA_CHECK( psa_generator_abort( &generator ) );
+ parent_key_slot = derived_key_slot;
+ }
+
+exit:
+ psa_generator_abort( &generator );
+ return( status );
+}
+
+/* Derive a wrapping key from the last intermediate key. */
+static psa_status_t derive_wrapping_key( psa_key_usage_t usage )
+{
+ psa_status_t status = PSA_SUCCESS;
+ psa_key_policy_t policy;
+ psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, usage, WRAPPING_ALG );
+ PSA_CHECK( psa_set_key_policy( wrapping_key_slot, &policy ) );
+
+ PSA_CHECK( psa_key_derivation(
+ &generator,
+ derived_key_slot,
+ KDF_ALG,
+ WRAPPING_KEY_SALT, WRAPPING_KEY_SALT_LENGTH,
+ NULL, 0,
+ PSA_BITS_TO_BYTES( WRAPPING_KEY_BITS ) ) );
+ PSA_CHECK( psa_generator_import_key(
+ wrapping_key_slot,
+ PSA_KEY_TYPE_AES,
+ WRAPPING_KEY_BITS,
+ &generator ) );
+
+exit:
+ psa_generator_abort( &generator );
+ return( status );
+}
+
+static psa_status_t wrap_data( const char *input_file_name,
+ const char *output_file_name )
+{
+ psa_status_t status;
+ FILE *input_file = NULL;
+ FILE *output_file = NULL;
+ long input_position;
+ size_t input_size;
+ size_t buffer_size;
+ unsigned char *buffer = NULL;
+ size_t ciphertext_size;
+ wrapped_data_header_t header;
+
+ /* Find the size of the data to wrap. */
+ SYS_CHECK( ( input_file = fopen( input_file_name, "rb" ) ) != NULL );
+ SYS_CHECK( fseek( input_file, 0, SEEK_END ) == 0 );
+ SYS_CHECK( ( input_position = ftell( input_file ) ) != -1 );
+#if LONG_MAX > SIZE_MAX
+ if( input_position > SIZE_MAX )
+ {
+ mbedcrypto_printf( "Input file too large.\n" );
+ status = DEMO_ERROR;
+ goto exit;
+ }
+#endif
+ input_size = input_position;
+ buffer_size = PSA_AEAD_ENCRYPT_OUTPUT_SIZE( WRAPPING_ALG, input_size );
+ /* Check for integer overflow. */
+ if( buffer_size < input_size )
+ {
+ mbedcrypto_printf( "Input file too large.\n" );
+ status = DEMO_ERROR;
+ goto exit;
+ }
+
+ /* Load the data to wrap. */
+ SYS_CHECK( fseek( input_file, 0, SEEK_SET ) == 0 );
+ SYS_CHECK( ( buffer = mbedcrypto_calloc( 1, buffer_size ) ) != NULL );
+ SYS_CHECK( fread( buffer, 1, input_size, input_file ) == input_size );
+ SYS_CHECK( fclose( input_file ) == 0 );
+ input_file = NULL;
+
+ /* Construct a header. */
+ memcpy( &header.magic, WRAPPED_DATA_MAGIC, WRAPPED_DATA_MAGIC_LENGTH );
+ header.ad_size = sizeof( header );
+ header.payload_size = input_size;
+
+ /* Wrap the data. */
+ PSA_CHECK( psa_generate_random( header.iv, WRAPPING_IV_SIZE ) );
+ PSA_CHECK( psa_aead_encrypt( wrapping_key_slot, WRAPPING_ALG,
+ header.iv, WRAPPING_IV_SIZE,
+ (uint8_t *) &header, sizeof( header ),
+ buffer, input_size,
+ buffer, buffer_size,
+ &ciphertext_size ) );
+
+ /* Write the output. */
+ SYS_CHECK( ( output_file = fopen( output_file_name, "wb" ) ) != NULL );
+ SYS_CHECK( fwrite( &header, 1, sizeof( header ),
+ output_file ) == sizeof( header ) );
+ SYS_CHECK( fwrite( buffer, 1, ciphertext_size,
+ output_file ) == ciphertext_size );
+ SYS_CHECK( fclose( output_file ) == 0 );
+ output_file = NULL;
+
+exit:
+ if( input_file != NULL )
+ fclose( input_file );
+ if( output_file != NULL )
+ fclose( output_file );
+ if( buffer != NULL )
+ mbedcrypto_platform_zeroize( buffer, buffer_size );
+ mbedcrypto_free( buffer );
+ return( status );
+}
+
+static psa_status_t unwrap_data( const char *input_file_name,
+ const char *output_file_name )
+{
+ psa_status_t status;
+ FILE *input_file = NULL;
+ FILE *output_file = NULL;
+ unsigned char *buffer = NULL;
+ size_t ciphertext_size;
+ size_t plaintext_size;
+ wrapped_data_header_t header;
+ unsigned char extra_byte;
+
+ /* Load and validate the header. */
+ SYS_CHECK( ( input_file = fopen( input_file_name, "rb" ) ) != NULL );
+ SYS_CHECK( fread( &header, 1, sizeof( header ),
+ input_file ) == sizeof( header ) );
+ if( memcmp( &header.magic, WRAPPED_DATA_MAGIC,
+ WRAPPED_DATA_MAGIC_LENGTH ) != 0 )
+ {
+ mbedcrypto_printf( "The input does not start with a valid magic header.\n" );
+ status = DEMO_ERROR;
+ goto exit;
+ }
+ if( header.ad_size != sizeof( header ) )
+ {
+ mbedcrypto_printf( "The header size is not correct.\n" );
+ status = DEMO_ERROR;
+ goto exit;
+ }
+ ciphertext_size =
+ PSA_AEAD_ENCRYPT_OUTPUT_SIZE( WRAPPING_ALG, header.payload_size );
+ /* Check for integer overflow. */
+ if( ciphertext_size < header.payload_size )
+ {
+ mbedcrypto_printf( "Input file too large.\n" );
+ status = DEMO_ERROR;
+ goto exit;
+ }
+
+ /* Load the payload data. */
+ SYS_CHECK( ( buffer = mbedcrypto_calloc( 1, ciphertext_size ) ) != NULL );
+ SYS_CHECK( fread( buffer, 1, ciphertext_size,
+ input_file ) == ciphertext_size );
+ if( fread( &extra_byte, 1, 1, input_file ) != 0 )
+ {
+ mbedcrypto_printf( "Extra garbage after ciphertext\n" );
+ status = DEMO_ERROR;
+ goto exit;
+ }
+ SYS_CHECK( fclose( input_file ) == 0 );
+ input_file = NULL;
+
+ /* Unwrap the data. */
+ PSA_CHECK( psa_aead_decrypt( wrapping_key_slot, WRAPPING_ALG,
+ header.iv, WRAPPING_IV_SIZE,
+ (uint8_t *) &header, sizeof( header ),
+ buffer, ciphertext_size,
+ buffer, ciphertext_size,
+ &plaintext_size ) );
+ if( plaintext_size != header.payload_size )
+ {
+ mbedcrypto_printf( "Incorrect payload size in the header.\n" );
+ status = DEMO_ERROR;
+ goto exit;
+ }
+
+ /* Write the output. */
+ SYS_CHECK( ( output_file = fopen( output_file_name, "wb" ) ) != NULL );
+ SYS_CHECK( fwrite( buffer, 1, plaintext_size,
+ output_file ) == plaintext_size );
+ SYS_CHECK( fclose( output_file ) == 0 );
+ output_file = NULL;
+
+exit:
+ if( input_file != NULL )
+ fclose( input_file );
+ if( output_file != NULL )
+ fclose( output_file );
+ if( buffer != NULL )
+ mbedcrypto_platform_zeroize( buffer, ciphertext_size );
+ mbedcrypto_free( buffer );
+ return( status );
+}
+
+static psa_status_t run( enum program_mode mode,
+ const char *key_file_name,
+ const char *ladder[], size_t ladder_depth,
+ const char *input_file_name,
+ const char *output_file_name )
+{
+ psa_status_t status = PSA_SUCCESS;
+
+ /* Initialize the PSA crypto library. */
+ PSA_CHECK( psa_crypto_init( ) );
+
+ /* Generate mode is unlike the others. Generate the master key and exit. */
+ if( mode == MODE_GENERATE )
+ return( generate( key_file_name ) );
+
+ /* Read the master key. */
+ PSA_CHECK( import_key_from_file( master_key_slot,
+ PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT,
+ KDF_ALG,
+ key_file_name ) );
+
+ /* Calculate the derived key for this session. */
+ PSA_CHECK( derive_key_ladder( ladder, ladder_depth ) );
+
+ switch( mode )
+ {
+ case MODE_SAVE:
+ PSA_CHECK( save_key( derived_key_slot, output_file_name ) );
+ break;
+ case MODE_UNWRAP:
+ PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_DECRYPT ) );
+ PSA_CHECK( unwrap_data( input_file_name, output_file_name ) );
+ break;
+ case MODE_WRAP:
+ PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_ENCRYPT ) );
+ PSA_CHECK( wrap_data( input_file_name, output_file_name ) );
+ break;
+ default:
+ /* Unreachable but some compilers don't realize it. */
+ break;
+ }
+
+exit:
+ /* Deinitialize the PSA crypto library. */
+ mbedcrypto_psa_crypto_free( );
+ return( status );
+}
+
+static void usage( void )
+{
+ mbedcrypto_printf( "Usage: key_ladder_demo MODE [OPTION=VALUE]...\n" );
+ mbedcrypto_printf( "Demonstrate the usage of a key derivation ladder.\n" );
+ mbedcrypto_printf( "\n" );
+ mbedcrypto_printf( "Modes:\n" );
+ mbedcrypto_printf( " generate Generate the master key\n" );
+ mbedcrypto_printf( " save Save the derived key\n" );
+ mbedcrypto_printf( " unwrap Unwrap (decrypt) input with the derived key\n" );
+ mbedcrypto_printf( " wrap Wrap (encrypt) input with the derived key\n" );
+ mbedcrypto_printf( "\n" );
+ mbedcrypto_printf( "Options:\n" );
+ mbedcrypto_printf( " input=FILENAME Input file (required for wrap/unwrap)\n" );
+ mbedcrypto_printf( " master=FILENAME File containing the master key (default: master.key)\n" );
+ mbedcrypto_printf( " output=FILENAME Output file (required for save/wrap/unwrap)\n" );
+ mbedcrypto_printf( " label=TEXT Label for the key derivation.\n" );
+ mbedcrypto_printf( " This may be repeated multiple times.\n" );
+ mbedcrypto_printf( " To get the same key, you must use the same master key\n" );
+ mbedcrypto_printf( " and the same sequence of labels.\n" );
+}
+
+int main( int argc, char *argv[] )
+{
+ char *key_file_name = "master.key";
+ char *input_file_name = NULL;
+ char *output_file_name = NULL;
+ const char *ladder[MAX_LADDER_DEPTH];
+ size_t ladder_depth = 0;
+ int i;
+ enum program_mode mode;
+ psa_status_t status;
+
+ if( argc <= 1 ||
+ strcmp( argv[1], "help" ) == 0 ||
+ strcmp( argv[1], "-help" ) == 0 ||
+ strcmp( argv[1], "--help" ) == 0 )
+ {
+ usage( );
+ return( MBEDCRYPTO_EXIT_SUCCESS );
+ }
+
+ for( i = 2; i < argc; i++ )
+ {
+ char *q = strchr( argv[i], '=' );
+ if( q == NULL )
+ {
+ mbedcrypto_printf( "Missing argument to option %s\n", argv[i] );
+ goto usage_failure;
+ }
+ *q = 0;
+ ++q;
+ if( strcmp( argv[i], "input" ) == 0 )
+ input_file_name = q;
+ else if( strcmp( argv[i], "label" ) == 0 )
+ {
+ if( ladder_depth == MAX_LADDER_DEPTH )
+ {
+ mbedcrypto_printf( "Maximum ladder depth %u exceeded.\n",
+ (unsigned) MAX_LADDER_DEPTH );
+ return( MBEDCRYPTO_EXIT_FAILURE );
+ }
+ ladder[ladder_depth] = q;
+ ++ladder_depth;
+ }
+ else if( strcmp( argv[i], "master" ) == 0 )
+ key_file_name = q;
+ else if( strcmp( argv[i], "output" ) == 0 )
+ output_file_name = q;
+ else
+ {
+ mbedcrypto_printf( "Unknown option: %s\n", argv[i] );
+ goto usage_failure;
+ }
+ }
+
+ if( strcmp( argv[1], "generate" ) == 0 )
+ mode = MODE_GENERATE;
+ else if( strcmp( argv[1], "save" ) == 0 )
+ mode = MODE_SAVE;
+ else if( strcmp( argv[1], "unwrap" ) == 0 )
+ mode = MODE_UNWRAP;
+ else if( strcmp( argv[1], "wrap" ) == 0 )
+ mode = MODE_WRAP;
+ else
+ {
+ mbedcrypto_printf( "Unknown action: %s\n", argv[1] );
+ goto usage_failure;
+ }
+
+ if( input_file_name == NULL &&
+ ( mode == MODE_WRAP || mode == MODE_UNWRAP ) )
+ {
+ mbedcrypto_printf( "Required argument missing: input\n" );
+ return( DEMO_ERROR );
+ }
+ if( output_file_name == NULL &&
+ ( mode == MODE_SAVE || mode == MODE_WRAP || mode == MODE_UNWRAP ) )
+ {
+ mbedcrypto_printf( "Required argument missing: output\n" );
+ return( DEMO_ERROR );
+ }
+
+ status = run( mode, key_file_name,
+ ladder, ladder_depth,
+ input_file_name, output_file_name );
+ return( status == PSA_SUCCESS ?
+ MBEDCRYPTO_EXIT_SUCCESS :
+ MBEDCRYPTO_EXIT_FAILURE );
+
+usage_failure:
+ usage( );
+ return( MBEDCRYPTO_EXIT_FAILURE );
+}
+#endif /* MBEDCRYPTO_SHA256_C && MBEDCRYPTO_MD_C && MBEDCRYPTO_AES_C && MBEDCRYPTO_CCM_C && MBEDCRYPTO_PSA_CRYPTO_C && MBEDCRYPTO_FS_IO */
diff --git a/programs/psa/key_ladder_demo.sh b/programs/psa/key_ladder_demo.sh
new file mode 100755
index 0000000..2cec945
--- /dev/null
+++ b/programs/psa/key_ladder_demo.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+set -e -u
+
+program="${0%/*}"/key_ladder_demo
+files_to_clean=
+
+run () {
+ echo
+ echo "# $1"
+ shift
+ echo "+ $*"
+ "$@"
+}
+
+if [ -e master.key ]; then
+ echo "# Reusing the existing master.key file."
+else
+ files_to_clean="$files_to_clean master.key"
+ run "Generate a master key." \
+ "$program" generate master=master.key
+fi
+
+files_to_clean="$files_to_clean input.txt hello_world.wrap"
+echo "Here is some input. See it wrapped." >input.txt
+run "Derive a key and wrap some data with it." \
+ "$program" wrap master=master.key label=hello label=world \
+ input=input.txt output=hello_world.wrap
+
+files_to_clean="$files_to_clean hello_world.txt"
+run "Derive the same key again and unwrap the data." \
+ "$program" unwrap master=master.key label=hello label=world \
+ input=hello_world.wrap output=hello_world.txt
+run "Compare the unwrapped data with the original input." \
+ cmp input.txt hello_world.txt
+
+files_to_clean="$files_to_clean hellow_orld.txt"
+! run "Derive a different key and attempt to unwrap the data. This must fail." \
+ "$program" unwrap master=master.key input=hello_world.wrap output=hellow_orld.txt label=hellow label=orld
+
+files_to_clean="$files_to_clean hello.key"
+run "Save the first step of the key ladder, then load it as a master key and construct the rest of the ladder." \
+ "$program" save master=master.key label=hello \
+ input=hello_world.wrap output=hello.key
+run "Check that we get the same key by unwrapping data made by the other key." \
+ "$program" unwrap master=hello.key label=world \
+ input=hello_world.wrap output=hello_world.txt
+
+# Cleanup
+rm -f $files_to_clean
diff --git a/programs/psa/psa_constant_names.c b/programs/psa/psa_constant_names.c
new file mode 100644
index 0000000..d422e14
--- /dev/null
+++ b/programs/psa/psa_constant_names.c
@@ -0,0 +1,157 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "psa/crypto.h"
+
+/* There are different GET_HASH macros for different kinds of algorithms
+ * built from hashes, but the values are all constructed on the
+ * same model. */
+#define PSA_ALG_GET_HASH(alg) \
+ (((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH)
+
+static void append(char **buffer, size_t buffer_size,
+ size_t *required_size,
+ const char *string, size_t length)
+{
+ *required_size += length;
+ if (*required_size < buffer_size) {
+ memcpy(*buffer, string, length);
+ *buffer += length;
+ }
+}
+
+/* The code of these function is automatically generated and included below. */
+static const char *psa_ecc_curve_name(psa_ecc_curve_t curve);
+static const char *psa_hash_algorithm_name(psa_algorithm_t hash_alg);
+
+static void append_with_curve(char **buffer, size_t buffer_size,
+ size_t *required_size,
+ const char *string, size_t length,
+ psa_ecc_curve_t curve)
+{
+ const char *curve_name = psa_ecc_curve_name(curve);
+ append(buffer, buffer_size, required_size, string, length);
+ append(buffer, buffer_size, required_size, "(", 1);
+ if (curve_name != NULL) {
+ append(buffer, buffer_size, required_size,
+ curve_name, strlen(curve_name));
+ } else {
+ size_t n = snprintf(*buffer, buffer_size - *required_size,
+ "0x%04x", (unsigned) curve);
+ if (n < buffer_size - *required_size) *buffer += n;
+ *required_size += n;
+ }
+ append(buffer, buffer_size, required_size, ")", 1);
+}
+
+static void append_with_hash(char **buffer, size_t buffer_size,
+ size_t *required_size,
+ const char *string, size_t length,
+ psa_algorithm_t hash_alg)
+{
+ const char *hash_name = psa_hash_algorithm_name(hash_alg);
+ append(buffer, buffer_size, required_size, string, length);
+ append(buffer, buffer_size, required_size, "(", 1);
+ if (hash_name != NULL) {
+ append(buffer, buffer_size, required_size,
+ hash_name, strlen(hash_name));
+ } else {
+ size_t n = snprintf(*buffer, buffer_size - *required_size,
+ "0x%08lx", (unsigned long) hash_alg);
+ if (n < buffer_size - *required_size) *buffer += n;
+ *required_size += n;
+ }
+ append(buffer, buffer_size, required_size, ")", 1);
+}
+
+#include "psa_constant_names_generated.c"
+
+static int psa_snprint_status(char *buffer, size_t buffer_size,
+ psa_status_t status)
+{
+ const char *name = psa_strerror(status);
+ if (name == NULL) {
+ return snprintf(buffer, buffer_size, "%ld", (long) status);
+ } else {
+ size_t length = strlen(name);
+ if (length < buffer_size) {
+ memcpy(buffer, name, length + 1);
+ return length;
+ } else {
+ return buffer_size;
+ }
+ }
+}
+
+static int psa_snprint_ecc_curve(char *buffer, size_t buffer_size,
+ psa_ecc_curve_t curve)
+{
+ const char *name = psa_ecc_curve_name(curve);
+ if (name == NULL) {
+ return snprintf(buffer, buffer_size, "0x%04x", (unsigned) curve);
+ } else {
+ size_t length = strlen(name);
+ if (length < buffer_size) {
+ memcpy(buffer, name, length + 1);
+ return length;
+ } else {
+ return buffer_size;
+ }
+ }
+}
+
+static void usage(const char *program_name)
+{
+ printf("Usage: %s TYPE VALUE\n",
+ program_name == NULL ? "psa_constant_names" : program_name);
+ printf("Print the symbolic name whose numerical value is VALUE in TYPE.\n");
+ printf("Supported types (with = between aliases):\n");
+ printf(" alg=algorithm Status code (psa_algorithm_t)\n");
+ printf(" curve=ecc_curve Elliptic curve identifier (psa_ecc_curve_t)\n");
+ printf(" type=key_type Status code (psa_key_type_t)\n");
+ printf(" usage=key_usage Key usage (psa_key_usage_t)\n");
+ printf(" error=status Status code (psa_status_t)\n");
+}
+
+int main(int argc, char *argv[])
+{
+ char buffer[200];
+ unsigned long value;
+ char *end;
+
+ if (argc <= 1 ||
+ !strcmp(argv[1], "help") ||
+ !strcmp(argv[1], "--help"))
+ {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ if (argc != 3) {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ value = strtoul(argv[2], &end, 0);
+ if (*end) {
+ printf("Non-numeric value: %s\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+
+ if (!strcmp(argv[1], "error") || !strcmp(argv[1], "status"))
+ psa_snprint_status(buffer, sizeof(buffer), value);
+ else if (!strcmp(argv[1], "alg") || !strcmp(argv[1], "algorithm"))
+ psa_snprint_algorithm(buffer, sizeof(buffer), value);
+ else if (!strcmp(argv[1], "curve") || !strcmp(argv[1], "ecc_curve"))
+ psa_snprint_ecc_curve(buffer, sizeof(buffer), value);
+ else if (!strcmp(argv[1], "type") || !strcmp(argv[1], "key_type"))
+ psa_snprint_key_type(buffer, sizeof(buffer), value);
+ else if (!strcmp(argv[1], "usage") || !strcmp(argv[1], "key_usage"))
+ psa_snprint_key_usage(buffer, sizeof(buffer), value);
+ else {
+ printf("Unknown type: %s\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ puts(buffer);
+ return EXIT_SUCCESS;
+}
diff --git a/scripts/config.pl b/scripts/config.pl
new file mode 100755
index 0000000..0f1e093
--- /dev/null
+++ b/scripts/config.pl
@@ -0,0 +1,297 @@
+#!/usr/bin/perl
+#
+# This file is part of Mbed Crypto (https://tls.mbed.org)
+#
+# Copyright (c) 2014-2016, ARM Limited, All Rights Reserved
+#
+# Purpose
+#
+# Comments and uncomments #define lines in the given header file and optionally
+# sets their value or can get the value. This is to provide scripting control of
+# what preprocessor symbols, and therefore what build time configuration flags
+# are set in the 'config.h' file.
+#
+# Usage: config.pl [-f <file> | --file <file>] [-o | --force]
+# [set <symbol> <value> | unset <symbol> | get <symbol> |
+# full | realfull]
+#
+# Full usage description provided below.
+#
+# The following options are disabled instead of enabled with "full".
+#
+# MBEDCRYPTO_TEST_NULL_ENTROPY
+# MBEDCRYPTO_DEPRECATED_REMOVED
+# MBEDCRYPTO_HAVE_SSE2
+# MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS
+# MBEDCRYPTO_ECP_DP_M221_ENABLED
+# MBEDCRYPTO_ECP_DP_M383_ENABLED
+# MBEDCRYPTO_ECP_DP_M511_ENABLED
+# MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES
+# MBEDCRYPTO_NO_PLATFORM_ENTROPY
+# MBEDCRYPTO_REMOVE_ARC4_CIPHERSUITES
+# MBEDCRYPTO_SSL_HW_RECORD_ACCEL
+# MBEDCRYPTO_RSA_NO_CRT
+# MBEDCRYPTO_X509_ALLOW_EXTENSIONS_NON_V3
+# MBEDCRYPTO_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+# - this could be enabled if the respective tests were adapted
+# MBEDCRYPTO_ZLIB_SUPPORT
+# MBEDCRYPTO_PKCS11_C
+# and any symbol beginning _ALT
+#
+
+use warnings;
+use strict;
+
+my $config_file = "include/mbedcrypto/config.h";
+my $usage = <<EOU;
+$0 [-f <file> | --file <file>] [-o | --force]
+ [set <symbol> <value> | unset <symbol> | get <symbol> |
+ full | realfull | baremetal]
+
+Commands
+ set <symbol> [<value>] - Uncomments or adds a #define for the <symbol> to
+ the configuration file, and optionally making it
+ of <value>.
+ If the symbol isn't present in the file an error
+ is returned.
+ unset <symbol> - Comments out the #define for the given symbol if
+ present in the configuration file.
+ get <symbol> - Finds the #define for the given symbol, returning
+ an exitcode of 0 if the symbol is found, and 1 if
+ not. The value of the symbol is output if one is
+ specified in the configuration file.
+ full - Uncomments all #define's in the configuration file
+ excluding some reserved symbols, until the
+ 'Module configuration options' section
+ realfull - Uncomments all #define's with no exclusions
+ baremetal - Sets full configuration suitable for baremetal build.
+
+Options
+ -f | --file <filename> - The file or file path for the configuration file
+ to edit. When omitted, the following default is
+ used:
+ $config_file
+ -o | --force - If the symbol isn't present in the configuration
+ file when setting its value, a #define is
+ appended to the end of the file.
+
+EOU
+
+my @excluded = qw(
+MBEDCRYPTO_TEST_NULL_ENTROPY
+MBEDCRYPTO_DEPRECATED_REMOVED
+MBEDCRYPTO_HAVE_SSE2
+MBEDCRYPTO_PLATFORM_NO_STD_FUNCTIONS
+MBEDCRYPTO_ECP_DP_M221_ENABLED
+MBEDCRYPTO_ECP_DP_M383_ENABLED
+MBEDCRYPTO_ECP_DP_M511_ENABLED
+MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES
+MBEDCRYPTO_NO_PLATFORM_ENTROPY
+MBEDCRYPTO_RSA_NO_CRT
+MBEDCRYPTO_REMOVE_ARC4_CIPHERSUITES
+MBEDCRYPTO_SSL_HW_RECORD_ACCEL
+MBEDCRYPTO_X509_ALLOW_EXTENSIONS_NON_V3
+MBEDCRYPTO_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+MBEDCRYPTO_ZLIB_SUPPORT
+MBEDCRYPTO_PKCS11_C
+MBEDCRYPTO_NO_UDBL_DIVISION
+MBEDCRYPTO_PSA_CRYPTO_SPM
+_ALT\s*$
+);
+
+# Things that should be disabled in "baremetal"
+my @excluded_baremetal = qw(
+MBEDCRYPTO_NET_C
+MBEDCRYPTO_TIMING_C
+MBEDCRYPTO_FS_IO
+MBEDCRYPTO_ENTROPY_NV_SEED
+MBEDCRYPTO_HAVE_TIME
+MBEDCRYPTO_HAVE_TIME_DATE
+MBEDCRYPTO_DEPRECATED_WARNING
+MBEDCRYPTO_HAVEGE_C
+MBEDCRYPTO_THREADING_C
+MBEDCRYPTO_THREADING_PTHREAD
+MBEDCRYPTO_MEMORY_BACKTRACE
+MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C
+MBEDCRYPTO_PLATFORM_TIME_ALT
+MBEDCRYPTO_PLATFORM_FPRINTF_ALT
+);
+
+# Things that should be enabled in "full" even if they match @excluded
+my @non_excluded = qw(
+PLATFORM_[A-Z0-9]+_ALT
+);
+
+# Things that should be enabled in "baremetal"
+my @non_excluded_baremetal = qw(
+MBEDCRYPTO_NO_PLATFORM_ENTROPY
+);
+
+# Process the command line arguments
+
+my $force_option = 0;
+
+my ($arg, $name, $value, $action);
+
+while ($arg = shift) {
+
+ # Check if the argument is an option
+ if ($arg eq "-f" || $arg eq "--file") {
+ $config_file = shift;
+
+ -f $config_file or die "No such file: $config_file\n";
+
+ }
+ elsif ($arg eq "-o" || $arg eq "--force") {
+ $force_option = 1;
+
+ }
+ else
+ {
+ # ...else assume it's a command
+ $action = $arg;
+
+ if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) {
+ # No additional parameters
+ die $usage if @ARGV;
+
+ }
+ elsif ($action eq "unset" || $action eq "get") {
+ die $usage unless @ARGV;
+ $name = shift;
+
+ }
+ elsif ($action eq "set") {
+ die $usage unless @ARGV;
+ $name = shift;
+ $value = shift if @ARGV;
+
+ }
+ else {
+ die "Command '$action' not recognised.\n\n".$usage;
+ }
+ }
+}
+
+# If no command was specified, exit...
+if ( not defined($action) ){ die $usage; }
+
+# Check the config file is present
+if (! -f $config_file) {
+
+ chdir '..' or die;
+
+ # Confirm this is the project root directory and try again
+ if ( !(-d 'scripts' && -d 'include' && -d 'library' && -f $config_file) ) {
+ die "If no file specified, must be run from the project root or scripts directory.\n";
+ }
+}
+
+
+# Now read the file and process the contents
+
+open my $config_read, '<', $config_file or die "read $config_file: $!\n";
+my @config_lines = <$config_read>;
+close $config_read;
+
+# Add required baremetal symbols to the list that is included.
+if ( $action eq "baremetal" ) {
+ @non_excluded = ( @non_excluded, @non_excluded_baremetal );
+}
+
+my ($exclude_re, $no_exclude_re, $exclude_baremetal_re);
+if ($action eq "realfull") {
+ $exclude_re = qr/^$/;
+ $no_exclude_re = qr/./;
+} else {
+ $exclude_re = join '|', @excluded;
+ $no_exclude_re = join '|', @non_excluded;
+}
+if ( $action eq "baremetal" ) {
+ $exclude_baremetal_re = join '|', @excluded_baremetal;
+}
+
+my $config_write = undef;
+if ($action ne "get") {
+ open $config_write, '>', $config_file or die "write $config_file: $!\n";
+}
+
+my $done;
+for my $line (@config_lines) {
+ if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) {
+ if ($line =~ /name SECTION: Module configuration options/) {
+ $done = 1;
+ }
+
+ if (!$done && $line =~ m!^//\s?#define! &&
+ ( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) &&
+ ( $action ne "baremetal" || ( $line !~ /$exclude_baremetal_re/ ) ) ) {
+ $line =~ s!^//\s?!!;
+ }
+ if (!$done && $line =~ m!^\s?#define! &&
+ ! ( ( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) &&
+ ( $action ne "baremetal" || ( $line !~ /$exclude_baremetal_re/ ) ) ) ) {
+ $line =~ s!^!//!;
+ }
+ } elsif ($action eq "unset") {
+ if (!$done && $line =~ /^\s*#define\s*$name\b/) {
+ $line = '//' . $line;
+ $done = 1;
+ }
+ } elsif (!$done && $action eq "set") {
+ if ($line =~ m!^(?://)?\s*#define\s*$name\b!) {
+ $line = "#define $name";
+ $line .= " $value" if defined $value && $value ne "";
+ $line .= "\n";
+ $done = 1;
+ }
+ } elsif (!$done && $action eq "get") {
+ if ($line =~ /^\s*#define\s*$name(?:\s+(.*?))\s*(?:$|\/\*|\/\/)/) {
+ $value = $1;
+ $done = 1;
+ }
+ }
+
+ if (defined $config_write) {
+ print $config_write $line or die "write $config_file: $!\n";
+ }
+}
+
+# Did the set command work?
+if ($action eq "set" && $force_option && !$done) {
+
+ # If the force option was set, append the symbol to the end of the file
+ my $line = "#define $name";
+ $line .= " $value" if defined $value && $value ne "";
+ $line .= "\n";
+ $done = 1;
+
+ print $config_write $line or die "write $config_file: $!\n";
+}
+
+if (defined $config_write) {
+ close $config_write or die "close $config_file: $!\n";
+}
+
+if ($action eq "get") {
+ if ($done) {
+ if ($value ne '') {
+ print "$value\n";
+ }
+ exit 0;
+ } else {
+ # If the symbol was not found, return an error
+ exit 1;
+ }
+}
+
+if ($action eq "full" && !$done) {
+ die "Configuration section was not found in $config_file\n";
+
+}
+
+if ($action ne "full" && $action ne "unset" && !$done) {
+ die "A #define for the symbol $name was not found in $config_file\n";
+}
+
+__END__
diff --git a/scripts/generate_psa_constants.py b/scripts/generate_psa_constants.py
new file mode 100755
index 0000000..5a5d2e5
--- /dev/null
+++ b/scripts/generate_psa_constants.py
@@ -0,0 +1,301 @@
+#!/usr/bin/env python
+import os
+import re
+import sys
+
+output_template = '''\
+/* Automatically generated by generate_psa_constant.py. DO NOT EDIT. */
+
+static const char *psa_strerror(psa_status_t status)
+{
+ switch (status) {
+ %(status_cases)s
+ default: return NULL;
+ }
+}
+
+static const char *psa_ecc_curve_name(psa_ecc_curve_t curve)
+{
+ switch (curve) {
+ %(ecc_curve_cases)s
+ default: return NULL;
+ }
+}
+
+static const char *psa_hash_algorithm_name(psa_algorithm_t hash_alg)
+{
+ switch (hash_alg) {
+ %(hash_algorithm_cases)s
+ default: return NULL;
+ }
+}
+
+static int psa_snprint_key_type(char *buffer, size_t buffer_size,
+ psa_key_type_t type)
+{
+ size_t required_size = 0;
+ switch (type) {
+ %(key_type_cases)s
+ default:
+ %(key_type_code)s{
+ return snprintf(buffer, buffer_size,
+ "0x%%08lx", (unsigned long) type);
+ }
+ break;
+ }
+ buffer[0] = 0;
+ return required_size;
+}
+
+static void append_padding_mode(char **buffer, size_t buffer_size,
+ size_t *required_size,
+ psa_algorithm_t padding_mode)
+{
+ size_t n;
+ append(buffer, buffer_size, required_size, " | ", 3);
+ switch (padding_mode) {
+ %(padding_mode_cases)s
+ default:
+ n = snprintf(*buffer, buffer_size - *required_size,
+ "0x%%08lx", (unsigned long) padding_mode);
+ if (n < buffer_size - *required_size) *buffer += n;
+ *required_size += n;
+ break;
+ }
+}
+
+static int psa_snprint_algorithm(char *buffer, size_t buffer_size,
+ psa_algorithm_t alg)
+{
+ size_t required_size = 0;
+ psa_algorithm_t padding_mode = -1;
+ psa_algorithm_t alg_without_padding = alg;
+ if (PSA_ALG_IS_CIPHER(alg) && PSA_ALG_IS_BLOCK_CIPHER(alg)) {
+ padding_mode = alg & PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
+ alg_without_padding = alg & ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
+ }
+ switch (alg_without_padding) {
+ %(algorithm_cases)s
+ default:
+ %(algorithm_code)s{
+ return snprintf(buffer, buffer_size,
+ "0x%%08lx", (unsigned long) alg);
+ }
+ break;
+ }
+ if (padding_mode != (psa_algorithm_t) -1) {
+ append_padding_mode(&buffer, buffer_size, &required_size, padding_mode);
+ }
+ buffer[0] = 0;
+ return required_size;
+}
+
+static int psa_snprint_key_usage(char *buffer, size_t buffer_size,
+ psa_key_usage_t usage)
+{
+ size_t required_size = 0;
+ if (usage == 0) {
+ if (buffer_size > 1) {
+ buffer[0] = '0';
+ buffer[1] = 0;
+ } else if (buffer_size == 1) {
+ buffer[0] = 0;
+ }
+ return 1;
+ }
+%(key_usage_code)s
+ if (usage != 0) {
+ if (required_size != 0) {
+ append(&buffer, buffer_size, &required_size, " | ", 3);
+ }
+ required_size += snprintf(buffer, buffer_size - required_size,
+ "0x%%08x", usage);
+ } else {
+ buffer[0] = 0;
+ }
+ return required_size;
+}
+
+/* End of automatically generated file. */
+'''
+
+key_type_from_curve_template = '''if (%(tester)s(type)) {
+ append_with_curve(&buffer, buffer_size, &required_size,
+ "%(builder)s", %(builder_length)s,
+ PSA_KEY_TYPE_GET_CURVE(type));
+ } else '''
+
+algorithm_from_hash_template = '''if (%(tester)s(alg_without_padding)) {
+ append_with_hash(&buffer, buffer_size, &required_size,
+ "%(builder)s", %(builder_length)s,
+ PSA_ALG_GET_HASH(alg_without_padding));
+ } else '''
+
+bit_test_template = '''\
+ if (%(var)s & %(flag)s) {
+ if (required_size != 0) {
+ append(&buffer, buffer_size, &required_size, " | ", 3);
+ }
+ append(&buffer, buffer_size, &required_size, "%(flag)s", %(length)d);
+ %(var)s ^= %(flag)s;
+ }\
+'''
+
+class MacroCollector:
+ def __init__(self):
+ self.statuses = set()
+ self.key_types = set()
+ self.key_types_from_curve = {}
+ self.ecc_curves = set()
+ self.algorithms = set()
+ self.hash_algorithms = set()
+ self.block_cipher_padding_modes = set()
+ self.algorithms_from_hash = {}
+ self.key_usages = set()
+
+ # "#define" followed by a macro name with either no parameters
+ # or a single parameter. Grab the macro name in group 1, the
+ # parameter name if any in group 2 and the definition in group 3.
+ definition_re = re.compile(r'\s*#\s*define\s+(\w+)(?:\s+|\((\w+)\)\s*)(.+)(?:/[*/])?')
+
+ def read_line(self, line):
+ m = re.match(self.definition_re, line)
+ if not m:
+ return
+ name, parameter, definition = m.groups()
+ if name.endswith('_FLAG') or name.endswith('MASK'):
+ # Macro only to build actual values
+ return
+ elif (name.startswith('PSA_ERROR_') or name == 'PSA_SUCCESS') \
+ and not parameter:
+ self.statuses.add(name)
+ elif name.startswith('PSA_KEY_TYPE_') and not parameter:
+ self.key_types.add(name)
+ elif name.startswith('PSA_KEY_TYPE_') and parameter == 'curve':
+ self.key_types_from_curve[name] = name[:13] + 'IS_' + name[13:]
+ elif name.startswith('PSA_ECC_CURVE_') and not parameter:
+ self.ecc_curves.add(name)
+ elif name.startswith('PSA_ALG_BLOCK_CIPHER_PAD_') and not parameter:
+ self.block_cipher_padding_modes.add(name)
+ elif name.startswith('PSA_ALG_') and not parameter:
+ if name in ['PSA_ALG_BLOCK_CIPHER_BASE',
+ 'PSA_ALG_ECDSA_BASE',
+ 'PSA_ALG_RSA_PKCS1V15_SIGN_BASE']:
+ # Ad hoc skipping of duplicate names for some numerical values
+ return
+ self.algorithms.add(name)
+ # Ad hoc detection of hash algorithms
+ if re.search(r'0x010000[0-9A-Fa-f]{2}', definition):
+ self.hash_algorithms.add(name)
+ elif name.startswith('PSA_ALG_') and parameter == 'hash_alg':
+ if name in ['PSA_ALG_DSA', 'PSA_ALG_ECDSA']:
+ # A naming irregularity
+ tester = name[:8] + 'IS_RANDOMIZED_' + name[8:]
+ else:
+ tester = name[:8] + 'IS_' + name[8:]
+ self.algorithms_from_hash[name] = tester
+ elif name.startswith('PSA_KEY_USAGE_') and not parameter:
+ self.key_usages.add(name)
+ else:
+ # Other macro without parameter
+ return
+
+ def read_file(self, header_file):
+ for line in header_file:
+ self.read_line(line)
+
+ def make_return_case(self, name):
+ return 'case %(name)s: return "%(name)s";' % {'name': name}
+
+ def make_append_case(self, name):
+ template = ('case %(name)s: '
+ 'append(&buffer, buffer_size, &required_size, "%(name)s", %(length)d); '
+ 'break;')
+ return template % {'name': name, 'length': len(name)}
+
+ def make_inner_append_case(self, name):
+ template = ('case %(name)s: '
+ 'append(buffer, buffer_size, required_size, "%(name)s", %(length)d); '
+ 'break;')
+ return template % {'name': name, 'length': len(name)}
+
+ def make_bit_test(self, var, flag):
+ return bit_test_template % {'var': var,
+ 'flag': flag,
+ 'length': len(flag)}
+
+ def make_status_cases(self):
+ return '\n '.join(map(self.make_return_case,
+ sorted(self.statuses)))
+
+ def make_ecc_curve_cases(self):
+ return '\n '.join(map(self.make_return_case,
+ sorted(self.ecc_curves)))
+
+ def make_key_type_cases(self):
+ return '\n '.join(map(self.make_append_case,
+ sorted(self.key_types)))
+
+ def make_key_type_from_curve_code(self, builder, tester):
+ return key_type_from_curve_template % {'builder': builder,
+ 'builder_length': len(builder),
+ 'tester': tester}
+
+ def make_key_type_code(self):
+ d = self.key_types_from_curve
+ make = self.make_key_type_from_curve_code
+ return ''.join([make(k, d[k]) for k in sorted(d.keys())])
+
+ def make_hash_algorithm_cases(self):
+ return '\n '.join(map(self.make_return_case,
+ sorted(self.hash_algorithms)))
+
+ def make_padding_mode_cases(self):
+ return '\n '.join(map(self.make_inner_append_case,
+ sorted(self.block_cipher_padding_modes)))
+
+ def make_algorithm_cases(self):
+ return '\n '.join(map(self.make_append_case,
+ sorted(self.algorithms)))
+
+ def make_algorithm_from_hash_code(self, builder, tester):
+ return algorithm_from_hash_template % {'builder': builder,
+ 'builder_length': len(builder),
+ 'tester': tester}
+
+ def make_algorithm_code(self):
+ d = self.algorithms_from_hash
+ make = self.make_algorithm_from_hash_code
+ return ''.join([make(k, d[k]) for k in sorted(d.keys())])
+
+ def make_key_usage_code(self):
+ return '\n'.join([self.make_bit_test('usage', bit)
+ for bit in sorted(self.key_usages)])
+
+ def write_file(self, output_file):
+ data = {}
+ data['status_cases'] = self.make_status_cases()
+ data['ecc_curve_cases'] = self.make_ecc_curve_cases()
+ data['key_type_cases'] = self.make_key_type_cases()
+ data['key_type_code'] = self.make_key_type_code()
+ data['hash_algorithm_cases'] = self.make_hash_algorithm_cases()
+ data['padding_mode_cases'] = self.make_padding_mode_cases()
+ data['algorithm_cases'] = self.make_algorithm_cases()
+ data['algorithm_code'] = self.make_algorithm_code()
+ data['key_usage_code'] = self.make_key_usage_code()
+ output_file.write(output_template % data)
+
+def generate_psa_constants(header_file_name, output_file_name):
+ collector = MacroCollector()
+ with open(header_file_name) as header_file:
+ collector.read_file(header_file)
+ temp_file_name = output_file_name + '.tmp'
+ with open(temp_file_name, 'w') as output_file:
+ collector.write_file(output_file)
+ os.rename(temp_file_name, output_file_name)
+
+if __name__ == '__main__':
+ if not os.path.isdir('programs') and os.path.isdir('../programs'):
+ os.chdir('..')
+ generate_psa_constants('include/psa/crypto.h',
+ 'programs/psa/psa_constant_names_generated.c')
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 0000000..3315a6e
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,73 @@
+CFLAGS ?= -O2 -I../include
+WARNING_CFLAGS ?= \
+ -Werror -Wall -Wextra \
+ -Wno-unused-function \
+ -Wno-overlength-strings \
+ -Wdeclaration-after-statement \
+# Don't delete this line.
+
+LDFLAGS ?= -L../library -lmbedcrypto
+
+DEP := ../library/libmbedcrypto.a
+
+# Python executable
+PYTHON ?= python
+
+APPS := \
+ test_suite_psa_crypto \
+# Don't delete this line.
+
+# Look up for associated function files
+func.test_suite_psa_crypto := test_suite_psa_crypto
+
+.SILENT:
+
+.PHONY: all test clean
+
+all: $(APPS)
+
+$(DEP):
+ $(MAKE) -C ../library
+
+C_FILES := $(addsuffix .c,$(APPS))
+
+.SECONDEXPANSION:
+$(C_FILES): %.c: suites/$$(func.$$*).function suites/%.data scripts/generate_test_code.py suites/helpers.function suites/main_test.function suites/host_test.function
+ echo " Gen $@"
+ $(PYTHON) scripts/generate_test_code.py -f suites/$(func.$*).function \
+ -d suites/$*.data \
+ -t suites/main_test.function \
+ -p suites/host_test.function \
+ -s suites \
+ --help-file suites/helpers.function \
+ -o .
+
+
+$(APPS): %: %.c $(DEP)
+ echo " CC $<"
+ $(CC) $(CFLAGS) $(WARNING_CFLAGS) $< $(LDFLAGS) -o $@
+
+clean:
+ rm -rf $(APPS) *.c *.data TESTS
+ rm -rf data_files/ctr_drbg_seed data_files/hmac_drbg_seed data_files/mpi_write
+
+test: $(APPS)
+ ./test_suite_psa_crypto
+
+# Create separate targets for generating embedded tests.
+EMBEDDED_TESTS := $(addprefix embedded_,$(APPS))
+
+# Generate test code for target.
+
+.SECONDEXPANSION:
+$(EMBEDDED_TESTS): embedded_%: suites/$$(func.$$*).function suites/%.data scripts/generate_test_code.py suites/helpers.function suites/main_test.function suites/target_test.function
+ echo " Gen ./TESTS/mbedcrypto/$*/$*.c"
+ $(PYTHON) scripts/generate_test_code.py -f suites/$(func.$*).function \
+ -d suites/$*.data \
+ -t suites/main_test.function \
+ -p suites/target_test.function \
+ -s suites \
+ --help-file suites/helpers.function \
+ -o ./TESTS/mbedcrypto/$*
+
+gen-embedded-test: $(EMBEDDED_TESTS)
diff --git a/tests/scripts/generate_test_code.py b/tests/scripts/generate_test_code.py
new file mode 100755
index 0000000..345df53
--- /dev/null
+++ b/tests/scripts/generate_test_code.py
@@ -0,0 +1,729 @@
+#!/usr/bin/env python3
+# Test suites code generator.
+#
+# Copyright (C) 2018, ARM Limited, All Rights Reserved
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# This file is part of Mbed Crypto (https://tls.mbed.org)
+
+"""
+Test Suite code generator.
+
+Generates a test source file using following input files:
+
+test_suite_xyz.function - Read test functions from test suite functions file.
+test_suite_xyz.data - Read test functions and their dependencies to generate
+ dispatch and dependency check code.
+main template - Substitute generated test function dispatch code, dependency
+ checking code.
+platform .function - Read host or target platform implementation for
+ dispatching test cases from .data file.
+helper .function - Read common reusable functions.
+"""
+
+
+import io
+import os
+import re
+import sys
+import argparse
+import shutil
+
+
+BEGIN_HEADER_REGEX = '/\*\s*BEGIN_HEADER\s*\*/'
+END_HEADER_REGEX = '/\*\s*END_HEADER\s*\*/'
+
+BEGIN_SUITE_HELPERS_REGEX = '/\*\s*BEGIN_SUITE_HELPERS\s*\*/'
+END_SUITE_HELPERS_REGEX = '/\*\s*END_SUITE_HELPERS\s*\*/'
+
+BEGIN_DEP_REGEX = 'BEGIN_DEPENDENCIES'
+END_DEP_REGEX = 'END_DEPENDENCIES'
+
+BEGIN_CASE_REGEX = '/\*\s*BEGIN_CASE\s*(.*?)\s*\*/'
+END_CASE_REGEX = '/\*\s*END_CASE\s*\*/'
+
+
+class InvalidFileFormat(Exception):
+ """
+ Exception to indicate invalid file format.
+ """
+ pass
+
+
+class FileWrapper(io.FileIO):
+ """
+ File wrapper class. Provides reading with line no. tracking.
+ """
+
+ def __init__(self, file_name):
+ """
+ Init file handle.
+
+ :param file_name: File path to open.
+ """
+ super(FileWrapper, self).__init__(file_name, 'r')
+ self.line_no = 0
+
+ # Override the generator function in a way that works in both Python 2
+ # and Python 3.
+ def __next__(self):
+ """
+ Iterator return impl.
+ :return: Line read from file.
+ """
+ parent = super(FileWrapper, self)
+ if hasattr(parent, '__next__'):
+ line = parent.__next__() # Python 3
+ else:
+ line = parent.next() # Python 2
+ if line:
+ self.line_no += 1
+ # Convert byte array to string with correct encoding
+ return line.decode(sys.getdefaultencoding())
+ return None
+ next = __next__
+
+
+def split_dep(dep):
+ """
+ Split NOT character '!' from dependency. Used by gen_deps()
+
+ :param dep: Dependency list
+ :return: list of tuples where index 0 has '!' if there was a '!' before the dependency string
+ """
+ return ('!', dep[1:]) if dep[0] == '!' else ('', dep)
+
+
+def gen_deps(deps):
+ """
+ Generates dependency i.e. if def and endif code
+
+ :param deps: List of dependencies.
+ :return: if defined and endif code with macro annotations for readability.
+ """
+ dep_start = ''.join(['#if %sdefined(%s)\n' % split_dep(x) for x in deps])
+ dep_end = ''.join(['#endif /* %s */\n' % x for x in reversed(deps)])
+
+ return dep_start, dep_end
+
+
+def gen_deps_one_line(deps):
+ """
+ Generates dependency checks in one line. Useful for writing code in #else case.
+
+ :param deps: List of dependencies.
+ :return: ifdef code
+ """
+ defines = ('#if ' if len(deps) else '') + ' && '.join(['%sdefined(%s)' % split_dep(x) for x in deps])
+ return defines
+
+
+def gen_function_wrapper(name, locals, args_dispatch):
+ """
+ Creates test function wrapper code. A wrapper has the code to unpack parameters from parameters[] array.
+
+ :param name: Test function name
+ :param locals: Local variables declaration code
+ :param args_dispatch: List of dispatch arguments. Ex: ['(char *)params[0]', '*((int *)params[1])']
+ :return: Test function wrapper.
+ """
+ # Then create the wrapper
+ wrapper = '''
+void {name}_wrapper( void ** params )
+{{
+{unused_params}{locals}
+ {name}( {args} );
+}}
+'''.format(name=name,
+ unused_params='' if args_dispatch else ' (void) params;\n',
+ args=', '.join(args_dispatch),
+ locals=locals)
+ return wrapper
+
+
+def gen_dispatch(name, deps):
+ """
+ Generates dispatch code for the test function table.
+
+ :param name: Test function name
+ :param deps: List of dependencies
+ :return: Dispatch code.
+ """
+ if len(deps):
+ ifdef = gen_deps_one_line(deps)
+ dispatch_code = '''
+{ifdef}
+ {name}_wrapper,
+#else
+ NULL,
+#endif
+'''.format(ifdef=ifdef, name=name)
+ else:
+ dispatch_code = '''
+ {name}_wrapper,
+'''.format(name=name)
+
+ return dispatch_code
+
+
+def parse_until_pattern(funcs_f, end_regex):
+ """
+ Parses function headers or helper code until end pattern.
+
+ :param funcs_f: file object for .functions file
+ :param end_regex: Pattern to stop parsing
+ :return: Test suite headers code
+ """
+ headers = '#line %d "%s"\n' % (funcs_f.line_no + 1, funcs_f.name)
+ for line in funcs_f:
+ if re.search(end_regex, line):
+ break
+ headers += line
+ else:
+ raise InvalidFileFormat("file: %s - end pattern [%s] not found!" % (funcs_f.name, end_regex))
+
+ return headers
+
+
+def parse_suite_deps(funcs_f):
+ """
+ Parses test suite dependencies.
+
+ :param funcs_f: file object for .functions file
+ :return: List of test suite dependencies.
+ """
+ deps = []
+ for line in funcs_f:
+ m = re.search('depends_on\:(.*)', line.strip())
+ if m:
+ deps += [x.strip() for x in m.group(1).split(':')]
+ if re.search(END_DEP_REGEX, line):
+ break
+ else:
+ raise InvalidFileFormat("file: %s - end dependency pattern [%s] not found!" % (funcs_f.name, END_DEP_REGEX))
+
+ return deps
+
+
+def parse_function_deps(line):
+ """
+ Parses function dependencies.
+
+ :param line: Line from .functions file that has dependencies.
+ :return: List of dependencies.
+ """
+ deps = []
+ m = re.search(BEGIN_CASE_REGEX, line)
+ dep_str = m.group(1)
+ if len(dep_str):
+ m = re.search('depends_on:(.*)', dep_str)
+ if m:
+ deps = [x.strip() for x in m.group(1).strip().split(':')]
+ return deps
+
+
+def parse_function_signature(line):
+ """
+ Parsing function signature
+
+ :param line: Line from .functions file that has a function signature.
+ :return: function name, argument list, local variables for wrapper function and argument dispatch code.
+ """
+ args = []
+ locals = ''
+ args_dispatch = []
+ m = re.search('\s*void\s+(\w+)\s*\(', line, re.I)
+ if not m:
+ raise ValueError("Test function should return 'void'\n%s" % line)
+ name = m.group(1)
+ line = line[len(m.group(0)):]
+ arg_idx = 0
+ for arg in line[:line.find(')')].split(','):
+ arg = arg.strip()
+ if arg == '':
+ continue
+ if re.search('int\s+.*', arg.strip()):
+ args.append('int')
+ args_dispatch.append('*( (int *) params[%d] )' % arg_idx)
+ elif re.search('char\s*\*\s*.*', arg.strip()):
+ args.append('char*')
+ args_dispatch.append('(char *) params[%d]' % arg_idx)
+ elif re.search('HexParam_t\s*\*\s*.*', arg.strip()):
+ args.append('hex')
+ # create a structure
+ locals += """ HexParam_t hex%d = {%s, %s};
+""" % (arg_idx, '(uint8_t *) params[%d]' % arg_idx, '*( (uint32_t *) params[%d] )' % (arg_idx + 1))
+
+ args_dispatch.append('&hex%d' % arg_idx)
+ arg_idx += 1
+ else:
+ raise ValueError("Test function arguments can only be 'int', 'char *' or 'HexParam_t'\n%s" % line)
+ arg_idx += 1
+
+ return name, args, locals, args_dispatch
+
+
+def parse_function_code(funcs_f, deps, suite_deps):
+ """
+ Parses out a function from function file object and generates function and dispatch code.
+
+ :param funcs_f: file object of the functions file.
+ :param deps: List of dependencies
+ :param suite_deps: List of test suite dependencies
+ :return: Function name, arguments, function code and dispatch code.
+ """
+ code = '#line %d "%s"\n' % (funcs_f.line_no + 1, funcs_f.name)
+ for line in funcs_f:
+ # Check function signature
+ m = re.match('.*?\s+(\w+)\s*\(', line, re.I)
+ if m:
+ # check if we have full signature i.e. split in more lines
+ if not re.match('.*\)', line):
+ for lin in funcs_f:
+ line += lin
+ if re.search('.*?\)', line):
+ break
+ name, args, locals, args_dispatch = parse_function_signature(line)
+ code += line.replace(name, 'test_' + name)
+ name = 'test_' + name
+ break
+ else:
+ raise InvalidFileFormat("file: %s - Test functions not found!" % funcs_f.name)
+
+ for line in funcs_f:
+ if re.search(END_CASE_REGEX, line):
+ break
+ code += line
+ else:
+ raise InvalidFileFormat("file: %s - end case pattern [%s] not found!" % (funcs_f.name, END_CASE_REGEX))
+
+ # Add exit label if not present
+ if code.find('exit:') == -1:
+ s = code.rsplit('}', 1)
+ if len(s) == 2:
+ code = """exit:
+ ;;
+}""".join(s)
+
+ code += gen_function_wrapper(name, locals, args_dispatch)
+ ifdef, endif = gen_deps(deps)
+ dispatch_code = gen_dispatch(name, suite_deps + deps)
+ return name, args, ifdef + code + endif, dispatch_code
+
+
+def parse_functions(funcs_f):
+ """
+ Returns functions code pieces
+
+ :param funcs_f: file object of the functions file.
+ :return: List of test suite dependencies, test function dispatch code, function code and
+ a dict with function identifiers and arguments info.
+ """
+ suite_headers = ''
+ suite_helpers = ''
+ suite_deps = []
+ suite_functions = ''
+ func_info = {}
+ function_idx = 0
+ dispatch_code = ''
+ for line in funcs_f:
+ if re.search(BEGIN_HEADER_REGEX, line):
+ headers = parse_until_pattern(funcs_f, END_HEADER_REGEX)
+ suite_headers += headers
+ elif re.search(BEGIN_SUITE_HELPERS_REGEX, line):
+ helpers = parse_until_pattern(funcs_f, END_SUITE_HELPERS_REGEX)
+ suite_helpers += helpers
+ elif re.search(BEGIN_DEP_REGEX, line):
+ deps = parse_suite_deps(funcs_f)
+ suite_deps += deps
+ elif re.search(BEGIN_CASE_REGEX, line):
+ deps = parse_function_deps(line)
+ func_name, args, func_code, func_dispatch = parse_function_code(funcs_f, deps, suite_deps)
+ suite_functions += func_code
+ # Generate dispatch code and enumeration info
+ assert func_name not in func_info, "file: %s - function %s re-declared at line %d" % \
+ (funcs_f.name, func_name, funcs_f.line_no)
+ func_info[func_name] = (function_idx, args)
+ dispatch_code += '/* Function Id: %d */\n' % function_idx
+ dispatch_code += func_dispatch
+ function_idx += 1
+
+ ifdef, endif = gen_deps(suite_deps)
+ func_code = ifdef + suite_headers + suite_helpers + suite_functions + endif
+ return suite_deps, dispatch_code, func_code, func_info
+
+
+def escaped_split(str, ch):
+ """
+ Split str on character ch but ignore escaped \{ch}
+ Since return value is used to write back to the intermediate data file.
+ Any escape characters in the input are retained in the output.
+
+ :param str: String to split
+ :param ch: split character
+ :return: List of splits
+ """
+ if len(ch) > 1:
+ raise ValueError('Expected split character. Found string!')
+ out = []
+ part = ''
+ escape = False
+ for i in range(len(str)):
+ if not escape and str[i] == ch:
+ out.append(part)
+ part = ''
+ else:
+ part += str[i]
+ escape = not escape and str[i] == '\\'
+ if len(part):
+ out.append(part)
+ return out
+
+
+def parse_test_data(data_f, debug=False):
+ """
+ Parses .data file
+
+ :param data_f: file object of the data file.
+ :return: Generator that yields test name, function name, dependency list and function argument list.
+ """
+ STATE_READ_NAME = 0
+ STATE_READ_ARGS = 1
+ state = STATE_READ_NAME
+ deps = []
+ name = ''
+ for line in data_f:
+ line = line.strip()
+ if len(line) and line[0] == '#': # Skip comments
+ continue
+
+ # Blank line indicates end of test
+ if len(line) == 0:
+ assert state != STATE_READ_ARGS, "Newline before arguments. " \
+ "Test function and arguments missing for %s" % name
+ continue
+
+ if state == STATE_READ_NAME:
+ # Read test name
+ name = line
+ state = STATE_READ_ARGS
+ elif state == STATE_READ_ARGS:
+ # Check dependencies
+ m = re.search('depends_on\:(.*)', line)
+ if m:
+ deps = [x.strip() for x in m.group(1).split(':') if len(x.strip())]
+ else:
+ # Read test vectors
+ parts = escaped_split(line, ':')
+ function = parts[0]
+ args = parts[1:]
+ yield name, function, deps, args
+ deps = []
+ state = STATE_READ_NAME
+ assert state != STATE_READ_ARGS, "Newline before arguments. " \
+ "Test function and arguments missing for %s" % name
+
+
+def gen_dep_check(dep_id, dep):
+ """
+ Generate code for the dependency.
+
+ :param dep_id: Dependency identifier
+ :param dep: Dependency macro
+ :return: Dependency check code
+ """
+ assert dep_id > -1, "Dependency Id should be a positive integer."
+ noT, dep = ('!', dep[1:]) if dep[0] == '!' else ('', dep)
+ assert len(dep) > 0, "Dependency should not be an empty string."
+ dep_check = '''
+ case {id}:
+ {{
+#if {noT}defined({macro})
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }}
+ break;'''.format(noT=noT, macro=dep, id=dep_id)
+ return dep_check
+
+
+def gen_expression_check(exp_id, exp):
+ """
+ Generates code for expression check
+
+ :param exp_id: Expression Identifier
+ :param exp: Expression/Macro
+ :return: Expression check code
+ """
+ assert exp_id > -1, "Expression Id should be a positive integer."
+ assert len(exp) > 0, "Expression should not be an empty string."
+ exp_code = '''
+ case {exp_id}:
+ {{
+ *out_value = {expression};
+ }}
+ break;'''.format(exp_id=exp_id, expression=exp)
+ return exp_code
+
+
+def write_deps(out_data_f, test_deps, unique_deps):
+ """
+ Write dependencies to intermediate test data file.
+ It also returns dependency check code.
+
+ :param out_data_f: Output intermediate data file
+ :param test_deps: Dependencies
+ :param unique_deps: Mutable list to track unique dependencies that are global to this re-entrant function.
+ :return: returns dependency check code.
+ """
+ dep_check_code = ''
+ if len(test_deps):
+ out_data_f.write('depends_on')
+ for dep in test_deps:
+ if dep not in unique_deps:
+ unique_deps.append(dep)
+ dep_id = unique_deps.index(dep)
+ dep_check_code += gen_dep_check(dep_id, dep)
+ else:
+ dep_id = unique_deps.index(dep)
+ out_data_f.write(':' + str(dep_id))
+ out_data_f.write('\n')
+ return dep_check_code
+
+
+def write_parameters(out_data_f, test_args, func_args, unique_expressions):
+ """
+ Writes test parameters to the intermediate data file.
+ Also generates expression code.
+
+ :param out_data_f: Output intermediate data file
+ :param test_args: Test parameters
+ :param func_args: Function arguments
+ :param unique_expressions: Mutable list to track unique expressions that are global to this re-entrant function.
+ :return: Returns expression check code.
+ """
+ expression_code = ''
+ for i in range(len(test_args)):
+ typ = func_args[i]
+ val = test_args[i]
+
+ # check if val is a non literal int val
+ if typ == 'int' and not re.match('(\d+$)|((0x)?[0-9a-fA-F]+$)', val): # its an expression
+ typ = 'exp'
+ if val not in unique_expressions:
+ unique_expressions.append(val)
+ # exp_id can be derived from len(). But for readability and consistency with case of existing let's
+ # use index().
+ exp_id = unique_expressions.index(val)
+ expression_code += gen_expression_check(exp_id, val)
+ val = exp_id
+ else:
+ val = unique_expressions.index(val)
+ out_data_f.write(':' + typ + ':' + str(val))
+ out_data_f.write('\n')
+ return expression_code
+
+
+def gen_suite_deps_checks(suite_deps, dep_check_code, expression_code):
+ """
+ Adds preprocessor checks for test suite dependencies.
+
+ :param suite_deps: Test suite dependencies read from the .functions file.
+ :param dep_check_code: Dependency check code
+ :param expression_code: Expression check code
+ :return: Dependency and expression code guarded by test suite dependencies.
+ """
+ if len(suite_deps):
+ ifdef = gen_deps_one_line(suite_deps)
+ dep_check_code = '''
+{ifdef}
+{code}
+#endif
+'''.format(ifdef=ifdef, code=dep_check_code)
+ expression_code = '''
+{ifdef}
+{code}
+#endif
+'''.format(ifdef=ifdef, code=expression_code)
+ return dep_check_code, expression_code
+
+
+def gen_from_test_data(data_f, out_data_f, func_info, suite_deps):
+ """
+ Generates dependency checks, expression code and intermediate data file from test data file.
+
+ :param data_f: Data file object
+ :param out_data_f:Output intermediate data file
+ :param func_info: Dict keyed by function and with function id and arguments info
+ :param suite_deps: Test suite deps
+ :return: Returns dependency and expression check code
+ """
+ unique_deps = []
+ unique_expressions = []
+ dep_check_code = ''
+ expression_code = ''
+ for test_name, function_name, test_deps, test_args in parse_test_data(data_f):
+ out_data_f.write(test_name + '\n')
+
+ # Write deps
+ dep_check_code += write_deps(out_data_f, test_deps, unique_deps)
+
+ # Write test function name
+ test_function_name = 'test_' + function_name
+ assert test_function_name in func_info, "Function %s not found!" % test_function_name
+ func_id, func_args = func_info[test_function_name]
+ out_data_f.write(str(func_id))
+
+ # Write parameters
+ assert len(test_args) == len(func_args), \
+ "Invalid number of arguments in test %s. See function %s signature." % (test_name, function_name)
+ expression_code += write_parameters(out_data_f, test_args, func_args, unique_expressions)
+
+ # Write a newline as test case separator
+ out_data_f.write('\n')
+
+ dep_check_code, expression_code = gen_suite_deps_checks(suite_deps, dep_check_code, expression_code)
+ return dep_check_code, expression_code
+
+
+def generate_code(funcs_file, data_file, template_file, platform_file, help_file, suites_dir, c_file, out_data_file):
+ """
+ Generate mbed-os test code.
+
+ :param funcs_file: Functions file object
+ :param data_file: Data file object
+ :param template_file: Template file object
+ :param platform_file: Platform file object
+ :param help_file: Helper functions file object
+ :param suites_dir: Test suites dir
+ :param c_file: Output C file object
+ :param out_data_file: Output intermediate data file object
+ :return:
+ """
+ for name, path in [('Functions file', funcs_file),
+ ('Data file', data_file),
+ ('Template file', template_file),
+ ('Platform file', platform_file),
+ ('Help code file', help_file),
+ ('Suites dir', suites_dir)]:
+ if not os.path.exists(path):
+ raise IOError("ERROR: %s [%s] not found!" % (name, path))
+
+ snippets = {'generator_script' : os.path.basename(__file__)}
+
+ # Read helpers
+ with open(help_file, 'r') as help_f, open(platform_file, 'r') as platform_f:
+ snippets['test_common_helper_file'] = help_file
+ snippets['test_common_helpers'] = help_f.read()
+ snippets['test_platform_file'] = platform_file
+ snippets['platform_code'] = platform_f.read().replace('DATA_FILE',
+ out_data_file.replace('\\', '\\\\')) # escape '\'
+
+ # Function code
+ with FileWrapper(funcs_file) as funcs_f, open(data_file, 'r') as data_f, open(out_data_file, 'w') as out_data_f:
+ suite_deps, dispatch_code, func_code, func_info = parse_functions(funcs_f)
+ snippets['functions_code'] = func_code
+ snippets['dispatch_code'] = dispatch_code
+ dep_check_code, expression_code = gen_from_test_data(data_f, out_data_f, func_info, suite_deps)
+ snippets['dep_check_code'] = dep_check_code
+ snippets['expression_code'] = expression_code
+
+ snippets['test_file'] = c_file
+ snippets['test_main_file'] = template_file
+ snippets['test_case_file'] = funcs_file
+ snippets['test_case_data_file'] = data_file
+ # Read Template
+ # Add functions
+ #
+ with open(template_file, 'r') as template_f, open(c_file, 'w') as c_f:
+ line_no = 1
+ for line in template_f.readlines():
+ snippets['line_no'] = line_no + 1 # Increment as it sets next line number
+ code = line.format(**snippets)
+ c_f.write(code)
+ line_no += 1
+
+
+def check_cmd():
+ """
+ Command line parser.
+
+ :return:
+ """
+ parser = argparse.ArgumentParser(description='Generate code for mbed-os tests.')
+
+ parser.add_argument("-f", "--functions-file",
+ dest="funcs_file",
+ help="Functions file",
+ metavar="FUNCTIONS",
+ required=True)
+
+ parser.add_argument("-d", "--data-file",
+ dest="data_file",
+ help="Data file",
+ metavar="DATA",
+ required=True)
+
+ parser.add_argument("-t", "--template-file",
+ dest="template_file",
+ help="Template file",
+ metavar="TEMPLATE",
+ required=True)
+
+ parser.add_argument("-s", "--suites-dir",
+ dest="suites_dir",
+ help="Suites dir",
+ metavar="SUITES",
+ required=True)
+
+ parser.add_argument("--help-file",
+ dest="help_file",
+ help="Help file",
+ metavar="HELPER",
+ required=True)
+
+ parser.add_argument("-p", "--platform-file",
+ dest="platform_file",
+ help="Platform code file",
+ metavar="PLATFORM_FILE",
+ required=True)
+
+ parser.add_argument("-o", "--out-dir",
+ dest="out_dir",
+ help="Dir where generated code and scripts are copied",
+ metavar="OUT_DIR",
+ required=True)
+
+ args = parser.parse_args()
+
+ data_file_name = os.path.basename(args.data_file)
+ data_name = os.path.splitext(data_file_name)[0]
+
+ out_c_file = os.path.join(args.out_dir, data_name + '.c')
+ out_data_file = os.path.join(args.out_dir, data_file_name)
+
+ out_c_file_dir = os.path.dirname(out_c_file)
+ out_data_file_dir = os.path.dirname(out_data_file)
+ for d in [out_c_file_dir, out_data_file_dir]:
+ if not os.path.exists(d):
+ os.makedirs(d)
+
+ generate_code(args.funcs_file, args.data_file, args.template_file, args.platform_file,
+ args.help_file, args.suites_dir, out_c_file, out_data_file)
+
+
+if __name__ == "__main__":
+ check_cmd()
diff --git a/tests/scripts/mbedtls_test.py b/tests/scripts/mbedtls_test.py
new file mode 100755
index 0000000..cdd7524
--- /dev/null
+++ b/tests/scripts/mbedtls_test.py
@@ -0,0 +1,342 @@
+# Greentea host test script for on-target tests.
+#
+# Copyright (C) 2018, ARM Limited, All Rights Reserved
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# This file is part of Mbed Crypto (https://tls.mbed.org)
+
+
+"""
+Greentea host test script for on-target tests.
+
+Host test script for testing Mbed Crypto test suites on target. Implements
+BaseHostTest to handle key,value pairs (events) coming from Mbed Crypto
+tests. Reads data file corresponding to the executing binary and dispatches
+test cases.
+"""
+
+
+import re
+import os
+import binascii
+from mbed_host_tests import BaseHostTest, event_callback
+
+
+class TestDataParser(object):
+ """
+ parser for mbedcrypto test data files.
+ """
+
+ def __init__(self):
+ """
+ Constructor
+ """
+ self.tests = []
+
+ def parse(self, data_file):
+ """
+ Data file parser.
+
+ :param data_file: Data file path
+ """
+ with open(data_file, 'r') as f:
+ self.__parse(f)
+
+ @staticmethod
+ def __escaped_split(str, ch):
+ """
+ Splits str on ch except when escaped.
+
+ :param str: String to split
+ :param ch: Split character
+ :return: List of splits
+ """
+ if len(ch) > 1:
+ raise ValueError('Expected split character. Found string!')
+ out = []
+ part = ''
+ escape = False
+ for i in range(len(str)):
+ if not escape and str[i] == ch:
+ out.append(part)
+ part = ''
+ else:
+ part += str[i]
+ escape = not escape and str[i] == '\\'
+ if len(part):
+ out.append(part)
+ return out
+
+ def __parse(self, file):
+ """
+ Parses data file using supplied file object.
+
+ :param file: Data file object
+ :return:
+ """
+ for line in file:
+ line = line.strip()
+ if len(line) == 0:
+ continue
+ # Read test name
+ name = line
+
+ # Check dependencies
+ deps = []
+ line = file.next().strip()
+ m = re.search('depends_on\:(.*)', line)
+ if m:
+ deps = [int(x) for x in m.group(1).split(':')]
+ line = file.next().strip()
+
+ # Read test vectors
+ line = line.replace('\\n', '\n')
+ parts = self.__escaped_split(line, ':')
+ function = int(parts[0])
+ x = parts[1:]
+ l = len(x)
+ assert l % 2 == 0, "Number of test arguments should be even: %s" % line
+ args = [(x[i * 2], x[(i * 2) + 1]) for i in range(len(x)/2)]
+ self.tests.append((name, function, deps, args))
+
+ def get_test_data(self):
+ """
+ Returns test data.
+ """
+ return self.tests
+
+
+class MbedCryptoTest(BaseHostTest):
+ """
+ Event handler for mbedcrypto unit tests. This script is loaded at run time
+ by htrun while executing mbedcrypto unit tests.
+ """
+ # From suites/helpers.function
+ DEPENDENCY_SUPPORTED = 0
+ KEY_VALUE_MAPPING_FOUND = DEPENDENCY_SUPPORTED
+ DISPATCH_TEST_SUCCESS = DEPENDENCY_SUPPORTED
+
+ KEY_VALUE_MAPPING_NOT_FOUND = -1
+ DEPENDENCY_NOT_SUPPORTED = -2
+ DISPATCH_TEST_FN_NOT_FOUND = -3
+ DISPATCH_INVALID_TEST_DATA = -4
+ DISPATCH_UNSUPPORTED_SUITE = -5
+
+ def __init__(self):
+ """
+ Constructor initialises test index to 0.
+ """
+ super(MbedCryptoTest, self).__init__()
+ self.tests = []
+ self.test_index = -1
+ self.dep_index = 0
+ self.error_str = dict()
+ self.error_str[self.DEPENDENCY_SUPPORTED] = 'DEPENDENCY_SUPPORTED'
+ self.error_str[self.KEY_VALUE_MAPPING_NOT_FOUND] = 'KEY_VALUE_MAPPING_NOT_FOUND'
+ self.error_str[self.DEPENDENCY_NOT_SUPPORTED] = 'DEPENDENCY_NOT_SUPPORTED'
+ self.error_str[self.DISPATCH_TEST_FN_NOT_FOUND] = 'DISPATCH_TEST_FN_NOT_FOUND'
+ self.error_str[self.DISPATCH_INVALID_TEST_DATA] = 'DISPATCH_INVALID_TEST_DATA'
+ self.error_str[self.DISPATCH_UNSUPPORTED_SUITE] = 'DISPATCH_UNSUPPORTED_SUITE'
+
+ def setup(self):
+ """
+ Setup hook implementation. Reads test suite data file and parses out tests.
+ """
+ binary_path = self.get_config_item('image_path')
+ script_dir = os.path.split(os.path.abspath(__file__))[0]
+ suite_name = os.path.splitext(os.path.basename(binary_path))[0]
+ data_file = ".".join((suite_name, 'data'))
+ data_file = os.path.join(script_dir, '..', 'mbedcrypto', suite_name, data_file)
+ if os.path.exists(data_file):
+ self.log("Running tests from %s" % data_file)
+ parser = TestDataParser()
+ parser.parse(data_file)
+ self.tests = parser.get_test_data()
+ self.print_test_info()
+ else:
+ self.log("Data file not found: %s" % data_file)
+ self.notify_complete(False)
+
+ def print_test_info(self):
+ """
+ Prints test summary read by Greentea to detect test cases.
+ """
+ self.log('{{__testcase_count;%d}}' % len(self.tests))
+ for name, _, _, _ in self.tests:
+ self.log('{{__testcase_name;%s}}' % name)
+
+ @staticmethod
+ def align_32bit(b):
+ """
+ 4 byte aligns input byte array.
+
+ :return:
+ """
+ b += bytearray((4 - (len(b))) % 4)
+
+ @staticmethod
+ def hex_str_bytes(hex_str):
+ """
+ Converts Hex string representation to byte array
+
+ :param hex_str: Hex in string format.
+ :return: Output Byte array
+ """
+ assert hex_str[0] == '"' and hex_str[len(hex_str) - 1] == '"', \
+ "HEX test parameter missing '\"': %s" % hex_str
+ hex_str = hex_str.strip('"')
+ assert len(hex_str) % 2 == 0, "HEX parameter len should be mod of 2: %s" % hex_str
+
+ b = binascii.unhexlify(hex_str)
+ return b
+
+ @staticmethod
+ def int32_to_bigendian_bytes(i):
+ """
+ Coverts i to bytearray in big endian format.
+
+ :param i: Input integer
+ :return: Output bytes array in big endian or network order
+ """
+ b = bytearray([((i >> x) & 0xff) for x in [24, 16, 8, 0]])
+ return b
+
+ def test_vector_to_bytes(self, function_id, deps, parameters):
+ """
+ Converts test vector into a byte array that can be sent to the target.
+
+ :param function_id: Test Function Identifier
+ :param deps: Dependency list
+ :param parameters: Test function input parameters
+ :return: Byte array and its length
+ """
+ b = bytearray([len(deps)])
+ if len(deps):
+ b += bytearray(deps)
+ b += bytearray([function_id, len(parameters)])
+ for typ, param in parameters:
+ if typ == 'int' or typ == 'exp':
+ i = int(param)
+ b += 'I' if typ == 'int' else 'E'
+ self.align_32bit(b)
+ b += self.int32_to_bigendian_bytes(i)
+ elif typ == 'char*':
+ param = param.strip('"')
+ i = len(param) + 1 # + 1 for null termination
+ b += 'S'
+ self.align_32bit(b)
+ b += self.int32_to_bigendian_bytes(i)
+ b += bytearray(list(param))
+ b += '\0' # Null terminate
+ elif typ == 'hex':
+ hb = self.hex_str_bytes(param)
+ b += 'H'
+ self.align_32bit(b)
+ i = len(hb)
+ b += self.int32_to_bigendian_bytes(i)
+ b += hb
+ length = self.int32_to_bigendian_bytes(len(b))
+ return b, length
+
+ def run_next_test(self):
+ """
+ Send next test function to the target.
+
+ """
+ self.test_index += 1
+ self.dep_index = 0
+ if self.test_index < len(self.tests):
+ name, function_id, deps, args = self.tests[self.test_index]
+ self.run_test(name, function_id, deps, args)
+ else:
+ self.notify_complete(True)
+
+ def run_test(self, name, function_id, deps, args):
+ """
+ Runs the test.
+
+ :param name: Test name
+ :param function_id: function identifier
+ :param deps: Dependencies list
+ :param args: test parameters
+ :return:
+ """
+ self.log("Running: %s" % name)
+
+ bytes, length = self.test_vector_to_bytes(function_id, deps, args)
+ self.send_kv(length, bytes)
+
+ @staticmethod
+ def get_result(value):
+ """
+ Converts result from string type to integer
+ :param value: Result code in string
+ :return: Integer result code
+ """
+ try:
+ return int(value)
+ except ValueError:
+ ValueError("Result should return error number. Instead received %s" % value)
+ return 0
+
+ @event_callback('GO')
+ def on_go(self, key, value, timestamp):
+ """
+ Called on key "GO". Kicks off test execution.
+
+ :param key: Event key
+ :param value: Value. ignored
+ :param timestamp: Timestamp ignored.
+ :return:
+ """
+ self.run_next_test()
+
+ @event_callback("R")
+ def on_result(self, key, value, timestamp):
+ """
+ Handle result. Prints test start, finish prints required by Greentea to detect test execution.
+
+ :param key: Event key
+ :param value: Value. ignored
+ :param timestamp: Timestamp ignored.
+ :return:
+ """
+ int_val = self.get_result(value)
+ name, function, deps, args = self.tests[self.test_index]
+ self.log('{{__testcase_start;%s}}' % name)
+ self.log('{{__testcase_finish;%s;%d;%d}}' % (name, int_val == 0,
+ int_val != 0))
+ self.run_next_test()
+
+ @event_callback("F")
+ def on_failure(self, key, value, timestamp):
+ """
+ Handles test execution failure. That means dependency not supported or
+ Test function not supported. Hence marking test as skipped.
+
+ :param key: Event key
+ :param value: Value. ignored
+ :param timestamp: Timestamp ignored.
+ :return:
+ """
+ int_val = self.get_result(value)
+ name, function, deps, args = self.tests[self.test_index]
+ if int_val in self.error_str:
+ err = self.error_str[int_val]
+ else:
+ err = 'Unknown error'
+ # For skip status, do not write {{__testcase_finish;...}}
+ self.log("Error: %s" % err)
+ self.run_next_test()
diff --git a/tests/scripts/run-test-suites.pl b/tests/scripts/run-test-suites.pl
new file mode 100755
index 0000000..5de20f8
--- /dev/null
+++ b/tests/scripts/run-test-suites.pl
@@ -0,0 +1,101 @@
+#!/usr/bin/perl
+
+# run-test-suites.pl
+#
+# This file is part of Mbed Crypto (https://tls.mbed.org)
+#
+# Copyright (c) 2015-2016, ARM Limited, All Rights Reserved
+#
+# Purpose
+#
+# Executes all the available test suites, and provides a basic summary of the
+# results.
+#
+# Usage: run-test-suites.pl [-v]
+#
+# Options :
+# -v|--verbose - Provide a pass/fail/skip breakdown per test suite and
+# in total
+#
+
+use warnings;
+use strict;
+
+use utf8;
+use open qw(:std utf8);
+
+use constant FALSE => 0;
+use constant TRUE => 1;
+
+my $verbose;
+my $switch = shift;
+if ( defined($switch) && ( $switch eq "-v" || $switch eq "--verbose" ) ) {
+ $verbose = TRUE;
+}
+
+# All test suites = executable files, excluding source files, debug
+# and profiling information, etc. We can't just grep {! /\./} because
+#some of our test cases' base names contain a dot.
+my @suites = grep { -x $_ || /\.exe$/ } glob 'test_suite_*';
+die "$0: no test suite found\n" unless @suites;
+
+# in case test suites are linked dynamically
+$ENV{'LD_LIBRARY_PATH'} = '../library';
+$ENV{'DYLD_LIBRARY_PATH'} = '../library';
+
+my $prefix = $^O eq "MSWin32" ? '' : './';
+
+my ($failed_suites, $total_tests_run, $failed, $suite_cases_passed,
+ $suite_cases_failed, $suite_cases_skipped, $total_cases_passed,
+ $total_cases_failed, $total_cases_skipped );
+
+for my $suite (@suites)
+{
+ print "$suite ", "." x ( 72 - length($suite) - 2 - 4 ), " ";
+ my $result = `$prefix$suite`;
+
+ $suite_cases_passed = () = $result =~ /.. PASS/g;
+ $suite_cases_failed = () = $result =~ /.. FAILED/g;
+ $suite_cases_skipped = () = $result =~ /.. ----/g;
+
+ if( $result =~ /PASSED/ ) {
+ print "PASS\n";
+ } else {
+ $failed_suites++;
+ print "FAIL\n";
+ }
+
+ my ($passed, $tests, $skipped) = $result =~ /([0-9]*) \/ ([0-9]*) tests.*?([0-9]*) skipped/;
+ $total_tests_run += $tests - $skipped;
+
+ if ( $verbose ) {
+ print "(test cases passed:", $suite_cases_passed,
+ " failed:", $suite_cases_failed,
+ " skipped:", $suite_cases_skipped,
+ " of total:", ($suite_cases_passed + $suite_cases_failed +
+ $suite_cases_skipped),
+ ")\n"
+ }
+
+ $total_cases_passed += $suite_cases_passed;
+ $total_cases_failed += $suite_cases_failed;
+ $total_cases_skipped += $suite_cases_skipped;
+}
+
+print "-" x 72, "\n";
+print $failed_suites ? "FAILED" : "PASSED";
+printf " (%d suites, %d tests run)\n", scalar @suites, $total_tests_run;
+
+if ( $verbose ) {
+ print " test cases passed :", $total_cases_passed, "\n";
+ print " failed :", $total_cases_failed, "\n";
+ print " skipped :", $total_cases_skipped, "\n";
+ print " of tests executed :", ( $total_cases_passed + $total_cases_failed ),
+ "\n";
+ print " of available tests :",
+ ( $total_cases_passed + $total_cases_failed + $total_cases_skipped ),
+ "\n"
+ }
+
+exit( $failed_suites ? 1 : 0 );
+
diff --git a/tests/scripts/test_generate_test_code.py b/tests/scripts/test_generate_test_code.py
new file mode 100755
index 0000000..9adb441
--- /dev/null
+++ b/tests/scripts/test_generate_test_code.py
@@ -0,0 +1,1524 @@
+# Unit test for generate_test_code.py
+#
+# Copyright (C) 2018, ARM Limited, All Rights Reserved
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# This file is part of Mbed Crypto (https://tls.mbed.org)
+
+from StringIO import StringIO
+from unittest import TestCase, main as unittest_main
+from mock import patch
+from generate_test_code import *
+
+
+"""
+Unit tests for generate_test_code.py
+"""
+
+
+class GenDep(TestCase):
+ """
+ Test suite for function gen_dep()
+ """
+
+ def test_deps_list(self):
+ """
+ Test that gen_dep() correctly creates deps for given dependency list.
+ :return:
+ """
+ deps = ['DEP1', 'DEP2']
+ dep_start, dep_end = gen_deps(deps)
+ ifdef1, ifdef2 = dep_start.splitlines()
+ endif1, endif2 = dep_end.splitlines()
+ self.assertEqual(ifdef1, '#if defined(DEP1)', 'ifdef generated incorrectly')
+ self.assertEqual(ifdef2, '#if defined(DEP2)', 'ifdef generated incorrectly')
+ self.assertEqual(endif1, '#endif /* DEP2 */', 'endif generated incorrectly')
+ self.assertEqual(endif2, '#endif /* DEP1 */', 'endif generated incorrectly')
+
+ def test_disabled_deps_list(self):
+ """
+ Test that gen_dep() correctly creates deps for given dependency list.
+ :return:
+ """
+ deps = ['!DEP1', '!DEP2']
+ dep_start, dep_end = gen_deps(deps)
+ ifdef1, ifdef2 = dep_start.splitlines()
+ endif1, endif2 = dep_end.splitlines()
+ self.assertEqual(ifdef1, '#if !defined(DEP1)', 'ifdef generated incorrectly')
+ self.assertEqual(ifdef2, '#if !defined(DEP2)', 'ifdef generated incorrectly')
+ self.assertEqual(endif1, '#endif /* !DEP2 */', 'endif generated incorrectly')
+ self.assertEqual(endif2, '#endif /* !DEP1 */', 'endif generated incorrectly')
+
+ def test_mixed_deps_list(self):
+ """
+ Test that gen_dep() correctly creates deps for given dependency list.
+ :return:
+ """
+ deps = ['!DEP1', 'DEP2']
+ dep_start, dep_end = gen_deps(deps)
+ ifdef1, ifdef2 = dep_start.splitlines()
+ endif1, endif2 = dep_end.splitlines()
+ self.assertEqual(ifdef1, '#if !defined(DEP1)', 'ifdef generated incorrectly')
+ self.assertEqual(ifdef2, '#if defined(DEP2)', 'ifdef generated incorrectly')
+ self.assertEqual(endif1, '#endif /* DEP2 */', 'endif generated incorrectly')
+ self.assertEqual(endif2, '#endif /* !DEP1 */', 'endif generated incorrectly')
+
+ def test_empty_deps_list(self):
+ """
+ Test that gen_dep() correctly creates deps for given dependency list.
+ :return:
+ """
+ deps = []
+ dep_start, dep_end = gen_deps(deps)
+ self.assertEqual(dep_start, '', 'ifdef generated incorrectly')
+ self.assertEqual(dep_end, '', 'ifdef generated incorrectly')
+
+ def test_large_deps_list(self):
+ """
+ Test that gen_dep() correctly creates deps for given dependency list.
+ :return:
+ """
+ deps = []
+ count = 10
+ for i in range(count):
+ deps.append('DEP%d' % i)
+ dep_start, dep_end = gen_deps(deps)
+ self.assertEqual(len(dep_start.splitlines()), count, 'ifdef generated incorrectly')
+ self.assertEqual(len(dep_end.splitlines()), count, 'ifdef generated incorrectly')
+
+
+class GenDepOneLine(TestCase):
+ """
+ Test Suite for testing gen_deps_one_line()
+ """
+
+ def test_deps_list(self):
+ """
+ Test that gen_dep() correctly creates deps for given dependency list.
+ :return:
+ """
+ deps = ['DEP1', 'DEP2']
+ dep_str = gen_deps_one_line(deps)
+ self.assertEqual(dep_str, '#if defined(DEP1) && defined(DEP2)', 'ifdef generated incorrectly')
+
+ def test_disabled_deps_list(self):
+ """
+ Test that gen_dep() correctly creates deps for given dependency list.
+ :return:
+ """
+ deps = ['!DEP1', '!DEP2']
+ dep_str = gen_deps_one_line(deps)
+ self.assertEqual(dep_str, '#if !defined(DEP1) && !defined(DEP2)', 'ifdef generated incorrectly')
+
+ def test_mixed_deps_list(self):
+ """
+ Test that gen_dep() correctly creates deps for given dependency list.
+ :return:
+ """
+ deps = ['!DEP1', 'DEP2']
+ dep_str = gen_deps_one_line(deps)
+ self.assertEqual(dep_str, '#if !defined(DEP1) && defined(DEP2)', 'ifdef generated incorrectly')
+
+ def test_empty_deps_list(self):
+ """
+ Test that gen_dep() correctly creates deps for given dependency list.
+ :return:
+ """
+ deps = []
+ dep_str = gen_deps_one_line(deps)
+ self.assertEqual(dep_str, '', 'ifdef generated incorrectly')
+
+ def test_large_deps_list(self):
+ """
+ Test that gen_dep() correctly creates deps for given dependency list.
+ :return:
+ """
+ deps = []
+ count = 10
+ for i in range(count):
+ deps.append('DEP%d' % i)
+ dep_str = gen_deps_one_line(deps)
+ expected = '#if ' + ' && '.join(['defined(%s)' % x for x in deps])
+ self.assertEqual(dep_str, expected, 'ifdef generated incorrectly')
+
+
+class GenFunctionWrapper(TestCase):
+ """
+ Test Suite for testing gen_function_wrapper()
+ """
+
+ def test_params_unpack(self):
+ """
+ Test that params are properly unpacked in the function call.
+
+ :return:
+ """
+ code = gen_function_wrapper('test_a', '', ('a', 'b', 'c', 'd'))
+ expected = '''
+void test_a_wrapper( void ** params )
+{
+
+
+ test_a( a, b, c, d );
+}
+'''
+ self.assertEqual(code, expected)
+
+ def test_local(self):
+ """
+ Test that params are properly unpacked in the function call.
+
+ :return:
+ """
+ code = gen_function_wrapper('test_a', 'int x = 1;', ('x', 'b', 'c', 'd'))
+ expected = '''
+void test_a_wrapper( void ** params )
+{
+
+int x = 1;
+ test_a( x, b, c, d );
+}
+'''
+ self.assertEqual(code, expected)
+
+ def test_empty_params(self):
+ """
+ Test that params are properly unpacked in the function call.
+
+ :return:
+ """
+ code = gen_function_wrapper('test_a', '', ())
+ expected = '''
+void test_a_wrapper( void ** params )
+{
+ (void)params;
+
+ test_a( );
+}
+'''
+ self.assertEqual(code, expected)
+
+
+class GenDispatch(TestCase):
+ """
+ Test suite for testing gen_dispatch()
+ """
+
+ def test_dispatch(self):
+ """
+ Test that dispatch table entry is generated correctly.
+ :return:
+ """
+ code = gen_dispatch('test_a', ['DEP1', 'DEP2'])
+ expected = '''
+#if defined(DEP1) && defined(DEP2)
+ test_a_wrapper,
+#else
+ NULL,
+#endif
+'''
+ self.assertEqual(code, expected)
+
+ def test_empty_deps(self):
+ """
+ Test empty dependency list.
+ :return:
+ """
+ code = gen_dispatch('test_a', [])
+ expected = '''
+ test_a_wrapper,
+'''
+ self.assertEqual(code, expected)
+
+
+class StringIOWrapper(StringIO, object):
+ """
+ file like class to mock file object in tests.
+ """
+ def __init__(self, file_name, data, line_no = 1):
+ """
+ Init file handle.
+
+ :param file_name:
+ :param data:
+ :param line_no:
+ """
+ super(StringIOWrapper, self).__init__(data)
+ self.line_no = line_no
+ self.name = file_name
+
+ def next(self):
+ """
+ Iterator return impl.
+ :return:
+ """
+ line = super(StringIOWrapper, self).next()
+ return line
+
+ def readline(self, limit=0):
+ """
+ Wrap the base class readline.
+
+ :param limit:
+ :return:
+ """
+ line = super(StringIOWrapper, self).readline()
+ if line:
+ self.line_no += 1
+ return line
+
+
+class ParseUntilPattern(TestCase):
+ """
+ Test Suite for testing parse_until_pattern().
+ """
+
+ def test_suite_headers(self):
+ """
+ Test that suite headers are parsed correctly.
+
+ :return:
+ """
+ data = '''#include "mbedcrypto/ecp.h"
+
+#define ECP_PF_UNKNOWN -1
+/* END_HEADER */
+'''
+ expected = '''#line 1 "test_suite_ut.function"
+#include "mbedcrypto/ecp.h"
+
+#define ECP_PF_UNKNOWN -1
+'''
+ s = StringIOWrapper('test_suite_ut.function', data, line_no=0)
+ headers = parse_until_pattern(s, END_HEADER_REGEX)
+ self.assertEqual(headers, expected)
+
+ def test_line_no(self):
+ """
+ Test that #line is set to correct line no. in source .function file.
+
+ :return:
+ """
+ data = '''#include "mbedcrypto/ecp.h"
+
+#define ECP_PF_UNKNOWN -1
+/* END_HEADER */
+'''
+ offset_line_no = 5
+ expected = '''#line %d "test_suite_ut.function"
+#include "mbedcrypto/ecp.h"
+
+#define ECP_PF_UNKNOWN -1
+''' % (offset_line_no + 1)
+ s = StringIOWrapper('test_suite_ut.function', data, offset_line_no)
+ headers = parse_until_pattern(s, END_HEADER_REGEX)
+ self.assertEqual(headers, expected)
+
+ def test_no_end_header_comment(self):
+ """
+ Test that InvalidFileFormat is raised when end header comment is missing.
+ :return:
+ """
+ data = '''#include "mbedcrypto/ecp.h"
+
+#define ECP_PF_UNKNOWN -1
+
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ self.assertRaises(InvalidFileFormat, parse_until_pattern, s, END_HEADER_REGEX)
+
+
+class ParseSuiteDeps(TestCase):
+ """
+ Test Suite for testing parse_suite_deps().
+ """
+
+ def test_suite_deps(self):
+ """
+
+ :return:
+ """
+ data = '''
+ * depends_on:MBEDCRYPTO_ECP_C
+ * END_DEPENDENCIES
+ */
+'''
+ expected = ['MBEDCRYPTO_ECP_C']
+ s = StringIOWrapper('test_suite_ut.function', data)
+ deps = parse_suite_deps(s)
+ self.assertEqual(deps, expected)
+
+ def test_no_end_dep_comment(self):
+ """
+ Test that InvalidFileFormat is raised when end dep comment is missing.
+ :return:
+ """
+ data = '''
+* depends_on:MBEDCRYPTO_ECP_C
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ self.assertRaises(InvalidFileFormat, parse_suite_deps, s)
+
+ def test_deps_split(self):
+ """
+ Test that InvalidFileFormat is raised when end dep comment is missing.
+ :return:
+ """
+ data = '''
+ * depends_on:MBEDCRYPTO_ECP_C:A:B: C : D :F : G: !H
+ * END_DEPENDENCIES
+ */
+'''
+ expected = ['MBEDCRYPTO_ECP_C', 'A', 'B', 'C', 'D', 'F', 'G', '!H']
+ s = StringIOWrapper('test_suite_ut.function', data)
+ deps = parse_suite_deps(s)
+ self.assertEqual(deps, expected)
+
+
+class ParseFuncDeps(TestCase):
+ """
+ Test Suite for testing parse_function_deps()
+ """
+
+ def test_function_deps(self):
+ """
+ Test that parse_function_deps() correctly parses function dependencies.
+ :return:
+ """
+ line = '/* BEGIN_CASE depends_on:MBEDCRYPTO_ENTROPY_NV_SEED:MBEDCRYPTO_FS_IO */'
+ expected = ['MBEDCRYPTO_ENTROPY_NV_SEED', 'MBEDCRYPTO_FS_IO']
+ deps = parse_function_deps(line)
+ self.assertEqual(deps, expected)
+
+ def test_no_deps(self):
+ """
+ Test that parse_function_deps() correctly parses function dependencies.
+ :return:
+ """
+ line = '/* BEGIN_CASE */'
+ deps = parse_function_deps(line)
+ self.assertEqual(deps, [])
+
+ def test_poorly_defined_deps(self):
+ """
+ Test that parse_function_deps() correctly parses function dependencies.
+ :return:
+ """
+ line = '/* BEGIN_CASE depends_on:MBEDCRYPTO_FS_IO: A : !B:C : F*/'
+ deps = parse_function_deps(line)
+ self.assertEqual(deps, ['MBEDCRYPTO_FS_IO', 'A', '!B', 'C', 'F'])
+
+
+class ParseFuncSignature(TestCase):
+ """
+ Test Suite for parse_function_signature().
+ """
+
+ def test_int_and_char_params(self):
+ """
+ Test int and char parameters parsing
+ :return:
+ """
+ line = 'void entropy_threshold( char * a, int b, int result )'
+ name, args, local, arg_dispatch = parse_function_signature(line)
+ self.assertEqual(name, 'entropy_threshold')
+ self.assertEqual(args, ['char*', 'int', 'int'])
+ self.assertEqual(local, '')
+ self.assertEqual(arg_dispatch, ['(char *) params[0]', '*( (int *) params[1] )', '*( (int *) params[2] )'])
+
+ def test_hex_params(self):
+ """
+ Test hex parameters parsing
+ :return:
+ """
+ line = 'void entropy_threshold( char * a, HexParam_t * h, int result )'
+ name, args, local, arg_dispatch = parse_function_signature(line)
+ self.assertEqual(name, 'entropy_threshold')
+ self.assertEqual(args, ['char*', 'hex', 'int'])
+ self.assertEqual(local, ' HexParam_t hex1 = {(uint8_t *) params[1], *( (uint32_t *) params[2] )};\n')
+ self.assertEqual(arg_dispatch, ['(char *) params[0]', '&hex1', '*( (int *) params[3] )'])
+
+ def test_non_void_function(self):
+ """
+ Test invalid signature (non void).
+ :return:
+ """
+ line = 'int entropy_threshold( char * a, HexParam_t * h, int result )'
+ self.assertRaises(ValueError, parse_function_signature, line)
+
+ def test_unsupported_arg(self):
+ """
+ Test unsupported arguments (not among int, char * and HexParam_t)
+ :return:
+ """
+ line = 'int entropy_threshold( char * a, HexParam_t * h, int * result )'
+ self.assertRaises(ValueError, parse_function_signature, line)
+
+ def test_no_params(self):
+ """
+ Test no parameters.
+ :return:
+ """
+ line = 'void entropy_threshold()'
+ name, args, local, arg_dispatch = parse_function_signature(line)
+ self.assertEqual(name, 'entropy_threshold')
+ self.assertEqual(args, [])
+ self.assertEqual(local, '')
+ self.assertEqual(arg_dispatch, [])
+
+
+class ParseFunctionCode(TestCase):
+ """
+ Test suite for testing parse_function_code()
+ """
+
+ def test_no_function(self):
+ """
+ Test no test function found.
+ :return:
+ """
+ data = '''
+No
+test
+function
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ self.assertRaises(InvalidFileFormat, parse_function_code, s, [], [])
+
+ def test_no_end_case_comment(self):
+ """
+ Test missing end case.
+ :return:
+ """
+ data = '''
+void test_func()
+{
+}
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ self.assertRaises(InvalidFileFormat, parse_function_code, s, [], [])
+
+ @patch("generate_test_code.parse_function_signature")
+ def test_parse_function_signature_called(self, parse_function_signature_mock):
+ """
+ Test parse_function_code()
+ :return:
+ """
+ parse_function_signature_mock.return_value = ('test_func', [], '', [])
+ data = '''
+void test_func()
+{
+}
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ self.assertRaises(InvalidFileFormat, parse_function_code, s, [], [])
+ self.assertTrue(parse_function_signature_mock.called)
+ parse_function_signature_mock.assert_called_with('void test_func()\n')
+
+ @patch("generate_test_code.gen_dispatch")
+ @patch("generate_test_code.gen_deps")
+ @patch("generate_test_code.gen_function_wrapper")
+ @patch("generate_test_code.parse_function_signature")
+ def test_return(self, parse_function_signature_mock,
+ gen_function_wrapper_mock,
+ gen_deps_mock,
+ gen_dispatch_mock):
+ """
+ Test generated code.
+ :return:
+ """
+ parse_function_signature_mock.return_value = ('func', [], '', [])
+ gen_function_wrapper_mock.return_value = ''
+ gen_deps_mock.side_effect = gen_deps
+ gen_dispatch_mock.side_effect = gen_dispatch
+ data = '''
+void func()
+{
+ ba ba black sheep
+ have you any wool
+}
+/* END_CASE */
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ name, arg, code, dispatch_code = parse_function_code(s, [], [])
+
+ #self.assertRaises(InvalidFileFormat, parse_function_code, s, [], [])
+ self.assertTrue(parse_function_signature_mock.called)
+ parse_function_signature_mock.assert_called_with('void func()\n')
+ gen_function_wrapper_mock.assert_called_with('test_func', '', [])
+ self.assertEqual(name, 'test_func')
+ self.assertEqual(arg, [])
+ expected = '''#line 2 "test_suite_ut.function"
+void test_func()
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ ;;
+}
+'''
+ self.assertEqual(code, expected)
+ self.assertEqual(dispatch_code, "\n test_func_wrapper,\n")
+
+ @patch("generate_test_code.gen_dispatch")
+ @patch("generate_test_code.gen_deps")
+ @patch("generate_test_code.gen_function_wrapper")
+ @patch("generate_test_code.parse_function_signature")
+ def test_with_exit_label(self, parse_function_signature_mock,
+ gen_function_wrapper_mock,
+ gen_deps_mock,
+ gen_dispatch_mock):
+ """
+ Test when exit label is present.
+ :return:
+ """
+ parse_function_signature_mock.return_value = ('func', [], '', [])
+ gen_function_wrapper_mock.return_value = ''
+ gen_deps_mock.side_effect = gen_deps
+ gen_dispatch_mock.side_effect = gen_dispatch
+ data = '''
+void func()
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ yes sir yes sir
+ 3 bags full
+}
+/* END_CASE */
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ name, arg, code, dispatch_code = parse_function_code(s, [], [])
+
+ expected = '''#line 2 "test_suite_ut.function"
+void test_func()
+{
+ ba ba black sheep
+ have you any wool
+exit:
+ yes sir yes sir
+ 3 bags full
+}
+'''
+ self.assertEqual(code, expected)
+
+
+class ParseFunction(TestCase):
+ """
+ Test Suite for testing parse_functions()
+ """
+
+ @patch("generate_test_code.parse_until_pattern")
+ def test_begin_header(self, parse_until_pattern_mock):
+ """
+ Test that begin header is checked and parse_until_pattern() is called.
+ :return:
+ """
+ def stop(this):
+ raise Exception
+ parse_until_pattern_mock.side_effect = stop
+ data = '''/* BEGIN_HEADER */
+#include "mbedcrypto/ecp.h"
+
+#define ECP_PF_UNKNOWN -1
+/* END_HEADER */
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ self.assertRaises(Exception, parse_functions, s)
+ parse_until_pattern_mock.assert_called_with(s, END_HEADER_REGEX)
+ self.assertEqual(s.line_no, 2)
+
+ @patch("generate_test_code.parse_until_pattern")
+ def test_begin_helper(self, parse_until_pattern_mock):
+ """
+ Test that begin helper is checked and parse_until_pattern() is called.
+ :return:
+ """
+ def stop(this):
+ raise Exception
+ parse_until_pattern_mock.side_effect = stop
+ data = '''/* BEGIN_SUITE_HELPERS */
+void print_helloworld()
+{
+ printf ("Hello World!\n");
+}
+/* END_SUITE_HELPERS */
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ self.assertRaises(Exception, parse_functions, s)
+ parse_until_pattern_mock.assert_called_with(s, END_SUITE_HELPERS_REGEX)
+ self.assertEqual(s.line_no, 2)
+
+ @patch("generate_test_code.parse_suite_deps")
+ def test_begin_dep(self, parse_suite_deps_mock):
+ """
+ Test that begin dep is checked and parse_suite_deps() is called.
+ :return:
+ """
+ def stop(this):
+ raise Exception
+ parse_suite_deps_mock.side_effect = stop
+ data = '''/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDCRYPTO_ECP_C
+ * END_DEPENDENCIES
+ */
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ self.assertRaises(Exception, parse_functions, s)
+ parse_suite_deps_mock.assert_called_with(s)
+ self.assertEqual(s.line_no, 2)
+
+ @patch("generate_test_code.parse_function_deps")
+ def test_begin_function_dep(self, parse_function_deps_mock):
+ """
+ Test that begin dep is checked and parse_function_deps() is called.
+ :return:
+ """
+ def stop(this):
+ raise Exception
+ parse_function_deps_mock.side_effect = stop
+
+ deps_str = '/* BEGIN_CASE depends_on:MBEDCRYPTO_ENTROPY_NV_SEED:MBEDCRYPTO_FS_IO */\n'
+ data = '''%svoid test_func()
+{
+}
+''' % deps_str
+ s = StringIOWrapper('test_suite_ut.function', data)
+ self.assertRaises(Exception, parse_functions, s)
+ parse_function_deps_mock.assert_called_with(deps_str)
+ self.assertEqual(s.line_no, 2)
+
+ @patch("generate_test_code.parse_function_code")
+ @patch("generate_test_code.parse_function_deps")
+ def test_return(self, parse_function_deps_mock, parse_function_code_mock):
+ """
+ Test that begin case is checked and parse_function_code() is called.
+ :return:
+ """
+ def stop(this):
+ raise Exception
+ parse_function_deps_mock.return_value = []
+ in_func_code= '''void test_func()
+{
+}
+'''
+ func_dispatch = '''
+ test_func_wrapper,
+'''
+ parse_function_code_mock.return_value = 'test_func', [], in_func_code, func_dispatch
+ deps_str = '/* BEGIN_CASE depends_on:MBEDCRYPTO_ENTROPY_NV_SEED:MBEDCRYPTO_FS_IO */\n'
+ data = '''%svoid test_func()
+{
+}
+''' % deps_str
+ s = StringIOWrapper('test_suite_ut.function', data)
+ suite_deps, dispatch_code, func_code, func_info = parse_functions(s)
+ parse_function_deps_mock.assert_called_with(deps_str)
+ parse_function_code_mock.assert_called_with(s, [], [])
+ self.assertEqual(s.line_no, 5)
+ self.assertEqual(suite_deps, [])
+ expected_dispatch_code = '''/* Function Id: 0 */
+
+ test_func_wrapper,
+'''
+ self.assertEqual(dispatch_code, expected_dispatch_code)
+ self.assertEqual(func_code, in_func_code)
+ self.assertEqual(func_info, {'test_func': (0, [])})
+
+ def test_parsing(self):
+ """
+ Test case parsing.
+ :return:
+ """
+ data = '''/* BEGIN_HEADER */
+#include "mbedcrypto/ecp.h"
+
+#define ECP_PF_UNKNOWN -1
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDCRYPTO_ECP_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:MBEDCRYPTO_ENTROPY_NV_SEED:MBEDCRYPTO_FS_IO */
+void func1()
+{
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDCRYPTO_ENTROPY_NV_SEED:MBEDCRYPTO_FS_IO */
+void func2()
+{
+}
+/* END_CASE */
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ suite_deps, dispatch_code, func_code, func_info = parse_functions(s)
+ self.assertEqual(s.line_no, 23)
+ self.assertEqual(suite_deps, ['MBEDCRYPTO_ECP_C'])
+
+ expected_dispatch_code = '''/* Function Id: 0 */
+
+#if defined(MBEDCRYPTO_ECP_C) && defined(MBEDCRYPTO_ENTROPY_NV_SEED) && defined(MBEDCRYPTO_FS_IO)
+ test_func1_wrapper,
+#else
+ NULL,
+#endif
+/* Function Id: 1 */
+
+#if defined(MBEDCRYPTO_ECP_C) && defined(MBEDCRYPTO_ENTROPY_NV_SEED) && defined(MBEDCRYPTO_FS_IO)
+ test_func2_wrapper,
+#else
+ NULL,
+#endif
+'''
+ self.assertEqual(dispatch_code, expected_dispatch_code)
+ expected_func_code = '''#if defined(MBEDCRYPTO_ECP_C)
+#line 3 "test_suite_ut.function"
+#include "mbedcrypto/ecp.h"
+
+#define ECP_PF_UNKNOWN -1
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+#if defined(MBEDCRYPTO_FS_IO)
+#line 14 "test_suite_ut.function"
+void test_func1()
+{
+exit:
+ ;;
+}
+
+void test_func1_wrapper( void ** params )
+{
+ (void)params;
+
+ test_func1( );
+}
+#endif /* MBEDCRYPTO_FS_IO */
+#endif /* MBEDCRYPTO_ENTROPY_NV_SEED */
+#if defined(MBEDCRYPTO_ENTROPY_NV_SEED)
+#if defined(MBEDCRYPTO_FS_IO)
+#line 20 "test_suite_ut.function"
+void test_func2()
+{
+exit:
+ ;;
+}
+
+void test_func2_wrapper( void ** params )
+{
+ (void)params;
+
+ test_func2( );
+}
+#endif /* MBEDCRYPTO_FS_IO */
+#endif /* MBEDCRYPTO_ENTROPY_NV_SEED */
+#endif /* MBEDCRYPTO_ECP_C */
+'''
+ self.assertEqual(func_code, expected_func_code)
+ self.assertEqual(func_info, {'test_func1': (0, []), 'test_func2': (1, [])})
+
+ def test_same_function_name(self):
+ """
+ Test name conflict.
+ :return:
+ """
+ data = '''/* BEGIN_HEADER */
+#include "mbedcrypto/ecp.h"
+
+#define ECP_PF_UNKNOWN -1
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDCRYPTO_ECP_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:MBEDCRYPTO_ENTROPY_NV_SEED:MBEDCRYPTO_FS_IO */
+void func()
+{
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDCRYPTO_ENTROPY_NV_SEED:MBEDCRYPTO_FS_IO */
+void func()
+{
+}
+/* END_CASE */
+'''
+ s = StringIOWrapper('test_suite_ut.function', data)
+ self.assertRaises(AssertionError, parse_functions, s)
+
+
+class ExcapedSplit(TestCase):
+ """
+ Test suite for testing escaped_split().
+ Note: Since escaped_split() output is used to write back to the intermediate data file. Any escape characters
+ in the input are retained in the output.
+ """
+
+ def test_invalid_input(self):
+ """
+ Test when input split character is not a character.
+ :return:
+ """
+ self.assertRaises(ValueError, escaped_split, '', 'string')
+
+ def test_empty_string(self):
+ """
+ Test empty strig input.
+ :return:
+ """
+ splits = escaped_split('', ':')
+ self.assertEqual(splits, [])
+
+ def test_no_escape(self):
+ """
+ Test with no escape character. The behaviour should be same as str.split()
+ :return:
+ """
+ s = 'yahoo:google'
+ splits = escaped_split(s, ':')
+ self.assertEqual(splits, s.split(':'))
+
+ def test_escaped_input(self):
+ """
+ Test imput that has escaped delimiter.
+ :return:
+ """
+ s = 'yahoo\:google:facebook'
+ splits = escaped_split(s, ':')
+ self.assertEqual(splits, ['yahoo\:google', 'facebook'])
+
+ def test_escaped_escape(self):
+ """
+ Test imput that has escaped delimiter.
+ :return:
+ """
+ s = 'yahoo\\\:google:facebook'
+ splits = escaped_split(s, ':')
+ self.assertEqual(splits, ['yahoo\\\\', 'google', 'facebook'])
+
+ def test_all_at_once(self):
+ """
+ Test imput that has escaped delimiter.
+ :return:
+ """
+ s = 'yahoo\\\:google:facebook\:instagram\\\:bbc\\\\:wikipedia'
+ splits = escaped_split(s, ':')
+ self.assertEqual(splits, ['yahoo\\\\', 'google', 'facebook\:instagram\\\\', 'bbc\\\\', 'wikipedia'])
+
+
+class ParseTestData(TestCase):
+ """
+ Test suite for parse test data.
+ """
+
+ def test_parser(self):
+ """
+ Test that tests are parsed correctly from data file.
+ :return:
+ """
+ data = """
+Diffie-Hellman full exchange #1
+dhm_do_dhm:10:"23":10:"5"
+
+Diffie-Hellman full exchange #2
+dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
+
+Diffie-Hellman full exchange #3
+dhm_do_dhm:10:"9345098382739712938719287391879381271":10:"9345098792137312973297123912791271"
+
+Diffie-Hellman selftest
+dhm_selftest:
+"""
+ s = StringIOWrapper('test_suite_ut.function', data)
+ tests = [(name, function, deps, args) for name, function, deps, args in parse_test_data(s)]
+ t1, t2, t3, t4 = tests
+ self.assertEqual(t1[0], 'Diffie-Hellman full exchange #1')
+ self.assertEqual(t1[1], 'dhm_do_dhm')
+ self.assertEqual(t1[2], [])
+ self.assertEqual(t1[3], ['10', '"23"', '10', '"5"'])
+
+ self.assertEqual(t2[0], 'Diffie-Hellman full exchange #2')
+ self.assertEqual(t2[1], 'dhm_do_dhm')
+ self.assertEqual(t2[2], [])
+ self.assertEqual(t2[3], ['10', '"93450983094850938450983409623"', '10', '"9345098304850938450983409622"'])
+
+ self.assertEqual(t3[0], 'Diffie-Hellman full exchange #3')
+ self.assertEqual(t3[1], 'dhm_do_dhm')
+ self.assertEqual(t3[2], [])
+ self.assertEqual(t3[3], ['10', '"9345098382739712938719287391879381271"', '10', '"9345098792137312973297123912791271"'])
+
+ self.assertEqual(t4[0], 'Diffie-Hellman selftest')
+ self.assertEqual(t4[1], 'dhm_selftest')
+ self.assertEqual(t4[2], [])
+ self.assertEqual(t4[3], [])
+
+ def test_with_dependencies(self):
+ """
+ Test that tests with dependencies are parsed.
+ :return:
+ """
+ data = """
+Diffie-Hellman full exchange #1
+depends_on:YAHOO
+dhm_do_dhm:10:"23":10:"5"
+
+Diffie-Hellman full exchange #2
+dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
+
+"""
+ s = StringIOWrapper('test_suite_ut.function', data)
+ tests = [(name, function, deps, args) for name, function, deps, args in parse_test_data(s)]
+ t1, t2 = tests
+ self.assertEqual(t1[0], 'Diffie-Hellman full exchange #1')
+ self.assertEqual(t1[1], 'dhm_do_dhm')
+ self.assertEqual(t1[2], ['YAHOO'])
+ self.assertEqual(t1[3], ['10', '"23"', '10', '"5"'])
+
+ self.assertEqual(t2[0], 'Diffie-Hellman full exchange #2')
+ self.assertEqual(t2[1], 'dhm_do_dhm')
+ self.assertEqual(t2[2], [])
+ self.assertEqual(t2[3], ['10', '"93450983094850938450983409623"', '10', '"9345098304850938450983409622"'])
+
+ def test_no_args(self):
+ """
+ Test AssertionError is raised when test function name and args line is missing.
+ :return:
+ """
+ data = """
+Diffie-Hellman full exchange #1
+depends_on:YAHOO
+
+
+Diffie-Hellman full exchange #2
+dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
+
+"""
+ s = StringIOWrapper('test_suite_ut.function', data)
+ e = None
+ try:
+ for x, y, z, a in parse_test_data(s):
+ pass
+ except AssertionError, e:
+ pass
+ self.assertEqual(type(e), AssertionError)
+
+ def test_incomplete_data(self):
+ """
+ Test AssertionError is raised when test function name and args line is missing.
+ :return:
+ """
+ data = """
+Diffie-Hellman full exchange #1
+depends_on:YAHOO
+"""
+ s = StringIOWrapper('test_suite_ut.function', data)
+ e = None
+ try:
+ for x, y, z, a in parse_test_data(s):
+ pass
+ except AssertionError, e:
+ pass
+ self.assertEqual(type(e), AssertionError)
+
+
+class GenDepCheck(TestCase):
+ """
+ Test suite for gen_dep_check(). It is assumed this function is called with valid inputs.
+ """
+
+ def test_gen_dep_check(self):
+ """
+ Test that dependency check code generated correctly.
+ :return:
+ """
+ expected = """
+ case 5:
+ {
+#if defined(YAHOO)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;"""
+ out = gen_dep_check(5, 'YAHOO')
+ self.assertEqual(out, expected)
+
+ def test_noT(self):
+ """
+ Test dependency with !.
+ :return:
+ """
+ expected = """
+ case 5:
+ {
+#if !defined(YAHOO)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;"""
+ out = gen_dep_check(5, '!YAHOO')
+ self.assertEqual(out, expected)
+
+ def test_empty_dependency(self):
+ """
+ Test invalid dependency input.
+ :return:
+ """
+ self.assertRaises(AssertionError, gen_dep_check, 5, '!')
+
+ def test_negative_dep_id(self):
+ """
+ Test invalid dependency input.
+ :return:
+ """
+ self.assertRaises(AssertionError, gen_dep_check, -1, 'YAHOO')
+
+
+class GenExpCheck(TestCase):
+ """
+ Test suite for gen_expression_check(). It is assumed this function is called with valid inputs.
+ """
+
+ def test_gen_exp_check(self):
+ """
+ Test that expression check code generated correctly.
+ :return:
+ """
+ expected = """
+ case 5:
+ {
+ *out_value = YAHOO;
+ }
+ break;"""
+ out = gen_expression_check(5, 'YAHOO')
+ self.assertEqual(out, expected)
+
+ def test_invalid_expression(self):
+ """
+ Test invalid expression input.
+ :return:
+ """
+ self.assertRaises(AssertionError, gen_expression_check, 5, '')
+
+ def test_negative_exp_id(self):
+ """
+ Test invalid expression id.
+ :return:
+ """
+ self.assertRaises(AssertionError, gen_expression_check, -1, 'YAHOO')
+
+
+class WriteDeps(TestCase):
+ """
+ Test suite for testing write_deps.
+ """
+
+ def test_no_test_deps(self):
+ """
+ Test when test_deps is empty.
+ :return:
+ """
+ s = StringIOWrapper('test_suite_ut.data', '')
+ unique_deps = []
+ dep_check_code = write_deps(s, [], unique_deps)
+ self.assertEqual(dep_check_code, '')
+ self.assertEqual(len(unique_deps), 0)
+ self.assertEqual(s.getvalue(), '')
+
+ def test_unique_dep_ids(self):
+ """
+
+ :return:
+ """
+ s = StringIOWrapper('test_suite_ut.data', '')
+ unique_deps = []
+ dep_check_code = write_deps(s, ['DEP3', 'DEP2', 'DEP1'], unique_deps)
+ expect_dep_check_code = '''
+ case 0:
+ {
+#if defined(DEP3)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;
+ case 1:
+ {
+#if defined(DEP2)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;
+ case 2:
+ {
+#if defined(DEP1)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;'''
+ self.assertEqual(dep_check_code, expect_dep_check_code)
+ self.assertEqual(len(unique_deps), 3)
+ self.assertEqual(s.getvalue(), 'depends_on:0:1:2\n')
+
+ def test_dep_id_repeat(self):
+ """
+
+ :return:
+ """
+ s = StringIOWrapper('test_suite_ut.data', '')
+ unique_deps = []
+ dep_check_code = ''
+ dep_check_code += write_deps(s, ['DEP3', 'DEP2'], unique_deps)
+ dep_check_code += write_deps(s, ['DEP2', 'DEP1'], unique_deps)
+ dep_check_code += write_deps(s, ['DEP1', 'DEP3'], unique_deps)
+ expect_dep_check_code = '''
+ case 0:
+ {
+#if defined(DEP3)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;
+ case 1:
+ {
+#if defined(DEP2)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;
+ case 2:
+ {
+#if defined(DEP1)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;'''
+ self.assertEqual(dep_check_code, expect_dep_check_code)
+ self.assertEqual(len(unique_deps), 3)
+ self.assertEqual(s.getvalue(), 'depends_on:0:1\ndepends_on:1:2\ndepends_on:2:0\n')
+
+
+class WriteParams(TestCase):
+ """
+ Test Suite for testing write_parameters().
+ """
+
+ def test_no_params(self):
+ """
+ Test with empty test_args
+ :return:
+ """
+ s = StringIOWrapper('test_suite_ut.data', '')
+ unique_expressions = []
+ expression_code = write_parameters(s, [], [], unique_expressions)
+ self.assertEqual(len(unique_expressions), 0)
+ self.assertEqual(expression_code, '')
+ self.assertEqual(s.getvalue(), '\n')
+
+ def test_no_exp_param(self):
+ """
+ Test when there is no macro or expression in the params.
+ :return:
+ """
+ s = StringIOWrapper('test_suite_ut.data', '')
+ unique_expressions = []
+ expression_code = write_parameters(s, ['"Yahoo"', '"abcdef00"', '0'], ['char*', 'hex', 'int'],
+ unique_expressions)
+ self.assertEqual(len(unique_expressions), 0)
+ self.assertEqual(expression_code, '')
+ self.assertEqual(s.getvalue(), ':char*:"Yahoo":hex:"abcdef00":int:0\n')
+
+ def test_hex_format_int_param(self):
+ """
+ Test int parameter in hex format.
+ :return:
+ """
+ s = StringIOWrapper('test_suite_ut.data', '')
+ unique_expressions = []
+ expression_code = write_parameters(s, ['"Yahoo"', '"abcdef00"', '0xAA'], ['char*', 'hex', 'int'],
+ unique_expressions)
+ self.assertEqual(len(unique_expressions), 0)
+ self.assertEqual(expression_code, '')
+ self.assertEqual(s.getvalue(), ':char*:"Yahoo":hex:"abcdef00":int:0xAA\n')
+
+ def test_with_exp_param(self):
+ """
+ Test when there is macro or expression in the params.
+ :return:
+ """
+ s = StringIOWrapper('test_suite_ut.data', '')
+ unique_expressions = []
+ expression_code = write_parameters(s, ['"Yahoo"', '"abcdef00"', '0', 'MACRO1', 'MACRO2', 'MACRO3'],
+ ['char*', 'hex', 'int', 'int', 'int', 'int'],
+ unique_expressions)
+ self.assertEqual(len(unique_expressions), 3)
+ self.assertEqual(unique_expressions, ['MACRO1', 'MACRO2', 'MACRO3'])
+ expected_expression_code = '''
+ case 0:
+ {
+ *out_value = MACRO1;
+ }
+ break;
+ case 1:
+ {
+ *out_value = MACRO2;
+ }
+ break;
+ case 2:
+ {
+ *out_value = MACRO3;
+ }
+ break;'''
+ self.assertEqual(expression_code, expected_expression_code)
+ self.assertEqual(s.getvalue(), ':char*:"Yahoo":hex:"abcdef00":int:0:exp:0:exp:1:exp:2\n')
+
+ def test_with_repeate_calls(self):
+ """
+ Test when write_parameter() is called with same macro or expression.
+ :return:
+ """
+ s = StringIOWrapper('test_suite_ut.data', '')
+ unique_expressions = []
+ expression_code = ''
+ expression_code += write_parameters(s, ['"Yahoo"', 'MACRO1', 'MACRO2'], ['char*', 'int', 'int'],
+ unique_expressions)
+ expression_code += write_parameters(s, ['"abcdef00"', 'MACRO2', 'MACRO3'], ['hex', 'int', 'int'],
+ unique_expressions)
+ expression_code += write_parameters(s, ['0', 'MACRO3', 'MACRO1'], ['int', 'int', 'int'],
+ unique_expressions)
+ self.assertEqual(len(unique_expressions), 3)
+ self.assertEqual(unique_expressions, ['MACRO1', 'MACRO2', 'MACRO3'])
+ expected_expression_code = '''
+ case 0:
+ {
+ *out_value = MACRO1;
+ }
+ break;
+ case 1:
+ {
+ *out_value = MACRO2;
+ }
+ break;
+ case 2:
+ {
+ *out_value = MACRO3;
+ }
+ break;'''
+ self.assertEqual(expression_code, expected_expression_code)
+ expected_data_file = ''':char*:"Yahoo":exp:0:exp:1
+:hex:"abcdef00":exp:1:exp:2
+:int:0:exp:2:exp:0
+'''
+ self.assertEqual(s.getvalue(), expected_data_file)
+
+
+class GenTestSuiteDepsChecks(TestCase):
+ """
+
+ """
+ def test_empty_suite_deps(self):
+ """
+ Test with empty suite_deps list.
+
+ :return:
+ """
+ dep_check_code, expression_code = gen_suite_deps_checks([], 'DEP_CHECK_CODE', 'EXPRESSION_CODE')
+ self.assertEqual(dep_check_code, 'DEP_CHECK_CODE')
+ self.assertEqual(expression_code, 'EXPRESSION_CODE')
+
+ def test_suite_deps(self):
+ """
+ Test with suite_deps list.
+
+ :return:
+ """
+ dep_check_code, expression_code = gen_suite_deps_checks(['SUITE_DEP'], 'DEP_CHECK_CODE', 'EXPRESSION_CODE')
+ exprectd_dep_check_code = '''
+#if defined(SUITE_DEP)
+DEP_CHECK_CODE
+#endif
+'''
+ expected_expression_code = '''
+#if defined(SUITE_DEP)
+EXPRESSION_CODE
+#endif
+'''
+ self.assertEqual(dep_check_code, exprectd_dep_check_code)
+ self.assertEqual(expression_code, expected_expression_code)
+
+ def test_no_dep_no_exp(self):
+ """
+ Test when there are no dependency and expression code.
+ :return:
+ """
+ dep_check_code, expression_code = gen_suite_deps_checks([], '', '')
+ self.assertEqual(dep_check_code, '')
+ self.assertEqual(expression_code, '')
+
+
+class GenFromTestData(TestCase):
+ """
+ Test suite for gen_from_test_data()
+ """
+
+ @patch("generate_test_code.write_deps")
+ @patch("generate_test_code.write_parameters")
+ @patch("generate_test_code.gen_suite_deps_checks")
+ def test_intermediate_data_file(self, gen_suite_deps_checks_mock, write_parameters_mock, write_deps_mock):
+ """
+ Test that intermediate data file is written with expected data.
+ :return:
+ """
+ data = '''
+My test
+depends_on:DEP1
+func1:0
+'''
+ data_f = StringIOWrapper('test_suite_ut.data', data)
+ out_data_f = StringIOWrapper('test_suite_ut.datax', '')
+ func_info = {'test_func1': (1, ('int',))}
+ suite_deps = []
+ write_parameters_mock.side_effect = write_parameters
+ write_deps_mock.side_effect = write_deps
+ gen_suite_deps_checks_mock.side_effect = gen_suite_deps_checks
+ gen_from_test_data(data_f, out_data_f, func_info, suite_deps)
+ write_deps_mock.assert_called_with(out_data_f, ['DEP1'], ['DEP1'])
+ write_parameters_mock.assert_called_with(out_data_f, ['0'], ('int',), [])
+ expected_dep_check_code = '''
+ case 0:
+ {
+#if defined(DEP1)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;'''
+ gen_suite_deps_checks_mock.assert_called_with(suite_deps, expected_dep_check_code, '')
+
+ def test_function_not_found(self):
+ """
+ Test that AssertError is raised when function info in not found.
+ :return:
+ """
+ data = '''
+My test
+depends_on:DEP1
+func1:0
+'''
+ data_f = StringIOWrapper('test_suite_ut.data', data)
+ out_data_f = StringIOWrapper('test_suite_ut.datax', '')
+ func_info = {'test_func2': (1, ('int',))}
+ suite_deps = []
+ self.assertRaises(AssertionError, gen_from_test_data, data_f, out_data_f, func_info, suite_deps)
+
+ def test_different_func_args(self):
+ """
+ Test that AssertError is raised when no. of parameters and function args differ.
+ :return:
+ """
+ data = '''
+My test
+depends_on:DEP1
+func1:0
+'''
+ data_f = StringIOWrapper('test_suite_ut.data', data)
+ out_data_f = StringIOWrapper('test_suite_ut.datax', '')
+ func_info = {'test_func2': (1, ('int','hex'))}
+ suite_deps = []
+ self.assertRaises(AssertionError, gen_from_test_data, data_f, out_data_f, func_info, suite_deps)
+
+ def test_output(self):
+ """
+ Test that intermediate data file is written with expected data.
+ :return:
+ """
+ data = '''
+My test 1
+depends_on:DEP1
+func1:0:0xfa:MACRO1:MACRO2
+
+My test 2
+depends_on:DEP1:DEP2
+func2:"yahoo":88:MACRO1
+'''
+ data_f = StringIOWrapper('test_suite_ut.data', data)
+ out_data_f = StringIOWrapper('test_suite_ut.datax', '')
+ func_info = {'test_func1': (0, ('int', 'int', 'int', 'int')), 'test_func2': (1, ('char*', 'int', 'int'))}
+ suite_deps = []
+ dep_check_code, expression_code = gen_from_test_data(data_f, out_data_f, func_info, suite_deps)
+ expected_dep_check_code = '''
+ case 0:
+ {
+#if defined(DEP1)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;
+ case 1:
+ {
+#if defined(DEP2)
+ ret = DEPENDENCY_SUPPORTED;
+#else
+ ret = DEPENDENCY_NOT_SUPPORTED;
+#endif
+ }
+ break;'''
+ expecrted_data = '''My test 1
+depends_on:0
+0:int:0:int:0xfa:exp:0:exp:1
+
+My test 2
+depends_on:0:1
+1:char*:"yahoo":int:88:exp:0
+
+'''
+ expected_expression_code = '''
+ case 0:
+ {
+ *out_value = MACRO1;
+ }
+ break;
+ case 1:
+ {
+ *out_value = MACRO2;
+ }
+ break;'''
+ self.assertEqual(dep_check_code, expected_dep_check_code)
+ self.assertEqual(out_data_f.getvalue(), expecrted_data)
+ self.assertEqual(expression_code, expected_expression_code)
+
+
+if __name__=='__main__':
+ unittest_main()
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
new file mode 100644
index 0000000..6f79701
--- /dev/null
+++ b/tests/suites/helpers.function
@@ -0,0 +1,469 @@
+#line 2 "suites/helpers.function"
+/*----------------------------------------------------------------------------*/
+/* Headers */
+
+#include <stdlib.h>
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+#include "mbedcrypto/platform.h"
+#else
+#include <stdio.h>
+#define mbedcrypto_fprintf fprintf
+#define mbedcrypto_snprintf snprintf
+#define mbedcrypto_calloc calloc
+#define mbedcrypto_free free
+#define mbedcrypto_exit exit
+#define mbedcrypto_time time
+#define mbedcrypto_time_t time_t
+#define MBEDCRYPTO_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDCRYPTO_EXIT_FAILURE EXIT_FAILURE
+#endif
+
+#if defined(MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C)
+#include "mbedcrypto/memory_buffer_alloc.h"
+#endif
+
+#ifdef _MSC_VER
+#include <basetsd.h>
+typedef UINT32 uint32_t;
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
+#else
+#include <stdint.h>
+#endif
+
+#include <string.h>
+
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+#include <unistd.h>
+#endif
+
+/* Type for Hex parameters */
+typedef struct HexParam_tag
+{
+ uint8_t * x;
+ uint32_t len;
+} HexParam_t;
+
+/*----------------------------------------------------------------------------*/
+/* Constants */
+
+#define DEPENDENCY_SUPPORTED 0
+#define KEY_VALUE_MAPPING_FOUND 0
+#define DISPATCH_TEST_SUCCESS 0
+
+#define KEY_VALUE_MAPPING_NOT_FOUND -1
+#define DEPENDENCY_NOT_SUPPORTED -2
+#define DISPATCH_TEST_FN_NOT_FOUND -3
+#define DISPATCH_INVALID_TEST_DATA -4
+#define DISPATCH_UNSUPPORTED_SUITE -5
+
+
+/*----------------------------------------------------------------------------*/
+/* Macros */
+
+#define TEST_ASSERT( TEST ) \
+ do { \
+ if( ! (TEST) ) \
+ { \
+ test_fail( #TEST, __LINE__, __FILE__ ); \
+ goto exit; \
+ } \
+ } while( 0 )
+
+#define assert(a) if( !( a ) ) \
+{ \
+ mbedcrypto_fprintf( stderr, "Assertion Failed at %s:%d - %s\n", \
+ __FILE__, __LINE__, #a ); \
+ mbedcrypto_exit( 1 ); \
+}
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+
+/*----------------------------------------------------------------------------*/
+/* Global variables */
+
+
+static struct
+{
+ int failed;
+ const char *test;
+ const char *filename;
+ int line_no;
+}
+test_info;
+
+#if defined(MBEDCRYPTO_PLATFORM_C)
+mbedcrypto_platform_context platform_ctx;
+#endif
+
+/*----------------------------------------------------------------------------*/
+/* Helper flags for complex dependencies */
+
+/* Indicates whether we expect mbedcrypto_entropy_init
+ * to initialize some strong entropy source. */
+#if defined(MBEDCRYPTO_TEST_NULL_ENTROPY) || \
+ ( !defined(MBEDCRYPTO_NO_DEFAULT_ENTROPY_SOURCES) && \
+ ( !defined(MBEDCRYPTO_NO_PLATFORM_ENTROPY) || \
+ defined(MBEDCRYPTO_HAVEGE_C) || \
+ defined(MBEDCRYPTO_ENTROPY_HARDWARE_ALT) || \
+ defined(ENTROPY_NV_SEED) ) )
+#define ENTROPY_HAVE_STRONG
+#endif
+
+
+/*----------------------------------------------------------------------------*/
+/* Helper Functions */
+static int platform_setup()
+{
+ int ret = 0;
+#if defined(MBEDCRYPTO_PLATFORM_C)
+ ret = mbedcrypto_platform_setup( &platform_ctx );
+#endif /* MBEDCRYPTO_PLATFORM_C */
+ return( ret );
+}
+
+static void platform_teardown()
+{
+#if defined(MBEDCRYPTO_PLATFORM_C)
+ mbedcrypto_platform_teardown( &platform_ctx );
+#endif /* MBEDCRYPTO_PLATFORM_C */
+}
+
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+static int redirect_output( FILE** out_stream, const char* path )
+{
+ int stdout_fd = dup( fileno( *out_stream ) );
+
+ if( stdout_fd == -1 )
+ {
+ return -1;
+ }
+
+ fflush( *out_stream );
+ fclose( *out_stream );
+ *out_stream = fopen( path, "w" );
+
+ if( *out_stream == NULL )
+ {
+ return -1;
+ }
+
+ return stdout_fd;
+}
+
+static int restore_output( FILE** out_stream, int old_fd )
+{
+ fflush( *out_stream );
+ fclose( *out_stream );
+
+ *out_stream = fdopen( old_fd, "w" );
+ if( *out_stream == NULL )
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+static void close_output( FILE* out_stream )
+{
+ fclose( out_stream );
+}
+#endif /* __unix__ || __APPLE__ __MACH__ */
+
+static int unhexify( unsigned char *obuf, const char *ibuf )
+{
+ unsigned char c, c2;
+ int len = strlen( ibuf ) / 2;
+ assert( strlen( ibuf ) % 2 == 0 ); /* must be even number of bytes */
+
+ while( *ibuf != 0 )
+ {
+ c = *ibuf++;
+ if( c >= '0' && c <= '9' )
+ c -= '0';
+ else if( c >= 'a' && c <= 'f' )
+ c -= 'a' - 10;
+ else if( c >= 'A' && c <= 'F' )
+ c -= 'A' - 10;
+ else
+ assert( 0 );
+
+ c2 = *ibuf++;
+ if( c2 >= '0' && c2 <= '9' )
+ c2 -= '0';
+ else if( c2 >= 'a' && c2 <= 'f' )
+ c2 -= 'a' - 10;
+ else if( c2 >= 'A' && c2 <= 'F' )
+ c2 -= 'A' - 10;
+ else
+ assert( 0 );
+
+ *obuf++ = ( c << 4 ) | c2;
+ }
+
+ return len;
+}
+
+static void hexify( unsigned char *obuf, const unsigned char *ibuf, int len )
+{
+ unsigned char l, h;
+
+ while( len != 0 )
+ {
+ h = *ibuf / 16;
+ l = *ibuf % 16;
+
+ if( h < 10 )
+ *obuf++ = '0' + h;
+ else
+ *obuf++ = 'a' + h - 10;
+
+ if( l < 10 )
+ *obuf++ = '0' + l;
+ else
+ *obuf++ = 'a' + l - 10;
+
+ ++ibuf;
+ len--;
+ }
+}
+
+/**
+ * Allocate and zeroize a buffer.
+ *
+ * If the size if zero, a pointer to a zeroized 1-byte buffer is returned.
+ *
+ * For convenience, dies if allocation fails.
+ */
+static unsigned char *zero_alloc( size_t len )
+{
+ void *p;
+ size_t actual_len = ( len != 0 ) ? len : 1;
+
+ p = mbedcrypto_calloc( 1, actual_len );
+ assert( p != NULL );
+
+ memset( p, 0x00, actual_len );
+
+ return( p );
+}
+
+/**
+ * Allocate and fill a buffer from hex data.
+ *
+ * The buffer is sized exactly as needed. This allows to detect buffer
+ * overruns (including overreads) when running the test suite under valgrind.
+ *
+ * If the size if zero, a pointer to a zeroized 1-byte buffer is returned.
+ *
+ * For convenience, dies if allocation fails.
+ */
+static unsigned char *unhexify_alloc( const char *ibuf, size_t *olen )
+{
+ unsigned char *obuf;
+
+ *olen = strlen( ibuf ) / 2;
+
+ if( *olen == 0 )
+ return( zero_alloc( *olen ) );
+
+ obuf = mbedcrypto_calloc( 1, *olen );
+ assert( obuf != NULL );
+
+ (void) unhexify( obuf, ibuf );
+
+ return( obuf );
+}
+
+/**
+ * This function just returns data from rand().
+ * Although predictable and often similar on multiple
+ * runs, this does not result in identical random on
+ * each run. So do not use this if the results of a
+ * test depend on the random data that is generated.
+ *
+ * rng_state shall be NULL.
+ */
+static int rnd_std_rand( void *rng_state, unsigned char *output, size_t len )
+{
+#if !defined(__OpenBSD__)
+ size_t i;
+
+ if( rng_state != NULL )
+ rng_state = NULL;
+
+ for( i = 0; i < len; ++i )
+ output[i] = rand();
+#else
+ if( rng_state != NULL )
+ rng_state = NULL;
+
+ arc4random_buf( output, len );
+#endif /* !OpenBSD */
+
+ return( 0 );
+}
+
+/**
+ * This function only returns zeros
+ *
+ * rng_state shall be NULL.
+ */
+static int rnd_zero_rand( void *rng_state, unsigned char *output, size_t len )
+{
+ if( rng_state != NULL )
+ rng_state = NULL;
+
+ memset( output, 0, len );
+
+ return( 0 );
+}
+
+typedef struct
+{
+ unsigned char *buf;
+ size_t length;
+} rnd_buf_info;
+
+/**
+ * This function returns random based on a buffer it receives.
+ *
+ * rng_state shall be a pointer to a rnd_buf_info structure.
+ *
+ * The number of bytes released from the buffer on each call to
+ * the random function is specified by per_call. (Can be between
+ * 1 and 4)
+ *
+ * After the buffer is empty it will return rand();
+ */
+static int rnd_buffer_rand( void *rng_state, unsigned char *output, size_t len )
+{
+ rnd_buf_info *info = (rnd_buf_info *) rng_state;
+ size_t use_len;
+
+ if( rng_state == NULL )
+ return( rnd_std_rand( NULL, output, len ) );
+
+ use_len = len;
+ if( len > info->length )
+ use_len = info->length;
+
+ if( use_len )
+ {
+ memcpy( output, info->buf, use_len );
+ info->buf += use_len;
+ info->length -= use_len;
+ }
+
+ if( len - use_len > 0 )
+ return( rnd_std_rand( NULL, output + use_len, len - use_len ) );
+
+ return( 0 );
+}
+
+/**
+ * Info structure for the pseudo random function
+ *
+ * Key should be set at the start to a test-unique value.
+ * Do not forget endianness!
+ * State( v0, v1 ) should be set to zero.
+ */
+typedef struct
+{
+ uint32_t key[16];
+ uint32_t v0, v1;
+} rnd_pseudo_info;
+
+/**
+ * This function returns random based on a pseudo random function.
+ * This means the results should be identical on all systems.
+ * Pseudo random is based on the XTEA encryption algorithm to
+ * generate pseudorandom.
+ *
+ * rng_state shall be a pointer to a rnd_pseudo_info structure.
+ */
+static int rnd_pseudo_rand( void *rng_state, unsigned char *output, size_t len )
+{
+ rnd_pseudo_info *info = (rnd_pseudo_info *) rng_state;
+ uint32_t i, *k, sum, delta=0x9E3779B9;
+ unsigned char result[4], *out = output;
+
+ if( rng_state == NULL )
+ return( rnd_std_rand( NULL, output, len ) );
+
+ k = info->key;
+
+ while( len > 0 )
+ {
+ size_t use_len = ( len > 4 ) ? 4 : len;
+ sum = 0;
+
+ for( i = 0; i < 32; i++ )
+ {
+ info->v0 += ( ( ( info->v1 << 4 ) ^ ( info->v1 >> 5 ) )
+ + info->v1 ) ^ ( sum + k[sum & 3] );
+ sum += delta;
+ info->v1 += ( ( ( info->v0 << 4 ) ^ ( info->v0 >> 5 ) )
+ + info->v0 ) ^ ( sum + k[( sum>>11 ) & 3] );
+ }
+
+ PUT_UINT32_BE( info->v0, result, 0 );
+ memcpy( out, result, use_len );
+ len -= use_len;
+ out += 4;
+ }
+
+ return( 0 );
+}
+
+static void test_fail( const char *test, int line_no, const char* filename )
+{
+ test_info.failed = 1;
+ test_info.test = test;
+ test_info.line_no = line_no;
+ test_info.filename = filename;
+}
+
+int hexcmp( uint8_t * a, uint8_t * b, uint32_t a_len, uint32_t b_len)
+{
+ int ret = 0;
+ uint32_t i = 0;
+
+ if ( a_len != b_len )
+ return( a_len - b_len );
+
+ for( i = 0; i < a_len; i++ )
+ {
+ if ( a[i] != b[i] )
+ {
+ ret = -1;
+ break;
+ }
+ }
+ return ret;
+}
+
diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function
new file mode 100644
index 0000000..31f93c6
--- /dev/null
+++ b/tests/suites/host_test.function
@@ -0,0 +1,672 @@
+#line 2 "suites/host_test.function"
+
+/**
+ * \brief Varifies that string is in string parameter format i.e. "<str>"
+ * It also strips enclosing '"' from the input string.
+ *
+ * \param str String parameter.
+ *
+ * \return 0 if success else 1
+ */
+int verify_string( char **str )
+{
+ if( (*str)[0] != '"' ||
+ (*str)[strlen( *str ) - 1] != '"' )
+ {
+ mbedcrypto_fprintf( stderr,
+ "Expected string (with \"\") for parameter and got: %s\n", *str );
+ return( -1 );
+ }
+
+ (*str)++;
+ (*str)[strlen( *str ) - 1] = '\0';
+
+ return( 0 );
+}
+
+/**
+ * \brief Varifies that string is an integer. Also gives the converted
+ * integer value.
+ *
+ * \param str Input string.
+ * \param value Pointer to int for output value.
+ *
+ * \return 0 if success else 1
+ */
+int verify_int( char *str, int *value )
+{
+ size_t i;
+ int minus = 0;
+ int digits = 1;
+ int hex = 0;
+
+ for( i = 0; i < strlen( str ); i++ )
+ {
+ if( i == 0 && str[i] == '-' )
+ {
+ minus = 1;
+ continue;
+ }
+
+ if( ( ( minus && i == 2 ) || ( !minus && i == 1 ) ) &&
+ str[i - 1] == '0' && str[i] == 'x' )
+ {
+ hex = 1;
+ continue;
+ }
+
+ if( ! ( ( str[i] >= '0' && str[i] <= '9' ) ||
+ ( hex && ( ( str[i] >= 'a' && str[i] <= 'f' ) ||
+ ( str[i] >= 'A' && str[i] <= 'F' ) ) ) ) )
+ {
+ digits = 0;
+ break;
+ }
+ }
+
+ if( digits )
+ {
+ if( hex )
+ *value = strtol( str, NULL, 16 );
+ else
+ *value = strtol( str, NULL, 10 );
+
+ return( 0 );
+ }
+
+ mbedcrypto_fprintf( stderr,
+ "Expected integer for parameter and got: %s\n", str );
+ return( KEY_VALUE_MAPPING_NOT_FOUND );
+}
+
+
+/**
+ * \brief Usage string.
+ *
+ */
+#define USAGE \
+ "Usage: %s [OPTIONS] files...\n\n" \
+ " Command line arguments:\n" \
+ " files... One or more test data file. If no file is specified\n" \
+ " the followimg default test case is used:\n" \
+ " %s\n\n" \
+ " Options:\n" \
+ " -v | --verbose Display full information about each test\n" \
+ " -h | --help Display this information\n\n", \
+ argv[0], \
+ "TESTCASE_FILENAME"
+
+
+/**
+ * \brief Read a line from the passed file pointer.
+ *
+ * \param f FILE pointer
+ * \param buf Pointer to memory to hold read line.
+ * \param len Length of the buf.
+ *
+ * \return 0 if success else -1
+ */
+int get_line( FILE *f, char *buf, size_t len )
+{
+ char *ret;
+ int i = 0, str_len = 0, has_string = 0;
+
+ /* Read until we get a valid line */
+ do
+ {
+ ret = fgets( buf, len, f );
+ if( ret == NULL )
+ return( -1 );
+
+ str_len = strlen( buf );
+
+ /* Skip empty line and comment */
+ if ( str_len == 0 || buf[0] == '#' )
+ continue;
+ has_string = 0;
+ for ( i = 0; i < str_len; i++ )
+ {
+ char c = buf[i];
+ if ( c != ' ' && c != '\t' && c != '\n' &&
+ c != '\v' && c != '\f' && c != '\r' )
+ {
+ has_string = 1;
+ break;
+ }
+ }
+ } while( !has_string );
+
+ /* Strip new line and carriage return */
+ ret = buf + strlen( buf );
+ if( ret-- > buf && *ret == '\n' )
+ *ret = '\0';
+ if( ret-- > buf && *ret == '\r' )
+ *ret = '\0';
+
+ return( 0 );
+}
+
+/**
+ * \brief Splits string delimited by ':'. Ignores '\:'.
+ *
+ * \param buf Input string
+ * \param len Input string length
+ * \param params Out params found
+ * \param params_len Out params array len
+ *
+ * \return Count of strings found.
+ */
+static int parse_arguments( char *buf, size_t len, char **params,
+ size_t params_len )
+{
+ size_t cnt = 0, i;
+ char *cur = buf;
+ char *p = buf, *q;
+
+ params[cnt++] = cur;
+
+ while( *p != '\0' && p < buf + len )
+ {
+ if( *p == '\\' )
+ {
+ p++;
+ p++;
+ continue;
+ }
+ if( *p == ':' )
+ {
+ if( p + 1 < buf + len )
+ {
+ cur = p + 1;
+ assert( cnt < params_len );
+ params[cnt++] = cur;
+ }
+ *p = '\0';
+ }
+
+ p++;
+ }
+
+ /* Replace newlines, question marks and colons in strings */
+ for( i = 0; i < cnt; i++ )
+ {
+ p = params[i];
+ q = params[i];
+
+ while( *p != '\0' )
+ {
+ if( *p == '\\' && *(p + 1) == 'n' )
+ {
+ p += 2;
+ *(q++) = '\n';
+ }
+ else if( *p == '\\' && *(p + 1) == ':' )
+ {
+ p += 2;
+ *(q++) = ':';
+ }
+ else if( *p == '\\' && *(p + 1) == '?' )
+ {
+ p += 2;
+ *(q++) = '?';
+ }
+ else
+ *(q++) = *(p++);
+ }
+ *q = '\0';
+ }
+
+ return( cnt );
+}
+
+/**
+ * \brief Converts parameters into test function consumable parameters.
+ * Example: Input: {"int", "0", "char*", "Hello",
+ * "hex", "abef", "exp", "1"}
+ * Output: {
+ * 0, // Verified int
+ * "Hello", // Verified string
+ * 2, { 0xab, 0xef },// Converted len,hex pair
+ * 9600 // Evaluated expression
+ * }
+ *
+ *
+ * \param cnt Input string.
+ * \param params Out array of found strings.
+ * \param int_params_store Memory for storing processed integer parameters.
+ *
+ * \return 0 for success else 1
+ */
+static int convert_params( size_t cnt , char ** params , int * int_params_store )
+{
+ char ** cur = params;
+ char ** out = params;
+ int ret = ( DISPATCH_TEST_SUCCESS );
+
+ while ( cur - params < (int) cnt )
+ {
+ char * type = *cur++;
+ char * val = *cur++;
+
+ if ( strcmp( type, "char*" ) == 0 )
+ {
+ if ( verify_string( &val ) == 0 )
+ {
+ *out++ = val;
+ }
+ else
+ {
+ ret = ( DISPATCH_INVALID_TEST_DATA );
+ break;
+ }
+ }
+ else if ( strcmp( type, "int" ) == 0 )
+ {
+ if ( verify_int ( val, int_params_store ) == 0 )
+ {
+ *out++ = (char *) int_params_store++;
+ }
+ else
+ {
+ ret = ( DISPATCH_INVALID_TEST_DATA );
+ break;
+ }
+ }
+ else if ( strcmp( type, "hex" ) == 0 )
+ {
+ if ( verify_string( &val ) == 0 )
+ {
+ int j;
+ *int_params_store = unhexify( (unsigned char *) val, val );
+ printf ("\n");
+ for (j = 0; j < *int_params_store; j++)
+ printf ("%02x ", (uint8_t)val[j]);
+ printf ("\n len %d\n", *int_params_store);
+ *out++ = val;
+ *out++ = (char *)(int_params_store++);
+ }
+ else
+ {
+ ret = ( DISPATCH_INVALID_TEST_DATA );
+ break;
+ }
+ }
+ else if ( strcmp( type, "exp" ) == 0 )
+ {
+ int exp_id = strtol( val, NULL, 10 );
+ if ( get_expression ( exp_id, int_params_store ) == 0 )
+ {
+ *out++ = (char *)int_params_store++;
+ }
+ else
+ {
+ ret = ( DISPATCH_INVALID_TEST_DATA );
+ break;
+ }
+ }
+ else
+ {
+ ret = ( DISPATCH_INVALID_TEST_DATA );
+ break;
+ }
+ }
+ return( ret );
+}
+
+/**
+ * \brief Tests snprintf implementation with test input.
+ *
+ * \param n Buffer test length.
+ * \param ref_buf Expected buffer.
+ * \param ref_ret Expected snprintf return value.
+ *
+ * \return 0 for success else 1
+ */
+#if defined(__GNUC__)
+/* At high optimization levels (e.g. gcc -O3), this function may be
+ * inlined in run_test_snprintf. This can trigger a spurious warning about
+ * potential misuse of snprintf from gcc -Wformat-truncation (observed with
+ * gcc 7.2). This warning makes tests in run_test_snprintf redundant on gcc
+ * only. They are still valid for other compilers. Avoid this warning by
+ * forbidding inlining of this function by gcc. */
+__attribute__((__noinline__))
+#endif
+static int test_snprintf( size_t n, const char ref_buf[10], int ref_ret )
+{
+ int ret;
+ char buf[10] = "xxxxxxxxx";
+ const char ref[10] = "xxxxxxxxx";
+
+ if( n >= sizeof( buf ) )
+ return( -1 );
+ ret = mbedcrypto_snprintf( buf, n, "%s", "123" );
+ if( ret < 0 || (size_t) ret >= n )
+ ret = -1;
+
+ if( strncmp( ref_buf, buf, sizeof( buf ) ) != 0 ||
+ ref_ret != ret ||
+ memcmp( buf + n, ref + n, sizeof( buf ) - n ) != 0 )
+ {
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+/**
+ * \brief Tests snprintf implementation.
+ *
+ * \param none
+ *
+ * \return 0 for success else 1
+ */
+static int run_test_snprintf( void )
+{
+ return( test_snprintf( 0, "xxxxxxxxx", -1 ) != 0 ||
+ test_snprintf( 1, "", -1 ) != 0 ||
+ test_snprintf( 2, "1", -1 ) != 0 ||
+ test_snprintf( 3, "12", -1 ) != 0 ||
+ test_snprintf( 4, "123", 3 ) != 0 ||
+ test_snprintf( 5, "123", 3 ) != 0 );
+}
+
+
+/**
+ * \brief Desktop implementation of execute_tests().
+ * Parses command line and executes tests from
+ * supplied or default data file.
+ *
+ * \param argc Command line argument count.
+ * \param argv Argument array.
+ *
+ * \return Program exit status.
+ */
+int execute_tests( int argc , const char ** argv )
+{
+ /* Local Configurations and options */
+ const char *default_filename = "DATA_FILE";
+ const char *test_filename = NULL;
+ const char **test_files = NULL;
+ int testfile_count = 0;
+ int option_verbose = 0;
+ int function_id = 0;
+
+ /* Other Local variables */
+ int arg_index = 1;
+ const char *next_arg;
+ int testfile_index, ret, i, cnt;
+ int total_errors = 0, total_tests = 0, total_skipped = 0;
+ FILE *file;
+ char buf[5000];
+ char *params[50];
+ int int_params[50]; // Store for proccessed integer params.
+ void *pointer;
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+ int stdout_fd = -1;
+#endif /* __unix__ || __APPLE__ __MACH__ */
+
+#if defined(MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C) && \
+ !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC)
+ unsigned char alloc_buf[1000000];
+ mbedcrypto_memory_buffer_alloc_init( alloc_buf, sizeof( alloc_buf ) );
+#endif
+
+ /*
+ * The C standard doesn't guarantee that all-bits-0 is the representation
+ * of a NULL pointer. We do however use that in our code for initializing
+ * structures, which should work on every modern platform. Let's be sure.
+ */
+ memset( &pointer, 0, sizeof( void * ) );
+ if( pointer != NULL )
+ {
+ mbedcrypto_fprintf( stderr, "all-bits-zero is not a NULL pointer\n" );
+ return( 1 );
+ }
+
+ /*
+ * Make sure we have a snprintf that correctly zero-terminates
+ */
+ if( run_test_snprintf() != 0 )
+ {
+ mbedcrypto_fprintf( stderr, "the snprintf implementation is broken\n" );
+ return( 1 );
+ }
+
+ while( arg_index < argc )
+ {
+ next_arg = argv[ arg_index ];
+
+ if( strcmp(next_arg, "--verbose" ) == 0 ||
+ strcmp(next_arg, "-v" ) == 0 )
+ {
+ option_verbose = 1;
+ }
+ else if( strcmp(next_arg, "--help" ) == 0 ||
+ strcmp(next_arg, "-h" ) == 0 )
+ {
+ mbedcrypto_fprintf( stdout, USAGE );
+ mbedcrypto_exit( EXIT_SUCCESS );
+ }
+ else
+ {
+ /* Not an option, therefore treat all further arguments as the file
+ * list.
+ */
+ test_files = &argv[ arg_index ];
+ testfile_count = argc - arg_index;
+ }
+
+ arg_index++;
+ }
+
+ /* If no files were specified, assume a default */
+ if ( test_files == NULL || testfile_count == 0 )
+ {
+ test_files = &default_filename;
+ testfile_count = 1;
+ }
+
+ /* Initialize the struct that holds information about the last test */
+ memset( &test_info, 0, sizeof( test_info ) );
+
+ /* Now begin to execute the tests in the testfiles */
+ for ( testfile_index = 0;
+ testfile_index < testfile_count;
+ testfile_index++ )
+ {
+ int unmet_dep_count = 0;
+ char *unmet_dependencies[20];
+
+ test_filename = test_files[ testfile_index ];
+
+ file = fopen( test_filename, "r" );
+ if( file == NULL )
+ {
+ mbedcrypto_fprintf( stderr, "Failed to open test file: %s\n",
+ test_filename );
+ return( 1 );
+ }
+
+ while( !feof( file ) )
+ {
+ if( unmet_dep_count > 0 )
+ {
+ mbedcrypto_fprintf( stderr,
+ "FATAL: Dep count larger than zero at start of loop\n" );
+ mbedcrypto_exit( MBEDCRYPTO_EXIT_FAILURE );
+ }
+ unmet_dep_count = 0;
+
+ if( ( ret = get_line( file, buf, sizeof(buf) ) ) != 0 )
+ break;
+ mbedcrypto_fprintf( stdout, "%s%.66s", test_info.failed ? "\n" : "", buf );
+ mbedcrypto_fprintf( stdout, " " );
+ for( i = strlen( buf ) + 1; i < 67; i++ )
+ mbedcrypto_fprintf( stdout, "." );
+ mbedcrypto_fprintf( stdout, " " );
+ fflush( stdout );
+
+ total_tests++;
+
+ if( ( ret = get_line( file, buf, sizeof( buf ) ) ) != 0 )
+ break;
+ cnt = parse_arguments( buf, strlen( buf ), params,
+ sizeof( params ) / sizeof( params[0] ) );
+
+ if( strcmp( params[0], "depends_on" ) == 0 )
+ {
+ for( i = 1; i < cnt; i++ )
+ {
+ int dep_id = strtol( params[i], NULL, 10 );
+ if( dep_check( dep_id ) != DEPENDENCY_SUPPORTED )
+ {
+ if( 0 == option_verbose )
+ {
+ /* Only one count is needed if not verbose */
+ unmet_dep_count++;
+ break;
+ }
+
+ unmet_dependencies[ unmet_dep_count ] = strdup( params[i] );
+ if( unmet_dependencies[ unmet_dep_count ] == NULL )
+ {
+ mbedcrypto_fprintf( stderr, "FATAL: Out of memory\n" );
+ mbedcrypto_exit( MBEDCRYPTO_EXIT_FAILURE );
+ }
+ unmet_dep_count++;
+ }
+ }
+
+ if( ( ret = get_line( file, buf, sizeof( buf ) ) ) != 0 )
+ break;
+ cnt = parse_arguments( buf, strlen( buf ), params,
+ sizeof( params ) / sizeof( params[0] ) );
+ }
+
+ // If there are no unmet dependencies execute the test
+ if( unmet_dep_count == 0 )
+ {
+ test_info.failed = 0;
+
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+ /* Suppress all output from the library unless we're verbose
+ * mode
+ */
+ if( !option_verbose )
+ {
+ stdout_fd = redirect_output( &stdout, "/dev/null" );
+ if( stdout_fd == -1 )
+ {
+ /* Redirection has failed with no stdout so exit */
+ exit( 1 );
+ }
+ }
+#endif /* __unix__ || __APPLE__ __MACH__ */
+
+ function_id = strtol( params[0], NULL, 10 );
+ if ( (ret = check_test( function_id )) == DISPATCH_TEST_SUCCESS )
+ {
+ ret = convert_params( cnt - 1, params + 1, int_params );
+ if ( DISPATCH_TEST_SUCCESS == ret )
+ {
+ ret = dispatch_test( function_id, (void **)( params + 1 ) );
+ }
+ }
+
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+ if( !option_verbose && restore_output( &stdout, stdout_fd ) )
+ {
+ /* Redirection has failed with no stdout so exit */
+ exit( 1 );
+ }
+#endif /* __unix__ || __APPLE__ __MACH__ */
+
+ }
+
+ if( unmet_dep_count > 0 || ret == DISPATCH_UNSUPPORTED_SUITE )
+ {
+ total_skipped++;
+ mbedcrypto_fprintf( stdout, "----" );
+
+ if( 1 == option_verbose && ret == DISPATCH_UNSUPPORTED_SUITE )
+ {
+ mbedcrypto_fprintf( stdout, "\n Test Suite not enabled" );
+ }
+
+ if( 1 == option_verbose && unmet_dep_count > 0 )
+ {
+ mbedcrypto_fprintf( stdout, "\n Unmet dependencies: " );
+ for( i = 0; i < unmet_dep_count; i++ )
+ {
+ mbedcrypto_fprintf( stdout, "%s ",
+ unmet_dependencies[i] );
+ free( unmet_dependencies[i] );
+ }
+ }
+ mbedcrypto_fprintf( stdout, "\n" );
+ fflush( stdout );
+
+ unmet_dep_count = 0;
+ }
+ else if( ret == DISPATCH_TEST_SUCCESS )
+ {
+ if( test_info.failed == 0 )
+ {
+ mbedcrypto_fprintf( stdout, "PASS\n" );
+ }
+ else
+ {
+ total_errors++;
+ mbedcrypto_fprintf( stdout, "FAILED\n" );
+ mbedcrypto_fprintf( stdout, " %s\n at line %d, %s\n",
+ test_info.test, test_info.line_no,
+ test_info.filename );
+ }
+ fflush( stdout );
+ }
+ else if( ret == DISPATCH_INVALID_TEST_DATA )
+ {
+ mbedcrypto_fprintf( stderr, "FAILED: FATAL PARSE ERROR\n" );
+ fclose( file );
+ mbedcrypto_exit( 2 );
+ }
+ else if( ret == DISPATCH_TEST_FN_NOT_FOUND )
+ {
+ mbedcrypto_fprintf( stderr, "FAILED: FATAL TEST FUNCTION NOT FUND\n" );
+ fclose( file );
+ mbedcrypto_exit( 2 );
+ }
+ else
+ total_errors++;
+ }
+ fclose( file );
+
+ /* In case we encounter early end of file */
+ for( i = 0; i < unmet_dep_count; i++ )
+ free( unmet_dependencies[i] );
+ }
+
+ mbedcrypto_fprintf( stdout, "\n----------------------------------------------------------------------------\n\n");
+ if( total_errors == 0 )
+ mbedcrypto_fprintf( stdout, "PASSED" );
+ else
+ mbedcrypto_fprintf( stdout, "FAILED" );
+
+ mbedcrypto_fprintf( stdout, " (%d / %d tests (%d skipped))\n",
+ total_tests - total_errors, total_tests, total_skipped );
+
+#if defined(MBEDCRYPTO_MEMORY_BUFFER_ALLOC_C) && \
+ !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC)
+#if defined(MBEDCRYPTO_MEMORY_DEBUG)
+ mbedcrypto_memory_buffer_alloc_status();
+#endif
+ mbedcrypto_memory_buffer_alloc_free();
+#endif
+
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+ if( stdout_fd != -1 )
+ close_output( stdout );
+#endif /* __unix__ || __APPLE__ __MACH__ */
+
+ return( total_errors != 0 );
+}
diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function
new file mode 100644
index 0000000..1a070ff
--- /dev/null
+++ b/tests/suites/main_test.function
@@ -0,0 +1,228 @@
+#line 2 "suites/main_test.function"
+/*
+ * *** THIS FILE HAS BEEN MACHINE GENERATED ***
+ *
+ * This file has been machine generated using the script:
+ * {generator_script}
+ *
+ * Test file : {test_file}
+ *
+ * The following files were used to create this file.
+ *
+ * Main code file : {test_main_file}
+ * Platform code file : {test_platform_file}
+ * Helper file : {test_common_helper_file}
+ * Test suite file : {test_case_file}
+ * Test suite data : {test_case_data_file}
+ *
+ *
+ * This file is part of Mbed Crypto (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDCRYPTO_CONFIG_FILE)
+#include <mbedcrypto/config.h>
+#else
+#include MBEDCRYPTO_CONFIG_FILE
+#endif
+
+
+/*----------------------------------------------------------------------------*/
+/* Common helper code */
+
+{test_common_helpers}
+
+#line {line_no} "suites/main_test.function"
+
+
+/*----------------------------------------------------------------------------*/
+/* Test Suite Code */
+
+
+#define TEST_SUITE_ACTIVE
+
+{functions_code}
+
+#line {line_no} "suites/main_test.function"
+
+
+/*----------------------------------------------------------------------------*/
+/* Test dispatch code */
+
+
+/**
+ * \brief Evaluates an expression/macro into its literal integer value.
+ * For optimizing space for embedded targets each expression/macro
+ * is identified by a unique identifier instead of string literals.
+ * Identifiers and evaluation code is generated by script:
+ * {generator_script}
+ *
+ * \param exp_id Expression identifier.
+ * \param out_value Pointer to int to hold the integer.
+ *
+ * \return 0 if exp_id is found. 1 otherwise.
+ */
+int get_expression( int32_t exp_id, int32_t * out_value )
+{{
+ int ret = KEY_VALUE_MAPPING_FOUND;
+
+ (void) exp_id;
+ (void) out_value;
+
+ switch( exp_id )
+ {{
+{expression_code}
+#line {line_no} "suites/main_test.function"
+ default:
+ {{
+ ret = KEY_VALUE_MAPPING_NOT_FOUND;
+ }}
+ break;
+ }}
+ return( ret );
+}}
+
+
+/**
+ * \brief Checks if the dependency i.e. the compile flag is set.
+ * For optimizing space for embedded targets each dependency
+ * is identified by a unique identifier instead of string literals.
+ * Identifiers and check code is generated by script:
+ * {generator_script}
+ *
+ * \param exp_id Dependency identifier.
+ *
+ * \return DEPENDENCY_SUPPORTED if set else DEPENDENCY_NOT_SUPPORTED
+ */
+int dep_check( int dep_id )
+{{
+ int ret = DEPENDENCY_NOT_SUPPORTED;
+
+ (void) dep_id;
+
+ switch( dep_id )
+ {{
+{dep_check_code}
+#line {line_no} "suites/main_test.function"
+ default:
+ break;
+ }}
+ return( ret );
+}}
+
+
+/**
+ * \brief Function pointer type for test function wrappers.
+ *
+ *
+ * \param void ** Pointer to void pointers. Represents an array of test
+ * function parameters.
+ *
+ * \return void
+ */
+typedef void (*TestWrapper_t)( void ** );
+
+
+/**
+ * \brief Table of test function wrappers. Used by dispatch_test().
+ * This table is populated by script:
+ * {generator_script}
+ *
+ */
+TestWrapper_t test_funcs[] =
+{{
+{dispatch_code}
+#line {line_no} "suites/main_test.function"
+}};
+
+
+/**
+ * \brief Dispatches test functions based on function index.
+ *
+ * \param exp_id Test function index.
+ *
+ * \return DISPATCH_TEST_SUCCESS if found
+ * DISPATCH_TEST_FN_NOT_FOUND if not found
+ * DISPATCH_UNSUPPORTED_SUITE if not compile time enabled.
+ */
+int dispatch_test( int func_idx, void ** params )
+{{
+ int ret = DISPATCH_TEST_SUCCESS;
+ TestWrapper_t fp = NULL;
+
+ if ( func_idx < (int)( sizeof(test_funcs)/sizeof( TestWrapper_t ) ) )
+ {{
+ fp = test_funcs[func_idx];
+ if ( fp )
+ fp( params );
+ else
+ ret = ( DISPATCH_UNSUPPORTED_SUITE );
+ }}
+ else
+ {{
+ ret = ( DISPATCH_TEST_FN_NOT_FOUND );
+ }}
+
+ return( ret );
+}}
+
+
+/**
+ * \brief Checks if test function is supported
+ *
+ * \param exp_id Test function index.
+ *
+ * \return DISPATCH_TEST_SUCCESS if found
+ * DISPATCH_TEST_FN_NOT_FOUND if not found
+ * DISPATCH_UNSUPPORTED_SUITE if not compile time enabled.
+ */
+int check_test( int func_idx )
+{{
+ int ret = DISPATCH_TEST_SUCCESS;
+ TestWrapper_t fp = NULL;
+
+ if ( func_idx < (int)( sizeof(test_funcs)/sizeof( TestWrapper_t ) ) )
+ {{
+ fp = test_funcs[func_idx];
+ if ( fp == NULL )
+ ret = ( DISPATCH_UNSUPPORTED_SUITE );
+ }}
+ else
+ {{
+ ret = ( DISPATCH_TEST_FN_NOT_FOUND );
+ }}
+
+ return( ret );
+}}
+
+
+{platform_code}
+
+#line {line_no} "suites/main_test.function"
+
+/*----------------------------------------------------------------------------*/
+/* Main Test code */
+
+
+/**
+ * \brief Program main. Invokes platform specific execute_tests().
+ *
+ * \param argc Command line arguments count.
+ * \param argv Array of command line arguments.
+ *
+ * \return Exit code.
+ */
+int main( int argc, const char *argv[] )
+{{
+ int ret = platform_setup();
+ if( ret != 0 )
+ {{
+ mbedcrypto_fprintf( stderr,
+ "FATAL: Failed to initialize platform - error %d\n",
+ ret );
+ return( -1 );
+ }}
+ ret = execute_tests( argc, argv );
+ platform_teardown();
+ return( ret );
+}}
+
diff --git a/tests/suites/target_test.function b/tests/suites/target_test.function
new file mode 100644
index 0000000..d5cded0
--- /dev/null
+++ b/tests/suites/target_test.function
@@ -0,0 +1,413 @@
+#line 2 "suites/target_test.function"
+
+#include "greentea-client/test_env.h"
+
+/**
+ * \brief Increments pointer and asserts that it does not overflow.
+ *
+ * \param p Pointer to byte array
+ * \param start Pointer to start of byte array
+ * \param len Length of byte array
+ * \param step Increment size
+ *
+ */
+#define INCR_ASSERT(p, start, len, step) do \
+{ \
+ assert( ( p ) >= ( start ) ); \
+ assert( sizeof( *( p ) ) == sizeof( *( start ) ) ); \
+ /* <= is checked to support use inside a loop where \
+ pointer is incremented after reading data. */ \
+ assert( (uint32_t)( ( ( p ) - ( start ) ) + ( step ) ) <= ( len ) );\
+ ( p ) += ( step ); \
+} \
+while( 0 )
+
+
+/**
+ * \brief 4 byte align unsigned char pointer
+ *
+ * \param p Pointer to byte array
+ * \param start Pointer to start of byte array
+ * \param len Length of byte array
+ *
+ */
+#define ALIGN_32BIT(p, start, len) do \
+{ \
+ uint32_t align = ( - (uintptr_t)( p ) ) % 4;\
+ INCR_ASSERT( ( p ), ( start ), ( len ), align);\
+} \
+while( 0 )
+
+
+/**
+ * \brief Verify dependencies. Dependency identifiers are
+ * encoded in the buffer as 8 bit unsigned integers.
+ *
+ * \param count Number of dependencies.
+ * \param dep_p Pointer to buffer.
+ *
+ * \return DEPENDENCY_SUPPORTED if success else DEPENDENCY_NOT_SUPPORTED.
+ */
+int verify_dependencies( uint8_t count, uint8_t * dep_p )
+{
+ uint8_t i;
+ for ( i = 0; i < count; i++ )
+ {
+ if ( dep_check( (int)(dep_p[i]) ) != DEPENDENCY_SUPPORTED )
+ return( DEPENDENCY_NOT_SUPPORTED );
+ }
+ return( DEPENDENCY_SUPPORTED );
+}
+
+
+/**
+ * \brief Receives unsigned integer on serial interface.
+ * Integers are encoded in network order.
+ *
+ * \param none
+ *
+ * \return unsigned int
+ */
+uint32_t receive_uint32()
+{
+ uint32_t value;
+ value = (uint8_t)greentea_getc() << 24;
+ value |= (uint8_t)greentea_getc() << 16;
+ value |= (uint8_t)greentea_getc() << 8;
+ value |= (uint8_t)greentea_getc();
+ return( (uint32_t)value );
+}
+
+/**
+ * \brief Parses out an unsigned 32 int value from the byte array.
+ * Integers are encoded in network order.
+ *
+ * \param p Pointer to byte array
+ *
+ * \return unsigned int
+ */
+uint32_t parse_uint32( uint8_t * p )
+{
+ uint32_t value;
+ value = *p++ << 24;
+ value |= *p++ << 16;
+ value |= *p++ << 8;
+ value |= *p;
+ return( value );
+}
+
+
+/**
+ * \brief Receives test data on serial as greentea key,value pair:
+ * {{<length>;<byte array>}}
+ *
+ * \param data_len Out pointer to hold received data length.
+ *
+ * \return Byte array.
+ */
+uint8_t * receive_data( uint32_t * data_len )
+{
+ uint32_t i = 0, errors = 0;
+ char c;
+ uint8_t * data = NULL;
+
+ /* Read opening braces */
+ i = 0;
+ while ( i < 2 )
+ {
+ c = greentea_getc();
+ /* Ignore any prevous CR LF characters */
+ if ( c == '\n' || c == '\r' )
+ continue;
+ i++;
+ if ( c != '{' )
+ return( NULL );
+ }
+
+ /* Read data length */
+ *data_len = receive_uint32();
+ data = (uint8_t *)malloc( *data_len );
+ assert( data != NULL );
+
+ greentea_getc(); // read ';' received after key i.e. *data_len
+
+ for( i = 0; i < *data_len; i++ )
+ data[i] = greentea_getc();
+
+ /* Read closing braces */
+ for( i = 0; i < 2; i++ )
+ {
+ c = greentea_getc();
+ if ( c != '}' )
+ {
+ errors++;
+ break;
+ }
+ }
+
+ if ( errors )
+ {
+ free( data );
+ data = NULL;
+ *data_len = 0;
+ }
+
+ return( data );
+}
+
+/**
+ * \brief Parse the received byte array and count the number of arguments
+ * to the test function passed as type hex.
+ *
+ * \param count Parameter count
+ * \param data Received Byte array
+ * \param data_len Byte array length
+ *
+ * \return count of hex params
+ */
+uint32_t find_hex_count( uint8_t count, uint8_t * data, uint32_t data_len )
+{
+ uint32_t i = 0, sz = 0;
+ char c;
+ uint8_t * p = NULL;
+ uint32_t hex_count = 0;
+
+ p = data;
+
+ for( i = 0; i < count; i++ )
+ {
+ c = (char)*p;
+ INCR_ASSERT( p, data, data_len, 1 );
+
+ /* Align p to 4 bytes for int, expression, string len or hex length */
+ ALIGN_32BIT( p, data, data_len );
+
+ /* Network to host conversion */
+ sz = (int32_t)parse_uint32( p );
+
+ INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
+
+ if ( c == 'H' || c == 'S' )
+ {
+ INCR_ASSERT( p, data, data_len, sz );
+ hex_count += ( c == 'H' )?1:0;
+ }
+ }
+
+ return( hex_count );
+}
+
+/**
+ * \brief Parses received byte array for test parameters.
+ *
+ * \param count Parameter count
+ * \param data Received Byte array
+ * \param data_len Byte array length
+ * \param error Parsing error out variable.
+ *
+ * \return Array of parsed parameters allocated on heap.
+ * Note: Caller has the responsibility to delete
+ * the memory after use.
+ */
+void ** parse_parameters( uint8_t count, uint8_t * data, uint32_t data_len,
+ int * error )
+{
+ uint32_t i = 0, hex_count = 0;
+ char c;
+ void ** params = NULL;
+ void ** cur = NULL;
+ uint8_t * p = NULL;
+
+ hex_count = find_hex_count(count, data, data_len);
+
+ params = (void **)malloc( sizeof( void *) * ( count + hex_count ) );
+ assert( params != NULL );
+ cur = params;
+
+ p = data;
+
+ /* Parameters */
+ for( i = 0; i < count; i++ )
+ {
+ c = (char)*p;
+ INCR_ASSERT( p, data, data_len, 1 );
+
+ /* Align p to 4 bytes for int, expression, string len or hex length */
+ ALIGN_32BIT( p, data, data_len );
+
+ /* Network to host conversion */
+ *( (int32_t *)p ) = (int32_t)parse_uint32( p );
+
+ switch( c )
+ {
+ case 'E':
+ {
+ if ( get_expression( *( (int32_t *)p ), (int32_t *)p ) )
+ {
+ *error = KEY_VALUE_MAPPING_NOT_FOUND;
+ goto exit;
+ }
+ } /* Intentional fall through */
+ case 'I':
+ {
+ *cur++ = (void *)p;
+ INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
+ }
+ break;
+ case 'H': /* Intentional fall through */
+ case 'S':
+ {
+ uint32_t * sz = (uint32_t *)p;
+ INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
+ *cur++ = (void *)p;
+ if ( c == 'H' )
+ *cur++ = (void *)sz;
+ INCR_ASSERT( p, data, data_len, ( *sz ) );
+ }
+ break;
+ default:
+ {
+ *error = DISPATCH_INVALID_TEST_DATA;
+ goto exit;
+ }
+ break;
+ }
+ }
+
+exit:
+ if ( *error )
+ {
+ free( params );
+ params = NULL;
+ }
+
+ return( params );
+}
+
+/**
+ * \brief Sends greentea key and int value pair to host.
+ *
+ * \param key key string
+ * \param value integer value
+ *
+ * \return void
+ */
+void send_key_integer( char * key, int value )
+{
+ char str[50];
+ snprintf( str, sizeof( str ), "%d", value );
+ greentea_send_kv( key, str );
+}
+
+/**
+ * \brief Sends test setup failure to the host.
+ *
+ * \param failure Test set failure
+ *
+ * \return void
+ */
+void send_failure( int failure )
+{
+ send_key_integer( "F", failure );
+}
+
+/**
+ * \brief Sends test status to the host.
+ *
+ * \param status Test status (PASS=0/FAIL=!0)
+ *
+ * \return void
+ */
+void send_status( int status )
+{
+ send_key_integer( "R", status );
+}
+
+
+/**
+ * \brief Embedded implementation of execute_tests().
+ * Ignores command line and received test data
+ * on serial.
+ *
+ * \param argc not used
+ * \param argv not used
+ *
+ * \return Program exit status.
+ */
+int execute_tests( int args, const char ** argv )
+{
+ int ret = 0;
+ uint32_t data_len = 0;
+ uint8_t count = 0, function_id;
+ void ** params = NULL;
+ uint8_t * data = NULL, * p = NULL;
+
+ GREENTEA_SETUP( 180, "mbedcrypto_test" );
+ greentea_send_kv( "GO", " " );
+
+ while ( 1 )
+ {
+ ret = 0;
+ test_info.failed = 0;
+ data_len = 0;
+
+ data = receive_data( &data_len );
+ if ( data == NULL )
+ continue;
+ p = data;
+
+ do
+ {
+ /* Read dependency count */
+ count = *p;
+ assert( count < data_len );
+ INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
+ ret = verify_dependencies( count, p );
+ if ( ret != DEPENDENCY_SUPPORTED )
+ break;
+
+ if ( count )
+ INCR_ASSERT( p, data, data_len, count );
+
+ /* Read function id */
+ function_id = *p;
+ INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
+ if ( ( ret = check_test( function_id ) ) != DISPATCH_TEST_SUCCESS )
+ break;
+
+ /* Read number of parameters */
+ count = *p;
+ INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
+
+ /* Parse parameters if present */
+ if ( count )
+ {
+ params = parse_parameters( count, p, data_len - ( p - data ), &ret );
+ if ( ret )
+ break;
+ }
+
+ ret = dispatch_test( function_id, params );
+ }
+ while ( 0 );
+
+ if ( data )
+ {
+ free(data);
+ data = NULL;
+ }
+
+ if ( params )
+ {
+ free( params );
+ params = NULL;
+ }
+
+ if ( ret )
+ send_failure( ret );
+ else
+ send_status( test_info.failed );
+ }
+ return( 0 );
+}
+
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
new file mode 100644
index 0000000..4a3dd17
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -0,0 +1,1170 @@
+PSA init/deinit
+init_deinit:
+
+PSA fill 250 slots
+fill_slots:250
+
+PSA import/export raw: 0 bytes
+import_export:"":PSA_KEY_TYPE_RAW_DATA:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_USAGE_EXPORT:0:0:PSA_SUCCESS:1
+
+PSA import/export raw: 1 bytes
+import_export:"2a":PSA_KEY_TYPE_RAW_DATA:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_USAGE_EXPORT:8:0:PSA_SUCCESS:1
+
+PSA import/export raw: 1 bytes, larger buffer
+import_export:"2a":PSA_KEY_TYPE_RAW_DATA:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_USAGE_EXPORT:8:1:PSA_SUCCESS:1
+
+PSA import/export raw: 2 bytes, buffer too small
+import_export:"2a2b":PSA_KEY_TYPE_RAW_DATA:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_USAGE_EXPORT:16:-1:PSA_ERROR_BUFFER_TOO_SMALL:1
+
+PSA import/export AES-128
+depends_on:MBEDCRYPTO_AES_C
+import_export:"0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_AES:PSA_ALG_CTR:PSA_KEY_USAGE_EXPORT:128:0:PSA_SUCCESS:1
+
+PSA import/export AES-192
+depends_on:MBEDCRYPTO_AES_C
+import_export:"0123456789abcdef0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_AES:PSA_ALG_CTR:PSA_KEY_USAGE_EXPORT:192:0:PSA_SUCCESS:1
+
+PSA import/export AES-256
+depends_on:MBEDCRYPTO_AES_C
+import_export:"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_AES:PSA_ALG_CTR:PSA_KEY_USAGE_EXPORT:256:0:PSA_SUCCESS:1
+
+PSA import AES: bad key size
+depends_on:MBEDCRYPTO_AES_C
+import:"0123456789abcdef":PSA_KEY_TYPE_AES:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import/export RSA public key: good, 1024-bit
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:0:PSA_SUCCESS:1
+
+PSA import/export RSA public key: good, larger buffer (+1 byte)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:1:PSA_SUCCESS:1
+
+PSA import/export RSA public key: good, larger buffer (*2-1)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:161:PSA_SUCCESS:1
+
+PSA import/export RSA public key: good, larger buffer (*2)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:162:PSA_SUCCESS:1
+
+PSA import/export RSA public key: good, larger buffer (*2+1)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:163:PSA_SUCCESS:1
+
+PSA import/export RSA public key: export buffer too small
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:-1:PSA_ERROR_BUFFER_TOO_SMALL:1
+
+PSA import/export RSA keypair: good, 1024-bit
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:0:PSA_SUCCESS:1
+
+PSA import/export RSA keypair: good, larger buffer (+1 byte)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:1:PSA_SUCCESS:1
+
+PSA import/export RSA keypair: good, larger buffer (*2-1)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:609:PSA_SUCCESS:1
+
+PSA import/export RSA keypair: good, larger buffer (*2)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:610:PSA_SUCCESS:1
+
+PSA import/export RSA keypair: good, larger buffer (*2+1)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:611:PSA_SUCCESS:1
+
+PSA import/export RSA keypair: export buffer too small
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:-1:PSA_ERROR_BUFFER_TOO_SMALL:1
+
+PSA import/export RSA keypair: trailing garbage ignored
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b2400":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1024:-1:PSA_SUCCESS:0
+
+PSA import RSA keypair: truncated
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C
+import:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import RSA keypair: public key
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C
+import:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import RSA public key: key pair
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C
+import:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import RSA keypair: valid key but EC
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C
+import:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import/export RSA keypair: good, 1023-bit
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export:"3082025a0201000281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001028180491b277413fb35efe82dace68b544a9dd6aa8917d329731955ec66ec3b0178fcf5a29196e1a6c093bf6c8064b36a8f0d9840a78003d11392754a70a77788975515a1442a6c806cafa2f07fe99cac78a86fa868888d654cec4baf205352cf8255acaa47e2455f23b58c0e5ae43fa297bbffe5b970caa80f71e82084fd35425479024100ef27f3fb2df90ac4910ed95fdde4877d09b0dc4e95079f12a7e2041300a8884a39372a1c79691338cd5c3965bcf3a24f2ce9e10de19d4cb87c7546d60ca0aa0d024073e9e1283475e9ab3075da0b005ca7c7b05e76325f8deb648238831c8353041d594307f784cd527cfee9187b997713d71c0ff98f01beac4d1a85583be52e90e302402f0c801e311c2677274671933f96fee4a56c6adaf6ccaa09c4875d5fd3a8542fadf3e14ffabea62e6d90302688b6b17ebc0a42e1353a79e66d6db102d9371e5d02406731ef3c8607fbf266806590a9cfd3a79a435ee355e2d9906fc6b4236c5f3a288ed178844a7d295512f49ed15b3d82325e4f729478af3262aa9bd083f273d49502410090a32c0e8ca3bcd4c66f092cdc369cd1abb4a05b9a6f0e65e5a51da1d96d5aca8c1525b3f11322c0588062fc8592ebf25b7950f918d39018e82b8acccc8f7e7a":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_EXPORT:1023:0:PSA_SUCCESS:1
+
+PSA import/export-public RSA public key: good, 1024-bit
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export_public_key:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:162:PSA_SUCCESS
+
+PSA import/export-public RSA keypair: good, 1024-bit
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export_public_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:162:PSA_SUCCESS
+
+PSA import/export-public: cannot export-public a symmetric key
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_RSA_C
+import_export_public_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:128:0:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import/export EC secp256r1: good
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED
+import_export:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:256:0:PSA_SUCCESS:1
+
+PSA import/export EC secp384r1: good
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_PK_WRITE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED
+import_export:"3081a402010104303f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76aa00706052b81040022a16403620004d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1):PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_EXPORT:384:0:PSA_SUCCESS:1
+
+PSA import/export AES key: policy forbids export
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR
+import_export:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:128:0:PSA_ERROR_NOT_PERMITTED:1
+
+PSA import/export HMAC key: policy forbids export
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+import_export:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_HMAC:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:256:0:PSA_ERROR_NOT_PERMITTED:1
+
+PSA import/export RSA keypair: policy forbids export (crypt)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:1024:0:PSA_ERROR_NOT_PERMITTED:1
+
+PSA import/export RSA keypair: policy forbids export (sign)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:1024:0:PSA_ERROR_NOT_PERMITTED:1
+
+PSA import EC keypair secp384r1: valid key but wrong curve (secp256r1)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED
+import:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1):PSA_ERROR_INVALID_ARGUMENT
+
+PSA import EC keypair brainpool384r1: valid key but wrong curve (secp384r1)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_BP384R1_ENABLED:MBEDCRYPTO_ECP_DP_SECP384R1_ENABLED
+import:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P384R1):PSA_ERROR_INVALID_ARGUMENT
+
+PSA import EC keypair: public key
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED
+import:"3059301306072a8648ce3d020106082a8648ce3d03010703420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):PSA_ERROR_INVALID_ARGUMENT
+
+PSA import EC public key: key pair
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED
+# For consistency with ECpub as ECpair, RSApub as RSApair and RSApair as RSApub,
+# one would expect the status to be PSA_ERROR_INVALID_ARGUMENT. But the
+# Mbed Crypto pkparse module returns MBEDCRYPTO_ERR_PK_INVALID_ALG, I think because
+# it's looking for an OID where there is no OID.
+import:"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):PSA_ERROR_NOT_SUPPORTED
+
+PSA import EC keypair: valid key but RSA
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_BP512R1_ENABLED:MBEDCRYPTO_RSA_C
+import:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):PSA_ERROR_INVALID_ARGUMENT
+
+PSA import RSA key pair: maximum size exceeded
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C
+import_rsa_made_up:PSA_VENDOR_RSA_MAX_KEY_BITS+8:1:PSA_ERROR_NOT_SUPPORTED
+
+PSA import RSA public key: maximum size exceeded
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C
+import_rsa_made_up:PSA_VENDOR_RSA_MAX_KEY_BITS+8:0:PSA_ERROR_NOT_SUPPORTED
+
+PSA key policy set and get
+key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE
+
+PSA key policy: MAC, sign | verify
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256)
+
+PSA key policy: MAC, wrong algorithm
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_224)
+
+PSA key policy: MAC, sign but not verify
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_key_policy:PSA_KEY_USAGE_SIGN:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256)
+
+PSA key policy: MAC, verify but not sign
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_key_policy:PSA_KEY_USAGE_VERIFY:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256)
+
+PSA key policy: MAC, neither sign nor verify
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_key_policy:0:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256)
+
+PSA key policy: cipher, encrypt | decrypt
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR
+cipher_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CTR
+
+PSA key policy: cipher, wrong algorithm
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE
+
+PSA key policy: cipher, encrypt but not decrypt
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR
+cipher_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CTR
+
+PSA key policy: cipher, decrypt but not encrypt
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR
+cipher_key_policy:PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CTR
+
+PSA key policy: cipher, neither encrypt nor decrypt
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR
+cipher_key_policy:0:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CTR
+
+PSA key policy: AEAD, encrypt | decrypt
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM
+
+PSA key policy: AEAD, wrong algorithm
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C:MBEDCRYPTO_GCM_C
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":16:16:PSA_ALG_GCM
+
+PSA key policy: AEAD, encrypt but not decrypt
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM
+
+PSA key policy: AEAD, decrypt but not encrypt
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_key_policy:PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM
+
+PSA key policy: AEAD, neither encrypt nor decrypt
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_key_policy:0:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM
+
+PSA key policy: asymmetric encryption, encrypt | decrypt
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encryption_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_CRYPT
+
+PSA key policy: asymmetric encryption, wrong algorithm
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_encryption_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
+
+PSA key policy: asymmetric encryption, encrypt but not decrypt
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encryption_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_CRYPT
+
+PSA key policy: asymmetric encryption, decrypt but not encrypt
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encryption_key_policy:PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_CRYPT
+
+PSA key policy: asymmetric encryption, neither encrypt nor decrypt
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encryption_key_policy:0:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_CRYPT
+
+PSA key policy: asymmetric signature, sign | verify
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW
+
+PSA key policy: asymmetric signature, wrong algorithm
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_SHA256_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS(PSA_ALG_SHA_224)
+
+PSA key policy: asymmetric signature, sign but not verify
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW
+
+PSA key policy: asymmetric signature, verify but not sign
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_signature_key_policy:PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW
+
+PSA key policy: asymmetric signature, neither sign nor verify
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_signature_key_policy:0:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEYPAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW
+
+PSA key policy: derive, permitted
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HKDF(PSA_ALG_SHA_256)
+
+PSA key policy: derive, not permitted
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_key_policy:0:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HKDF(PSA_ALG_SHA_256)
+
+PSA key policy: derive, wrong algorithm
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HKDF(PSA_ALG_SHA_224)
+
+PSA key lifetime: set and get volatile
+key_lifetime:PSA_KEY_LIFETIME_VOLATILE
+
+PSA key lifetime set: invalid key slot
+key_lifetime_set_fail:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
+
+PSA key lifetime set: cannot change write_once lifetime
+key_lifetime_set_fail:1:PSA_KEY_LIFETIME_WRITE_ONCE:PSA_ERROR_NOT_SUPPORTED
+
+PSA key lifetime set: invalid key lifetime value
+key_lifetime_set_fail:1:PSA_KEY_LIFETIME_PERSISTENT+1:PSA_ERROR_INVALID_ARGUMENT
+
+PSA hash setup: good, SHA-256
+depends_on:MBEDCRYPTO_SHA256_C
+hash_setup:PSA_ALG_SHA_256:PSA_SUCCESS
+
+PSA hash setup: bad (unknown hash algorithm)
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+hash_setup:PSA_ALG_CATEGORY_HASH:PSA_ERROR_NOT_SUPPORTED
+
+PSA hash setup: bad (not a hash algorithm)
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+hash_setup:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_INVALID_ARGUMENT
+
+PSA hash finish: SHA-256
+depends_on:MBEDCRYPTO_SHA256_C
+hash_finish:PSA_ALG_SHA_256:"bd":"68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b"
+
+PSA hash verify: SHA-256
+depends_on:MBEDCRYPTO_SHA256_C
+hash_verify:PSA_ALG_SHA_256:"bd":"68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b"
+
+PSA MAC setup: good, HMAC-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_SUCCESS
+
+PSA MAC setup: good, AES-CMAC
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CMAC_C
+mac_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CMAC:PSA_SUCCESS
+
+PSA MAC setup: bad algorithm (unknown MAC algorithm)
+depends_on:MBEDCRYPTO_MD_C
+mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_HMAC(0):PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC setup: bad algorithm (not a MAC algorithm)
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+mac_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_ERROR_INVALID_ARGUMENT
+
+PSA MAC setup: invalid key type, HMAC-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_setup:PSA_KEY_TYPE_RAW_DATA:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_INVALID_ARGUMENT
+
+PSA MAC setup: incompatible key HMAC for CMAC
+depends_on:MBEDCRYPTO_CMAC_C
+# Either INVALID_ARGUMENT or NOT_SUPPORTED would be reasonable here
+mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CMAC:PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC verify: HMAC-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_HMAC(PSA_ALG_SHA_256):"53616d706c65206d65737361676520666f72206b65796c656e3d626c6f636b6c656e":"8bb9a1db9806f20df7f77b82138c7914d174d59e13dc4d0169c9057b133e1d62"
+
+PSA MAC verify: RFC4231 Test case 1 - HMAC-SHA-224
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22"
+
+PSA MAC verify: RFC4231 Test case 1 - HMAC-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_256):"4869205468657265":"b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"
+
+PSA MAC verify: RFC4231 Test case 1 - HMAC-SHA-384
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_384):"4869205468657265":"afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6"
+
+PSA MAC verify: RFC4231 Test case 1 - HMAC-SHA-512
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_512):"4869205468657265":"87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"
+
+PSA MAC verify: RFC4231 Test case 2 - HMAC-SHA-224
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"4a656665":PSA_ALG_HMAC(PSA_ALG_SHA_224):"7768617420646f2079612077616e7420666f72206e6f7468696e673f":"a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44"
+
+PSA MAC verify: RFC4231 Test case 2 - HMAC-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"4a656665":PSA_ALG_HMAC(PSA_ALG_SHA_256):"7768617420646f2079612077616e7420666f72206e6f7468696e673f":"5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"
+
+PSA MAC verify: RFC4231 Test case 2 - HMAC-SHA-384
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"4a656665":PSA_ALG_HMAC(PSA_ALG_SHA_384):"7768617420646f2079612077616e7420666f72206e6f7468696e673f":"af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649"
+
+PSA MAC verify: RFC4231 Test case 2 - HMAC-SHA-512
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"4a656665":PSA_ALG_HMAC(PSA_ALG_SHA_512):"7768617420646f2079612077616e7420666f72206e6f7468696e673f":"164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737"
+
+PSA MAC verify: RFC4231 Test case 3 - HMAC-SHA-224
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_224):"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd":"7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea"
+
+PSA MAC verify: RFC4231 Test case 3 - HMAC-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd":"773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"
+
+PSA MAC verify: RFC4231 Test case 3 - HMAC-SHA-384
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_384):"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd":"88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27"
+
+PSA MAC verify: RFC4231 Test case 3 - HMAC-SHA-512
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_512):"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd":"fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb"
+
+PSA MAC verify: RFC4231 Test case 4 - HMAC-SHA-224
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"0102030405060708090a0b0c0d0e0f10111213141516171819":PSA_ALG_HMAC(PSA_ALG_SHA_224):"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd":"6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a"
+
+PSA MAC verify: RFC4231 Test case 4 - HMAC-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"0102030405060708090a0b0c0d0e0f10111213141516171819":PSA_ALG_HMAC(PSA_ALG_SHA_256):"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd":"82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"
+
+PSA MAC verify: RFC4231 Test case 4 - HMAC-SHA-384
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"0102030405060708090a0b0c0d0e0f10111213141516171819":PSA_ALG_HMAC(PSA_ALG_SHA_384):"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd":"3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb"
+
+PSA MAC verify: RFC4231 Test case 4 - HMAC-SHA-512
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"0102030405060708090a0b0c0d0e0f10111213141516171819":PSA_ALG_HMAC(PSA_ALG_SHA_512):"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd":"b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd"
+
+PSA MAC verify: RFC4231 Test case 6 - HMAC-SHA-224
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_224):"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374":"95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e"
+
+PSA MAC verify: RFC4231 Test case 6 - HMAC-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374":"60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"
+
+PSA MAC verify: RFC4231 Test case 6 - HMAC-SHA-384
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_384):"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374":"4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952"
+
+PSA MAC verify: RFC4231 Test case 6 - HMAC-SHA-512
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_512):"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374":"80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598"
+
+PSA MAC verify: RFC4231 Test case 7 - HMAC-SHA-224
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_224):"5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e":"3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1"
+
+PSA MAC verify: RFC4231 Test case 7 - HMAC-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):"5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e":"9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"
+
+PSA MAC verify: RFC4231 Test case 7 - HMAC-SHA-384
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_384):"5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e":"6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e"
+
+PSA MAC verify: RFC4231 Test case 7 - HMAC-SHA-512
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA512_C
+mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_512):"5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e":"e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"
+
+PSA MAC verify: CMAC-AES-128
+depends_on:MBEDCRYPTO_CMAC_C:MBEDCRYPTO_AES_C
+mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827"
+
+PSA cipher setup: good, AES-CTR
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR
+cipher_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CTR:PSA_SUCCESS
+
+PSA cipher setup: bad algorithm (unknown cipher algorithm)
+depends_on:MBEDCRYPTO_AES_C
+cipher_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CATEGORY_CIPHER:PSA_ERROR_NOT_SUPPORTED
+
+PSA cipher setup: bad algorithm (not a cipher algorithm)
+depends_on:MBEDCRYPTO_AES_C
+cipher_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CMAC:PSA_ERROR_INVALID_ARGUMENT
+
+PSA cipher setup: invalid key type, CTR
+depends_on:MBEDCRYPTO_CIPHER_MODE_CTR
+# Either INVALID_ARGUMENT or NOT_SUPPORTED would be reasonable here
+cipher_setup:PSA_KEY_TYPE_RAW_DATA:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CTR:PSA_ERROR_NOT_SUPPORTED
+
+PSA cipher setup: incompatible key ARC4 for CTR
+depends_on:MBEDCRYPTO_ARC4_C:MBEDCRYPTO_CIPHER_MODE_CTR
+# Either INVALID_ARGUMENT or NOT_SUPPORTED would be reasonable here
+cipher_setup:PSA_KEY_TYPE_ARC4:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CTR:PSA_ERROR_NOT_SUPPORTED
+
+PSA symmetric encrypt: AES-CBC-nopad, 16 bytes, good
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":"a076ec9dfbe47d52afc357336f20743b":PSA_SUCCESS
+
+PSA symmetric encrypt: AES-CBC-PKCS#7, 16 bytes, good
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":"a076ec9dfbe47d52afc357336f20743bca7e8a15dc3c776436314293031cd4f3":PSA_SUCCESS
+
+PSA symmetric encrypt: AES-CBC-PKCS#7, 15 bytes, good
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317":"6279b49d7f7a8dd87b685175d4276e24":PSA_SUCCESS
+
+PSA symmetric encrypt: AES-CBC-nopad, input too short
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee223":"6bc1bee223":PSA_ERROR_INVALID_ARGUMENT
+
+PSA symmetric encrypt: AES-CTR, 16 bytes, good
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC:MBEDCRYPTO_CIPHER_MODE_CTR
+cipher_encrypt:PSA_ALG_CTR | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS
+
+PSA symmetric encrypt: AES-CTR, 15 bytes, good
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC:MBEDCRYPTO_CIPHER_MODE_CTR
+cipher_encrypt:PSA_ALG_CTR | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS
+
+PSA symmetric encrypt: DES-CBC-nopad, 8 bytes, good
+depends_on:MBEDCRYPTO_DES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_DES:"01020407080b0d0e":"eda4011239bc3ac9":"64f917b0152f8f05":PSA_SUCCESS
+
+PSA symmetric encrypt: 2-key 3DES-CBC-nopad, 8 bytes, good
+depends_on:MBEDCRYPTO_DES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"eda4011239bc3ac9":"5d0652429c5b0ac7":PSA_SUCCESS
+
+PSA symmetric encrypt: 3-key 3DES-CBC-nopad, 8 bytes, good
+depends_on:MBEDCRYPTO_DES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"eda4011239bc3ac9":"817ca7d69b80d86a":PSA_SUCCESS
+
+PSA symmetric decrypt: AES-CBC-nopad, 16 bytes, good
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"396ee84fb75fdbb5c2b13c7fe5a654aa":"49e4e66c89a86b67758df89db9ad6955":PSA_SUCCESS
+
+PSA symmetric decrypt: AES-CBC-PKCS#7, 16 bytes, good
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"a076ec9dfbe47d52afc357336f20743bca7e8a15dc3c776436314293031cd4f3":"6bc1bee22e409f96e93d7e117393172a":PSA_SUCCESS
+
+PSA symmetric decrypt: AES-CBC-PKCS#7, 15 bytes, good
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6279b49d7f7a8dd87b685175d4276e24":"6bc1bee22e409f96e93d7e11739317":PSA_SUCCESS
+
+PSA symmetric decrypt: AES-CBC-PKCS#7, input too short (15 bytes)
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317":"49e4e66c89a86b67758df89db9ad6955":PSA_ERROR_BAD_STATE
+
+PSA symmetric decrypt: AES-CTR, 16 bytes, good
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC:MBEDCRYPTO_CIPHER_MODE_CTR
+cipher_decrypt:PSA_ALG_CTR | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":PSA_SUCCESS
+
+PSA symmetric decrypt: AES-CBC-nopad, input too short (5 bytes)
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee223":"6bc1bee223":PSA_ERROR_BAD_STATE
+
+PSA symmetric decrypt: DES-CBC-nopad, 8 bytes, good
+depends_on:MBEDCRYPTO_DES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_DES:"01020407080b0d0e":"64f917b0152f8f05":"eda4011239bc3ac9":PSA_SUCCESS
+
+PSA symmetric decrypt: 2-key 3DES-CBC-nopad, 8 bytes, good
+depends_on:MBEDCRYPTO_DES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"5d0652429c5b0ac7":"eda4011239bc3ac9":PSA_SUCCESS
+
+PSA symmetric decrypt: 3-key 3DES-CBC-nopad, 8 bytes, good
+depends_on:MBEDCRYPTO_DES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"817ca7d69b80d86a":"eda4011239bc3ac9":PSA_SUCCESS
+
+PSA symmetric encrypt/decrypt: AES-CBC-nopad, 16 bytes, good
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_verify_output:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
+
+PSA symmetric encrypt/decrypt: AES-CBC-PKCS#7, 16 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC:MBEDCRYPTO_CIPHER_PADDING_PKCS7
+cipher_verify_output:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
+
+PSA symmetric encrypt/decrypt: AES-CBC-PKCS#7, 15 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC:MBEDCRYPTO_CIPHER_PADDING_PKCS7
+cipher_verify_output:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317"
+
+PSA symmetric encrypt/decrypt: AES-CTR
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR
+cipher_verify_output:PSA_ALG_CTR | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
+
+PSA symmetric encryption multipart: AES-CBC-nopad, 7+9 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt_multipart:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":7:"a076ec9dfbe47d52afc357336f20743b"
+
+PSA symmetric encryption multipart: AES-CBC-nopad, 3+13 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt_multipart:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":3:"a076ec9dfbe47d52afc357336f20743b"
+
+PSA symmetric encryption multipart: AES-CBC-nopad, 4+12 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt_multipart:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":4:"a076ec9dfbe47d52afc357336f20743b"
+
+PSA symmetric encryption multipart: AES-CBC-nopad, 11+5 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_encrypt_multipart:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":11:"a076ec9dfbe47d52afc357336f20743b"
+
+PSA symmetric decryption multipart: AES-CBC-nopad, 7+9 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt_multipart:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"a076ec9dfbe47d52afc357336f20743b":7:"6bc1bee22e409f96e93d7e117393172a"
+
+PSA symmetric decryption multipart: AES-CBC-nopad, 3+13 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt_multipart:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"a076ec9dfbe47d52afc357336f20743b":3:"6bc1bee22e409f96e93d7e117393172a"
+
+PSA symmetric decryption multipart: AES-CBC-nopad, 11+5 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_decrypt_multipart:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"a076ec9dfbe47d52afc357336f20743b":11:"6bc1bee22e409f96e93d7e117393172a"
+
+PSA symmetric encrypt/decrypt multipart: AES-CBC-nopad, 11+5 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+cipher_verify_output_multipart:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"a076ec9dfbe47d52afc357336f20743b":11
+
+PSA symmetric encrypt/decrypt multipart: AES-CBC-PKCS#7 padding, 4+12 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CBC:MBEDCRYPTO_CIPHER_PADDING_PKCS7
+cipher_verify_output_multipart:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"a076ec9dfbe47d52afc357336f20743b":4
+
+PSA AEAD encrypt/decrypt: AES-CCM, 19 bytes #1
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":PSA_ALG_CCM:"0C0D0E0F101112131415161718191A1B1C1D1E":"000102030405060708090A0B":"000102030405060708090A0B":PSA_SUCCESS
+
+PSA AEAD encrypt/decrypt: AES-CCM, 19 bytes #2
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"B96B49E21D621741632875DB7F6C9243D2D7C2":"000102030405060708090A0B":"EC46BB63B02520C33C49FD70":PSA_SUCCESS
+
+PSA AEAD encrypt/decrypt: DES-CCM not supported
+depends_on:MBEDCRYPTO_DES_C:MBEDCRYPTO_CCM_C
+aead_encrypt_decrypt:PSA_KEY_TYPE_DES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"B96B49E21D621741632875DB7F6C9243D2D7C2":"000102030405060708090A0B":"EC46BB63B02520C33C49FD70":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD encrypt: AES-CCM, 23 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":"0BE1A88BACE018B1":"00412B4EA9CDBE3C9696766CFA":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8"
+
+PSA AEAD encrypt: AES-CCM, 24 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"48c0906930561e0ab0ef4cd972":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9"
+
+PSA AEAD decrypt: AES-CCM, 39 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"0BE1A88BACE018B1":"00412B4EA9CDBE3C9696766CFA":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_SUCCESS
+
+PSA AEAD decrypt, AES-CCM, 40 bytes
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"48c0906930561e0ab0ef4cd972":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
+
+PSA AEAD decrypt: AES-CCM, invalid signature
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"26d56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"48c0906930561e0ab0ef4cd972":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_SIGNATURE
+
+PSA AEAD encrypt/decrypt, AES-GCM, 19 bytes #1
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_GCM_C
+aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":PSA_ALG_GCM:"0C0D0E0F101112131415161718191A1B1C1D1E":"000102030405060708090A0B0C0D0E0F":"000102030405060708090A0B":PSA_SUCCESS
+
+PSA AEAD encrypt/decrypt, AES GCM, 19 bytes #2
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_GCM_C
+aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_GCM:"B96B49E21D621741632875DB7F6C9243D2D7C2":"000102030405060708090A0B0C0D0E0F":"EC46BB63B02520C33C49FD70":PSA_SUCCESS
+
+PSA AEAD encrypt, AES-GCM, 128 bytes #1
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_GCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"00e440846db73a490573deaf3728c94f":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96"
+
+PSA AEAD encrypt, AES-GCM, 128 bytes #2
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_GCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"194c8bbbfae4a671386b8cd38f390f46f9df6b8661b470c310921a1c858a938045834bb10380037fbf5f5e00688554537be0fcafe8270b9b59068fa056ab1268fc166c2d729243a06650a171c929c7845c85330c04568d62977eedf3b1ba9dca13bdb8f9522817c8cb99e635e37465ec1c9f6f148d51437aa9f994a62e1bd013":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"97ce3f848276783599c6875de324361e":"12495120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f6bac793bdc2190a195122c98544ccf56"
+
+PSA AEAD decrypt, AES-GCM, 144 bytes #1
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_GCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"00e440846db73a490573deaf3728c94f":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
+
+PSA AEAD decrypt, AES-GCM, 144 bytes #2
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_GCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"12495120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f6bac793bdc2190a195122c98544ccf56":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"97ce3f848276783599c6875de324361e":"194c8bbbfae4a671386b8cd38f390f46f9df6b8661b470c310921a1c858a938045834bb10380037fbf5f5e00688554537be0fcafe8270b9b59068fa056ab1268fc166c2d729243a06650a171c929c7845c85330c04568d62977eedf3b1ba9dca13bdb8f9522817c8cb99e635e37465ec1c9f6f148d51437aa9f994a62e1bd013":PSA_SUCCESS
+
+PSA AEAD decrypt, AES-GCM, invalid signature
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_GCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"12195120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f6bac793bdc2190a195122c98544ccf56":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"97ce3f848276783599c6875de324361e":"194c8bbbfae4a671386b8cd38f390f46f9df6b8661b470c310921a1c858a938045834bb10380037fbf5f5e00688554537be0fcafe8270b9b59068fa056ab1268fc166c2d729243a06650a171c929c7845c85330c04568d62977eedf3b1ba9dca13bdb8f9522817c8cb99e635e37465ec1c9f6f148d51437aa9f994a62e1bd013":PSA_ERROR_INVALID_SIGNATURE
+
+PSA AEAD encrypt/decrypt: invalid algorithm (CTR)
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_GCM_C
+aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CTR:"B96B49E21D621741632875DB7F6C9243D2D7C2":"000102030405060708090A0B0C0D0E0F":"EC46BB63B02520C33C49FD70":PSA_ERROR_NOT_SUPPORTED
+
+PSA signature size: RSA keypair, 1024 bits, PKCS#1 v1.5 raw
+signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:128
+
+PSA signature size: RSA public key, 1024 bits, PKCS#1 v1.5 raw
+signature_size:PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:128
+
+PSA signature size: RSA keypair, 1024 bits, PKCS#1 v1.5 SHA-256
+signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):128
+
+PSA signature size: RSA keypair, 1024 bits, PSS
+signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_ALG_RSA_PSS( PSA_ALG_SHA_256 ):128
+
+PSA signature size: RSA keypair, 1023 bits, PKCS#1 v1.5 raw
+signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1023:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:128
+
+PSA signature size: RSA keypair, 1025 bits, PKCS#1 v1.5 raw
+signature_size:PSA_KEY_TYPE_RSA_KEYPAIR:1025:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:129
+
+PSA import/exercise RSA keypair, PKCS#1 v1.5 raw
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+import_and_exercise_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW
+
+PSA import/exercise: ECP SECP256R1 keypair, ECDSA
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_C
+import_and_exercise_key:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_ALG_ECDSA_ANY
+
+PSA import/exercise: ECP SECP256R1 keypair, deterministic ECDSA
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_C:MBEDCRYPTO_ECDSA_DETERMINISTIC:MBEDCRYPTO_SHA256_C
+import_and_exercise_key:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 )
+
+PSA sign: RSA PKCS#1 v1.5, raw
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+sign_deterministic:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263":"2c7744983f023ac7bb1c55529d83ed11a76a7898a1bb5ce191375a4aa7495a633d27879ff58eba5a57371c34feb1180e8b850d552476ebb5634df620261992f12ebee9097041dbbea85a42d45b344be5073ceb772ffc604954b9158ba81ec3dc4d9d65e3ab7aa318165f38c36f841f1c69cb1cfa494aa5cbb4d6c0efbafb043a"
+
+PSA sign: RSA PKCS#1 v1.5 SHA-256
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15:MBEDCRYPTO_SHA256_C
+sign_deterministic:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
+
+PSA sign: deterministic ECDSA SECP256R1 SHA-256
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_DETERMINISTIC:MBEDCRYPTO_SHA256_C:MBEDCRYPTO_ECDSA_C
+sign_deterministic:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
+
+PSA sign: RSA PKCS#1 v1.5 SHA-256, wrong hash size
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15:MBEDCRYPTO_SHA256_C
+sign_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015":128:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign: RSA PKCS#1 v1.5 raw, input too large
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+sign_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":128:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign: RSA PKCS#1 v1.5 SHA-256, output buffer too small
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15:MBEDCRYPTO_SHA256_C
+sign_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":127:PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA sign: deterministic ECDSA SECP256R1 SHA-256, output buffer too small
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_SHA256_C:MBEDCRYPTO_ECDSA_C
+sign_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":63:PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA sign: deterministic ECDSA SECP256R1, invalid hash
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_DETERMINISTIC:MBEDCRYPTO_SHA256_C
+sign_fail:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( 0 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign/verify: RSA PKCS#1 v1.5, raw
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+sign_verify:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263"
+
+PSA sign/verify: RSA PKCS#1 v1.5 SHA-256
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15:MBEDCRYPTO_SHA256_C
+sign_verify:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
+
+PSA sign/verify: RSA PSS SHA-256, 0 bytes
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+sign_verify:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):""
+
+PSA sign/verify: RSA PSS SHA-256, 32 bytes (hash size)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+sign_verify:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
+
+PSA sign/verify: RSA PSS SHA-256, 129 bytes
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+sign_verify:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+PSA sign/verify: randomized ECDSA SECP256R1 SHA-256
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_C
+sign_verify:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+
+PSA sign/verify: deterministic ECDSA SECP256R1 SHA-256
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_DETERMINISTIC:MBEDCRYPTO_SHA256_C:MBEDCRYPTO_ECDSA_C
+sign_verify:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+
+PSA verify: RSA PKCS#1 v1.5 SHA-256, good signature
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15:MBEDCRYPTO_SHA256_C
+asymmetric_verify:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
+
+PSA verify with keypair: RSA PKCS#1 v1.5 SHA-256, good signature
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15:MBEDCRYPTO_SHA256_C
+asymmetric_verify:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
+
+PSA verify: RSA PKCS#1 v1.5 SHA-256, wrong hash
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15:MBEDCRYPTO_SHA1_C
+asymmetric_verify_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_1):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_ARGUMENT
+
+PSA verify: RSA PKCS#1 v1.5 SHA-256, wrong signature
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15:MBEDCRYPTO_SHA256_C
+asymmetric_verify_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"111164d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify: RSA PSS SHA-256, good signature, 0 bytes
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_verify:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"":"34c011b625c32d992f4ab8fcfa52b616ea66270b5b75a4fc71af712f9b8806bcdd374ce50eafcbb489562b93347885f93c2de1d404c45cacccefceb112ff6ffdfe4264f91d66320bbbe09304b851b8ad6280bbccc571eebcd49c7db5dfa399a6289e1978407904598751613d9870770cdd8507e3dc7b46851dbf05ae1df2988d"
+
+PSA verify: RSA PSS SHA-256, good signature, 32 bytes (hash size)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_verify:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"1967ae568cc071dfebeeca76b11d40bd1ec5af241c50b3dcceff21f4536c0693a7179a8d5d163a7625fefd37c161127800edeebc24fa73ca772096827bd3f75e8ccf2c64f07b7171b5c99022a4d73b760f34a385ccff0bd5ed7997d2a29d2847acb0767f93a2a404bc046c97de66d95dc9f7646fdb216b627b2ea0de8afcefb7"
+
+PSA verify: RSA PSS SHA-256, good signature, 129 bytes
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_verify:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"1491cead330b4ad5b092f8351518141ac11d0888591572669c1e79d6e932c488acd62d44479b0e14cd91a048778bc02398a772ad6bdb4f7764780cf0afe70293d0cac86f2695a1dcb54568bb37d7086f9e86f95a6802d2ee5a4facaa762beff5261bb2816b62cb5af86404974c3f6b67985ac1fbfdf46d6de54f6e29d9274308"
+
+PSA verify: ECDSA SECP256R1, good
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_SHA256_C:MBEDCRYPTO_ECDSA_C
+asymmetric_verify:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):"3059301306072a8648ce3d020106082a8648ce3d03010703420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
+
+PSA verify with keypair: ECDSA SECP256R1, good
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_C
+asymmetric_verify:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
+
+PSA verify: ECDSA SECP256R1, wrong signature size (correct but ASN1-encoded)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_C
+asymmetric_verify_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):"3059301306072a8648ce3d020106082a8648ce3d03010703420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify: ECDSA SECP256R1, wrong signature of correct size
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_C
+asymmetric_verify_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):"3059301306072a8648ce3d020106082a8648ce3d03010703420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50e":PSA_ERROR_INVALID_SIGNATURE
+
+PSA encrypt: RSA PKCS#1 v1.5, good
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_CRYPT:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":128:PSA_SUCCESS
+
+PSA encrypt: RSA OAEP-SHA-256, good
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":128:PSA_SUCCESS
+
+PSA encrypt: RSA OAEP-SHA-256, good, with label
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"746869730069730061006c6162656c00":128:PSA_SUCCESS
+
+PSA encrypt: RSA OAEP-SHA-384, good
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA512_C
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e":"":128:PSA_SUCCESS
+
+PSA encrypt: RSA OAEP-SHA-384, good
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA512_C
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e":"":128:PSA_SUCCESS
+
+PSA encrypt: RSA PKCS#1 v1.5, key pair
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":128:PSA_SUCCESS
+
+PSA encrypt: RSA OAEP-SHA-256, key pair
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":128:PSA_SUCCESS
+
+PSA encrypt: RSA PKCS#1 v1.5, input too large
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_CRYPT:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"":0:PSA_ERROR_INVALID_ARGUMENT
+
+PSA encrypt: RSA PKCS#1 v1.5: salt not allowed
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_CRYPT:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee":0:PSA_ERROR_INVALID_ARGUMENT
+
+PSA encrypt: RSA OAEP-SHA-384, input too large
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA512_C
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f":"":0:PSA_ERROR_INVALID_ARGUMENT
+
+PSA encrypt: invalid algorithm
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_SHA_256:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":0:PSA_ERROR_INVALID_ARGUMENT
+
+PSA encrypt: RSA PKCS#1 v1.5: invalid key type
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encrypt:PSA_KEY_TYPE_AES:"3082025e02010002818100af057d396e":PSA_ALG_RSA_PKCS1V15_CRYPT:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":0:PSA_ERROR_INVALID_ARGUMENT
+
+PSA encrypt-decrypt: RSA PKCS#1 v1.5 vector #1
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encrypt_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":""
+
+PSA encrypt-decrypt: RSA PKCS#1 v1.5 vector #2
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_encrypt_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"99e8a6144bcb9a29660303bdc4305bb5eca8c64b96788cad062be9967bdab2f7ffff":""
+
+PSA encrypt-decrypt: RSA OAEP-SHA-256
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_encrypt_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":""
+
+PSA encrypt-decrypt: RSA OAEP-SHA-256, with label
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_encrypt_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"746869730069730061006c6162656c00"
+
+PSA encrypt-decrypt: RSA OAEP-SHA-384
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA512_C
+asymmetric_encrypt_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e":""
+
+PSA decrypt: RSA PKCS#1 v1.5: good #1
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"99ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"":"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
+
+PSA decrypt: RSA PKCS#1 v1.5: good #2
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"adeecba2db7f867a733853f0136c554e5e01c7a2015721a9bfe30c3ad163b93a9c7589170311209f91420ad8a1a8280c7e890a6d7bca3c500b4da4f53a17bd84a21d58f979a9b4b8f2246b482d930804f12b3aeb2ac8b5ac7938d452ca13be8eb8e973c4e2b19fd454058cbae037bcef7ef68a5fbabf050de5f283cf1998c695":"":"99e8a6144bcb9a29660303bdc4305bb5eca8c64b96788cad062be9967bdab2f7ffff"
+
+PSA decrypt: RSA OAEP-SHA-256, 0 bytes
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"3d3146b1c982004273a9ebb9b063e6ae53b1a85bfc802324bcdd04faa0f7211fb2bdeea40358095554df9c250866c7361e738f0d270eaa27738e87928c5e31815506346727900ff03cef0be6f9dd6bba63ce89074e8194fe68b5a5739422d4f138bbbb61f49b76cf1f18def2c993e3113b08c191ea1da0feb94f8fd9b30109a1":"":""
+
+PSA decrypt: RSA OAEP-SHA-256, 0 bytes, with label
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"14e57648fbbd3c2c195d71fcb9b6c332e2ad9e3402aa701e7270b05775e9ddd025e2330d7b84e67866524c67f9c38b11e4679e28a38574b47f8d218a1a04a7466754d6ea7f959ab1f5b85d066d3f90076e8219f66653f7b78a9789d76213505b4e75ec28081608ed2f1ea1238e3eeab011ce4ec147327cd0ca029c2818133cb6":"746869730069730061006c6162656c00":""
+
+PSA decrypt: RSA OAEP-SHA-256, 30 bytes
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"3fd3c81e3919a19014400d91098090f273312e0150e09eff7f66fb9624d2ec9764fc80befcb592e9d102493c882b8bc0334a257e73aba23a0ee13f826cbc64f8200b9150784d004ccb2955c877c95ab888e3917f423dd52f3c8a49cb61c1966ec04f336068729ae0bce7d7fb3e680f9d15d658db9b906efcbf2c2fae45e75429":"":"74686973206973206e6f2073717565616d697368206f7373696672616765"
+
+PSA decrypt: RSA OAEP-SHA-256, 30 bytes, with label
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"46edc9984a6d4b7c7fd88fda9ea91ddbd30b28a0793cc75a9fcdd94d867c69090a697d46a6f336a3e48a122dd3ee3b51566b445ff78adb613d09b7d8c59c25a27d8cf7f5e36455f2e71ff6c6ee98d5740e66b23794acc72906561951c2be5064f6a250646ab627ecbfa48c02f82c29fe9b8c8e6be8eb752432124974373b542c":"746869730069730061006c6162656c00":"74686973206973206e6f2073717565616d697368206f7373696672616765"
+
+PSA decrypt: RSA OAEP-SHA-384, 30 bytes
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA512_C
+asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"0df6750b8fed749359c016887d2cf097cc512c065526a91a7ee9b345a1bfff833737e7326e54d03f6bb65971962885a7661a16858d53ea55821052f4c7798d395b5c5495332fd4174451a1a437f36c27f446b96f309ff1cb6837274aa8ae2b51a8a479d736d25b8d2ca8ab96fe589553a3e52818b7df75544eb5469977b29aa4":"":"74686973206973206e6f2073717565616d697368206f7373696672616765"
+
+PSA decrypt: RSA OAEP-SHA-256, 30 bytes, wrong label (should be empty)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"3fd3c81e3919a19014400d91098090f273312e0150e09eff7f66fb9624d2ec9764fc80befcb592e9d102493c882b8bc0334a257e73aba23a0ee13f826cbc64f8200b9150784d004ccb2955c877c95ab888e3917f423dd52f3c8a49cb61c1966ec04f336068729ae0bce7d7fb3e680f9d15d658db9b906efcbf2c2fae45e75429":"00":PSA_ERROR_INVALID_PADDING
+
+PSA decrypt: RSA OAEP-SHA-256, 30 bytes, wrong label (empty)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"46edc9984a6d4b7c7fd88fda9ea91ddbd30b28a0793cc75a9fcdd94d867c69090a697d46a6f336a3e48a122dd3ee3b51566b445ff78adb613d09b7d8c59c25a27d8cf7f5e36455f2e71ff6c6ee98d5740e66b23794acc72906561951c2be5064f6a250646ab627ecbfa48c02f82c29fe9b8c8e6be8eb752432124974373b542c":"":PSA_ERROR_INVALID_PADDING
+
+PSA decrypt: RSA OAEP-SHA-256, 30 bytes, wrong label (same length)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"46edc9984a6d4b7c7fd88fda9ea91ddbd30b28a0793cc75a9fcdd94d867c69090a697d46a6f336a3e48a122dd3ee3b51566b445ff78adb613d09b7d8c59c25a27d8cf7f5e36455f2e71ff6c6ee98d5740e66b23794acc72906561951c2be5064f6a250646ab627ecbfa48c02f82c29fe9b8c8e6be8eb752432124974373b542c":"746869730069730061006c6162656c01":PSA_ERROR_INVALID_PADDING
+
+PSA decrypt: RSA PKCS#1 v1.5, invalid padding
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"99ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46873":"":PSA_ERROR_INVALID_PADDING
+
+PSA decrypt: RSA PKCS#1 v1.5: salt not allowed
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"99ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee":PSA_ERROR_INVALID_ARGUMENT
+
+PSA decrypt: RSA OAEP-SHA-256, invalid padding
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"3fd3c81e3919a19014400d91098090f273312e0150e09eff7f66fb9624d2ec9764fc80befcb592e9d102493c882b8bc0334a257e73aba23a0ee13f826cbc64f8200b9150784d004ccb2955c877c95ab888e3917f423dd52f3c8a49cb61c1966ec04f336068729ae0bce7d7fb3e680f9d15d658db9b906efcbf2c2fae45e75428":"":PSA_ERROR_INVALID_PADDING
+
+PSA decrypt: invalid algorithm
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_SHA_256:"adeecba2db7f867a733853f0136c554e5e01c7a2015721a9bfe30c3ad163b93a9c7589170311209f91420ad8a1a8280c7e890a6d7bca3c500b4da4f53a17bd84a21d58f979a9b4b8f2246b482d930804f12b3aeb2ac8b5ac7938d452ca13be8eb8e973c4e2b19fd454058cbae037bcef7ef68a5fbabf050de5f283cf1998c695":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA decrypt: RSA PKCS#1 v1.5, invalid key type (RSA public key)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_CRYPT:"adeecba2db7f867a733853f0136c554e5e01c7a2015721a9bfe30c3ad163b93a9c7589170311209f91420ad8a1a8280c7e890a6d7bca3c500b4da4f53a17bd84a21d58f979a9b4b8f2246b482d930804f12b3aeb2ac8b5ac7938d452ca13be8eb8e973c4e2b19fd454058cbae037bcef7ef68a5fbabf050de5f283cf1998c695":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA decrypt: RSA OAEP, invalid key type (RSA public key)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"adeecba2db7f867a733853f0136c554e5e01c7a2015721a9bfe30c3ad163b93a9c7589170311209f91420ad8a1a8280c7e890a6d7bca3c500b4da4f53a17bd84a21d58f979a9b4b8f2246b482d930804f12b3aeb2ac8b5ac7938d452ca13be8eb8e973c4e2b19fd454058cbae037bcef7ef68a5fbabf050de5f283cf1998c695":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA decrypt: RSA PKCS#1 v1.5: invalid key type (AES)
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_decrypt_fail:PSA_KEY_TYPE_AES:"3082025e02010002818100af057d396e":PSA_ALG_RSA_PKCS1V15_CRYPT:"3082025e02010002818100af057d396e":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA decrypt: RSA PKCS#1 v1.5, input too small
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA decrypt: RSA PKCS#1 v1.5, input too large
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V15
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"0099ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA decrypt: RSA OAEP-SHA-256, input too small
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA decrypt: RSA OAEP-SHA-256, input too large
+depends_on:MBEDCRYPTO_PK_PARSE_C:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"0099ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA key derivation: HKDF-SHA-256, good case
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_setup:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HKDF(PSA_ALG_SHA_256):"":"":42:PSA_SUCCESS
+
+PSA key derivation: bad key type
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_setup:PSA_KEY_TYPE_RAW_DATA:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HKDF(PSA_ALG_SHA_256):"":"":42:PSA_ERROR_INVALID_ARGUMENT
+
+PSA key derivation: not a key derivation algorithm
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_setup:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_256):"":"":42:PSA_ERROR_INVALID_ARGUMENT
+
+PSA key derivation: unsupported key derivation algorithm
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_setup:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HKDF(PSA_ALG_CATEGORY_HASH):"":"":42:PSA_ERROR_NOT_SUPPORTED
+
+PSA key derivation: HKDF SHA-256, RFC5869 #1, output 42+0
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":""
+
+PSA key derivation: HKDF SHA-256, RFC5869 #1, output 32+10
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf":"34007208d5b887185865"
+
+PSA key derivation: HKDF SHA-256, RFC5869 #1, output 0+42
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"":"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
+
+PSA key derivation: HKDF SHA-256, RFC5869 #1, output 1+41
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"3c":"b25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
+
+PSA key derivation: HKDF SHA-256, RFC5869 #1, output 41+0
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b8871858":""
+
+PSA key derivation: HKDF SHA-256, RFC5869 #1, output 1+40
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"3c":"b25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b8871858"
+
+PSA key derivation: HKDF SHA-256, RFC5869 #2, output 82+0
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":82:"b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87":""
+
+PSA key derivation: HKDF SHA-256, RFC5869 #3, output 42+0
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"":"":42:"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8":""
+
+PSA key derivation: HKDF SHA-1, RFC5869 #4, output 42+0
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA1_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):"0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896":""
+
+PSA key derivation: HKDF SHA-1, RFC5869 #5, output 82+0
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA1_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":82:"0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4":""
+
+PSA key derivation: HKDF SHA-1, RFC5869 #6, output 42+0
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA1_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"":"":42:"0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918":""
+
+PSA key derivation: HKDF SHA-1, RFC5869 #7, output 42+0
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA1_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":"":"":42:"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48":""
+
+PSA key derivation: HKDF SHA-256, request maximum capacity
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":""
+
+PSA key derivation: HKDF SHA-1, request maximum capacity
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA1_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":"":"":255 * 20:"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48":""
+
+PSA key derivation: HKDF SHA-256, request too much capacity
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_setup:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HKDF(PSA_ALG_SHA_256):"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32 + 1:PSA_ERROR_INVALID_ARGUMENT
+
+PSA key derivation: HKDF SHA-1, request too much capacity
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA1_C
+derive_setup:PSA_KEY_TYPE_DERIVE:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":PSA_ALG_HKDF(PSA_ALG_SHA_1):"":"":255 * 20 + 1:PSA_ERROR_INVALID_ARGUMENT
+
+PSA key derivation: over capacity 42: output 42+1
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":"ff"
+
+PSA key derivation: over capacity 42: output 41+2
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b8871858":"65ff"
+
+PSA key derivation: over capacity 42: output 43+0
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865ff":""
+
+PSA key derivation: over capacity 42: output 43+1
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865ff":"ff"
+
+PSA key derivation: HKDF SHA-256, read maximum capacity minus 1
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32 - 1
+
+PSA key derivation: HKDF SHA-256, read maximum capacity
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32
+
+PSA key derivation: HKDF SHA-256, exercise AES128-CTR
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR
+derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
+
+PSA key derivation: HKDF SHA-256, exercise AES256-CTR
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR
+derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:256:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
+
+PSA key derivation: HKDF SHA-256, exercise DES-CBC
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C:MBEDCRYPTO_DES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7
+
+PSA key derivation: HKDF SHA-256, exercise 2-key 3DES-CBC
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C:MBEDCRYPTO_DES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7
+
+PSA key derivation: HKDF SHA-256, exercise 3-key 3DES-CBC
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C:MBEDCRYPTO_DES_C:MBEDCRYPTO_CIPHER_MODE_CBC
+derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DES:192:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7
+
+PSA key derivation: HKDF SHA-256, exercise HMAC-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_HMAC:256:PSA_KEY_USAGE_SIGN:PSA_ALG_HMAC(PSA_ALG_SHA_256)
+
+PSA key derivation: HKDF SHA-256, exercise HKDF-SHA-256
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DERIVE:400:PSA_KEY_USAGE_DERIVE:PSA_ALG_HKDF(PSA_ALG_SHA_256)
+
+PSA key derivation: HKDF SHA-256, derive key, 16+32
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_key_export:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":16:32
+
+PSA key derivation: HKDF SHA-256, derive key, 1+41
+depends_on:MBEDCRYPTO_MD_C:MBEDCRYPTO_SHA256_C
+derive_key_export:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":1:41
+
+PSA generate random: 0 bytes
+generate_random:0
+
+PSA generate random: 1 byte
+generate_random:1
+
+PSA generate random: 4 bytes
+generate_random:4
+
+PSA generate random: 16 bytes
+generate_random:16
+
+PSA generate random: 19 bytes
+generate_random:19
+
+PSA generate random: 260 bytes
+generate_random:260
+
+PSA generate key: bad type (PSA_KEY_TYPE_CATEGORY_MASK)
+generate_key:PSA_KEY_TYPE_CATEGORY_MASK:128:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED
+
+PSA generate key: bad type (RSA public key)
+generate_key:PSA_KEY_TYPE_RSA_PUBLIC_KEY:512:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED
+
+PSA generate key: raw data, 0 bits
+generate_key:PSA_KEY_TYPE_RAW_DATA:128:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
+
+PSA generate key: raw data, 7 bits: invalid argument
+generate_key:PSA_KEY_TYPE_RAW_DATA:7:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key: raw data, 8 bits
+generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
+
+PSA generate key: AES, 128 bits, CTR
+depends_on:MBEDCRYPTO_AES_C:MBEDCRYPTO_CIPHER_MODE_CTR
+generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_SUCCESS
+
+PSA generate key: AES, 128 bits, GCM
+depends_on:MBEDCRYPTO_AES_C
+generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_GCM:PSA_SUCCESS
+
+PSA generate key: DES, 64 bits, CBC-nopad
+depends_on:MBEDCRYPTO_DES_C
+generate_key:PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_SUCCESS
+
+PSA generate key: DES, 128 bits, CBC-nopad
+depends_on:MBEDCRYPTO_DES_C
+generate_key:PSA_KEY_TYPE_DES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_SUCCESS
+
+PSA generate key: DES, 192 bits, CBC-nopad
+depends_on:MBEDCRYPTO_DES_C
+generate_key:PSA_KEY_TYPE_DES:192:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_NONE:PSA_SUCCESS
+
+PSA generate key: invalid key size: AES, 64 bits
+depends_on:MBEDCRYPTO_AES_C
+generate_key:PSA_KEY_TYPE_AES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key: RSA, 512 bits, good, sign (PKCS#1 v1.5)
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_GENPRIME:MBEDCRYPTO_PKCS1_V15
+generate_key:PSA_KEY_TYPE_RSA_KEYPAIR:512:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_SUCCESS
+
+PSA generate key: RSA, 1024 bits, good, sign (PSS SHA-256)
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_GENPRIME:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+generate_key:PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_SUCCESS
+
+PSA generate key: RSA, 512 bits, good, encrypt (PKCS#1 v1.5)
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_GENPRIME:MBEDCRYPTO_PKCS1_V15
+generate_key:PSA_KEY_TYPE_RSA_KEYPAIR:512:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_SUCCESS
+
+PSA generate key: RSA, 1024 bits, good, encrypt (OAEP SHA-256)
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_PKCS1_V21:MBEDCRYPTO_SHA256_C
+generate_key:PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):PSA_SUCCESS
+
+PSA generate key: RSA, maximum size exceeded
+depends_on:MBEDCRYPTO_RSA_C:MBEDCRYPTO_GENPRIME
+generate_key:PSA_KEY_TYPE_RSA_KEYPAIR:PSA_VENDOR_RSA_MAX_KEY_BITS+1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_NOT_SUPPORTED
+
+PSA generate key: ECC, SECP256R1, good
+depends_on:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_C
+generate_key:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:PSA_SUCCESS
+
+PSA generate key: ECC, SECP256R1, incorrect bit size
+depends_on:MBEDCRYPTO_ECP_C:MBEDCRYPTO_ECP_DP_SECP256R1_ENABLED:MBEDCRYPTO_ECDSA_C
+generate_key:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:PSA_ERROR_INVALID_ARGUMENT
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
new file mode 100644
index 0000000..77e3e51
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -0,0 +1,3172 @@
+/* BEGIN_HEADER */
+#include <stdint.h>
+
+#if defined(MBEDCRYPTO_PSA_CRYPTO_SPM)
+#include "spm/psa_defs.h"
+#endif
+
+#include "mbedcrypto/asn1write.h"
+#include "psa/crypto.h"
+
+#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) )
+
+#if(UINT32_MAX > SIZE_MAX)
+#define PSA_CRYPTO_TEST_SIZE_T_RANGE( x ) ( ( x ) <= SIZE_MAX )
+#else
+#define PSA_CRYPTO_TEST_SIZE_T_RANGE( x ) 1
+#endif
+
+/** An invalid export length that will never be set by psa_export_key(). */
+static const size_t INVALID_EXPORT_LENGTH = ~0U;
+
+/** Test if a buffer is all-bits zero.
+ *
+ * \param buffer Pointer to the beginning of the buffer.
+ * \param size Size of the buffer in bytes.
+ *
+ * \return 1 if the buffer is all-bits-zero.
+ * \return 0 if there is at least one nonzero byte.
+ */
+static int mem_is_zero( void *buffer, size_t size )
+{
+ size_t i;
+ for( i = 0; i < size; i++ )
+ {
+ if( ( (unsigned char *) buffer )[i] != 0 )
+ return( 0 );
+ }
+ return( 1 );
+}
+
+static int key_type_is_raw_bytes( psa_key_type_t type )
+{
+ psa_key_type_t category = type & PSA_KEY_TYPE_CATEGORY_MASK;
+ return( category == PSA_KEY_TYPE_RAW_DATA ||
+ category == PSA_KEY_TYPE_CATEGORY_SYMMETRIC );
+}
+
+/* Write the ASN.1 INTEGER with the value 2^(bits-1)+x backwards from *p. */
+static int asn1_write_10x( unsigned char **p,
+ unsigned char *start,
+ size_t bits,
+ unsigned char x )
+{
+ int ret;
+ int len = bits / 8 + 1;
+ if( bits == 0 )
+ return( MBEDCRYPTO_ERR_ASN1_INVALID_DATA );
+ if( bits <= 8 && x >= 1 << ( bits - 1 ) )
+ return( MBEDCRYPTO_ERR_ASN1_INVALID_DATA );
+ if( *p < start || *p - start < (ptrdiff_t) len )
+ return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
+ *p -= len;
+ ( *p )[len-1] = x;
+ if( bits % 8 == 0 )
+ ( *p )[1] |= 1;
+ else
+ ( *p )[0] |= 1 << ( bits % 8 );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start,
+ MBEDCRYPTO_ASN1_INTEGER ) );
+ return( len );
+}
+
+static int construct_fake_rsa_key( unsigned char *buffer,
+ size_t buffer_size,
+ unsigned char **p,
+ size_t bits,
+ int keypair )
+{
+ size_t half_bits = ( bits + 1 ) / 2;
+ int ret;
+ int len = 0;
+ /* Construct something that looks like a DER encoding of
+ * as defined by PKCS#1 v2.2 (RFC 8017) section A.1.2:
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ * Or, for a public key, the same structure with only
+ * version, modulus and publicExponent.
+ */
+ *p = buffer + buffer_size;
+ if( keypair )
+ {
+ MBEDCRYPTO_ASN1_CHK_ADD( len, /* pq */
+ asn1_write_10x( p, buffer, half_bits, 1 ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, /* dq */
+ asn1_write_10x( p, buffer, half_bits, 1 ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, /* dp */
+ asn1_write_10x( p, buffer, half_bits, 1 ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, /* q */
+ asn1_write_10x( p, buffer, half_bits, 1 ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, /* p != q to pass mbedcrypto sanity checks */
+ asn1_write_10x( p, buffer, half_bits, 3 ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, /* d */
+ asn1_write_10x( p, buffer, bits, 1 ) );
+ }
+ MBEDCRYPTO_ASN1_CHK_ADD( len, /* e = 65537 */
+ asn1_write_10x( p, buffer, 17, 1 ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, /* n */
+ asn1_write_10x( p, buffer, bits, 1 ) );
+ if( keypair )
+ MBEDCRYPTO_ASN1_CHK_ADD( len, /* version = 0 */
+ mbedcrypto_asn1_write_int( p, buffer, 0 ) );
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, buffer, len ) );
+ {
+ const unsigned char tag =
+ MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE;
+ MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, buffer, tag ) );
+ }
+ return( len );
+}
+
+static int exercise_mac_key( psa_key_slot_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ psa_mac_operation_t operation;
+ const unsigned char input[] = "foo";
+ unsigned char mac[PSA_MAC_MAX_SIZE] = {0};
+ size_t mac_length = sizeof( mac );
+
+ if( usage & PSA_KEY_USAGE_SIGN )
+ {
+ TEST_ASSERT( psa_mac_sign_setup( &operation,
+ key, alg ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_mac_update( &operation,
+ input, sizeof( input ) ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_mac_sign_finish( &operation,
+ mac, sizeof( mac ),
+ &mac_length ) == PSA_SUCCESS );
+ }
+
+ if( usage & PSA_KEY_USAGE_VERIFY )
+ {
+ psa_status_t verify_status =
+ ( usage & PSA_KEY_USAGE_SIGN ?
+ PSA_SUCCESS :
+ PSA_ERROR_INVALID_SIGNATURE );
+ TEST_ASSERT( psa_mac_verify_setup( &operation,
+ key, alg ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_mac_update( &operation,
+ input, sizeof( input ) ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_mac_verify_finish( &operation,
+ mac,
+ mac_length ) == verify_status );
+ }
+
+ return( 1 );
+
+exit:
+ psa_mac_abort( &operation );
+ return( 0 );
+}
+
+static int exercise_cipher_key( psa_key_slot_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ psa_cipher_operation_t operation;
+ unsigned char iv[16] = {0};
+ size_t iv_length = sizeof( iv );
+ const unsigned char plaintext[16] = "Hello, world...";
+ unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
+ size_t ciphertext_length = sizeof( ciphertext );
+ unsigned char decrypted[sizeof( ciphertext )];
+ size_t part_length;
+
+ if( usage & PSA_KEY_USAGE_ENCRYPT )
+ {
+ TEST_ASSERT( psa_cipher_encrypt_setup( &operation,
+ key, alg ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_cipher_generate_iv( &operation,
+ iv, sizeof( iv ),
+ &iv_length ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_cipher_update( &operation,
+ plaintext, sizeof( plaintext ),
+ ciphertext, sizeof( ciphertext ),
+ &ciphertext_length ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_cipher_finish( &operation,
+ ciphertext + ciphertext_length,
+ sizeof( ciphertext ) - ciphertext_length,
+ &part_length ) == PSA_SUCCESS );
+ ciphertext_length += part_length;
+ }
+
+ if( usage & PSA_KEY_USAGE_DECRYPT )
+ {
+ psa_status_t status;
+ psa_key_type_t type = PSA_KEY_TYPE_NONE;
+ if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
+ {
+ size_t bits;
+ TEST_ASSERT( psa_get_key_information( key, &type, &bits ) );
+ iv_length = PSA_BLOCK_CIPHER_BLOCK_SIZE( type );
+ }
+ TEST_ASSERT( psa_cipher_decrypt_setup( &operation,
+ key, alg ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_cipher_set_iv( &operation,
+ iv, iv_length ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_cipher_update( &operation,
+ ciphertext, ciphertext_length,
+ decrypted, sizeof( decrypted ),
+ &part_length ) == PSA_SUCCESS );
+ status = psa_cipher_finish( &operation,
+ decrypted + part_length,
+ sizeof( decrypted ) - part_length,
+ &part_length );
+ /* For a stream cipher, all inputs are valid. For a block cipher,
+ * if the input is some aribtrary data rather than an actual
+ ciphertext, a padding error is likely. */
+ if( ( usage & PSA_KEY_USAGE_ENCRYPT ) ||
+ PSA_BLOCK_CIPHER_BLOCK_SIZE( type ) == 1 )
+ TEST_ASSERT( status == PSA_SUCCESS );
+ else
+ TEST_ASSERT( status == PSA_SUCCESS ||
+ status == PSA_ERROR_INVALID_PADDING );
+ }
+
+ return( 1 );
+
+exit:
+ psa_cipher_abort( &operation );
+ return( 0 );
+}
+
+static int exercise_aead_key( psa_key_slot_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ unsigned char nonce[16] = {0};
+ size_t nonce_length = sizeof( nonce );
+ unsigned char plaintext[16] = "Hello, world...";
+ unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
+ size_t ciphertext_length = sizeof( ciphertext );
+ size_t plaintext_length = sizeof( ciphertext );
+
+ if( usage & PSA_KEY_USAGE_ENCRYPT )
+ {
+ TEST_ASSERT( psa_aead_encrypt( key, alg,
+ nonce, nonce_length,
+ NULL, 0,
+ plaintext, sizeof( plaintext ),
+ ciphertext, sizeof( ciphertext ),
+ &ciphertext_length ) == PSA_SUCCESS );
+ }
+
+ if( usage & PSA_KEY_USAGE_DECRYPT )
+ {
+ psa_status_t verify_status =
+ ( usage & PSA_KEY_USAGE_ENCRYPT ?
+ PSA_SUCCESS :
+ PSA_ERROR_INVALID_SIGNATURE );
+ TEST_ASSERT( psa_aead_decrypt( key, alg,
+ nonce, nonce_length,
+ NULL, 0,
+ ciphertext, ciphertext_length,
+ plaintext, sizeof( plaintext ),
+ &plaintext_length ) == verify_status );
+ }
+
+ return( 1 );
+
+exit:
+ return( 0 );
+}
+
+static int exercise_signature_key( psa_key_slot_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ unsigned char payload[PSA_HASH_MAX_SIZE] = {1};
+ size_t payload_length = 16;
+ unsigned char signature[PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE] = {0};
+ size_t signature_length = sizeof( signature );
+
+ if( usage & PSA_KEY_USAGE_SIGN )
+ {
+ /* Some algorithms require the payload to have the size of
+ * the hash encoded in the algorithm. Use this input size
+ * even for algorithms that allow other input sizes. */
+ psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
+ if( hash_alg != 0 )
+ payload_length = PSA_HASH_SIZE( hash_alg );
+ TEST_ASSERT( psa_asymmetric_sign( key, alg,
+ payload, payload_length,
+ signature, sizeof( signature ),
+ &signature_length ) == PSA_SUCCESS );
+ }
+
+ if( usage & PSA_KEY_USAGE_VERIFY )
+ {
+ psa_status_t verify_status =
+ ( usage & PSA_KEY_USAGE_SIGN ?
+ PSA_SUCCESS :
+ PSA_ERROR_INVALID_SIGNATURE );
+ TEST_ASSERT( psa_asymmetric_verify( key, alg,
+ payload, payload_length,
+ signature, signature_length ) ==
+ verify_status );
+ }
+
+ return( 1 );
+
+exit:
+ return( 0 );
+}
+
+static int exercise_asymmetric_encryption_key( psa_key_slot_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ unsigned char plaintext[256] = "Hello, world...";
+ unsigned char ciphertext[256] = "(wabblewebblewibblewobblewubble)";
+ size_t ciphertext_length = sizeof( ciphertext );
+ size_t plaintext_length = 16;
+
+ if( usage & PSA_KEY_USAGE_ENCRYPT )
+ {
+ TEST_ASSERT(
+ psa_asymmetric_encrypt( key, alg,
+ plaintext, plaintext_length,
+ NULL, 0,
+ ciphertext, sizeof( ciphertext ),
+ &ciphertext_length ) == PSA_SUCCESS );
+ }
+
+ if( usage & PSA_KEY_USAGE_DECRYPT )
+ {
+ psa_status_t status =
+ psa_asymmetric_decrypt( key, alg,
+ ciphertext, ciphertext_length,
+ NULL, 0,
+ plaintext, sizeof( plaintext ),
+ &plaintext_length );
+ TEST_ASSERT( status == PSA_SUCCESS ||
+ ( ( usage & PSA_KEY_USAGE_ENCRYPT ) == 0 &&
+ ( status == PSA_ERROR_INVALID_ARGUMENT ||
+ status == PSA_ERROR_INVALID_PADDING ) ) );
+ }
+
+ return( 1 );
+
+exit:
+ return( 0 );
+}
+
+static int exercise_key_derivation_key( psa_key_slot_t key,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ unsigned char label[16] = "This is a label.";
+ size_t label_length = sizeof( label );
+ unsigned char seed[16] = "abcdefghijklmnop";
+ size_t seed_length = sizeof( seed );
+ unsigned char output[1];
+
+ if( usage & PSA_KEY_USAGE_DERIVE )
+ {
+ TEST_ASSERT( psa_key_derivation( &generator,
+ key, alg,
+ label, label_length,
+ seed, seed_length,
+ sizeof( output ) ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_read( &generator,
+ output,
+ sizeof( output ) ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_abort( &generator ) == PSA_SUCCESS );
+ }
+
+ return( 1 );
+
+exit:
+ return( 0 );
+}
+
+static int exercise_key( psa_key_slot_t slot,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg )
+{
+ int ok;
+ if( alg == 0 )
+ ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */
+ else if( PSA_ALG_IS_MAC( alg ) )
+ ok = exercise_mac_key( slot, usage, alg );
+ else if( PSA_ALG_IS_CIPHER( alg ) )
+ ok = exercise_cipher_key( slot, usage, alg );
+ else if( PSA_ALG_IS_AEAD( alg ) )
+ ok = exercise_aead_key( slot, usage, alg );
+ else if( PSA_ALG_IS_SIGN( alg ) )
+ ok = exercise_signature_key( slot, usage, alg );
+ else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
+ ok = exercise_asymmetric_encryption_key( slot, usage, alg );
+ else if( PSA_ALG_IS_KEY_DERIVATION( alg ) )
+ ok = exercise_key_derivation_key( slot, usage, alg );
+ else
+ {
+ char message[40];
+ mbedcrypto_snprintf( message, sizeof( message ),
+ "No code to exercise alg=0x%08lx",
+ (unsigned long) alg );
+ test_fail( message, __LINE__, __FILE__ );
+ ok = 0;
+ }
+ return( ok );
+}
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDCRYPTO_PSA_CRYPTO_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void init_deinit( )
+{
+ psa_status_t status;
+ int i;
+ for( i = 0; i <= 1; i++ )
+ {
+ status = psa_crypto_init( );
+ TEST_ASSERT( status == PSA_SUCCESS );
+ status = psa_crypto_init( );
+ TEST_ASSERT( status == PSA_SUCCESS );
+ mbedcrypto_psa_crypto_free( );
+ }
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void fill_slots( int max_arg )
+{
+ /* Fill all the slots until we run out of memory or out of slots,
+ * or until some limit specified in the test data for the sake of
+ * implementations with an essentially unlimited number of slots.
+ * This test assumes that available slots are numbered from 1. */
+
+ psa_key_slot_t slot;
+ psa_key_slot_t max = 0;
+ psa_key_policy_t policy;
+ uint8_t exported[sizeof( max )];
+ size_t exported_size;
+ psa_status_t status;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 );
+
+ for( max = 1; max <= (size_t) max_arg; max++ )
+ {
+ status = psa_set_key_policy( max, &policy );
+ /* Stop filling slots if we run out of memory or out of
+ * available slots. */
+ TEST_ASSERT( status == PSA_SUCCESS ||
+ status == PSA_ERROR_INSUFFICIENT_MEMORY ||
+ status == PSA_ERROR_INVALID_ARGUMENT );
+ if( status != PSA_SUCCESS )
+ break;
+ status = psa_import_key( max, PSA_KEY_TYPE_RAW_DATA,
+ (uint8_t*) &max, sizeof( max ) );
+ /* Since psa_set_key_policy succeeded, we know that the slot
+ * number is valid. But we may legitimately run out of memory. */
+ TEST_ASSERT( status == PSA_SUCCESS ||
+ status == PSA_ERROR_INSUFFICIENT_MEMORY );
+ if( status != PSA_SUCCESS )
+ break;
+ }
+ /* `max` is now the first slot number that wasn't filled. */
+ max -= 1;
+
+ for( slot = 1; slot <= max; slot++ )
+ {
+ TEST_ASSERT( psa_export_key( slot,
+ exported, sizeof( exported ),
+ &exported_size ) == PSA_SUCCESS );
+ TEST_ASSERT( exported_size == sizeof( slot ) );
+ TEST_ASSERT( memcmp( exported, &slot, sizeof( slot ) ) == 0 );
+ }
+
+exit:
+ /* Do not destroy the keys. mbedcrypto_psa_crypto_free() should do it. */
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void import( HexParam_t *data, int type, int expected_status_arg )
+{
+ int slot = 1;
+ psa_status_t expected_status = expected_status_arg;
+ psa_status_t status;
+
+ TEST_ASSERT( data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( data->len ) );
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ status = psa_import_key( slot, type, data->x, data->len );
+ TEST_ASSERT( status == expected_status );
+ if( status == PSA_SUCCESS )
+ TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
+
+exit:
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void import_rsa_made_up( int bits_arg, int keypair, int expected_status_arg )
+{
+ int slot = 1;
+ size_t bits = bits_arg;
+ psa_status_t expected_status = expected_status_arg;
+ psa_status_t status;
+ psa_key_type_t type =
+ keypair ? PSA_KEY_TYPE_RSA_KEYPAIR : PSA_KEY_TYPE_RSA_PUBLIC_KEY;
+ size_t buffer_size = /* Slight overapproximations */
+ keypair ? bits * 9 / 16 + 80 : bits / 8 + 20;
+ unsigned char *buffer = mbedcrypto_calloc( 1, buffer_size );
+ unsigned char *p;
+ int ret;
+ size_t length;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+ TEST_ASSERT( buffer != NULL );
+
+ TEST_ASSERT( ( ret = construct_fake_rsa_key( buffer, buffer_size, &p,
+ bits, keypair ) ) >= 0 );
+ length = ret;
+
+ /* Try importing the key */
+ status = psa_import_key( slot, type, p, length );
+ TEST_ASSERT( status == expected_status );
+ if( status == PSA_SUCCESS )
+ TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
+
+exit:
+ mbedcrypto_free( buffer );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void import_export( HexParam_t *data,
+ int type_arg,
+ int alg_arg,
+ int usage_arg,
+ int expected_bits,
+ int export_size_delta,
+ int expected_export_status_arg,
+ int canonical_input )
+{
+ int slot = 1;
+ int slot2 = slot + 1;
+ psa_key_type_t type = type_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_status_t expected_export_status = expected_export_status_arg;
+ psa_status_t status;
+ unsigned char *exported = NULL;
+ unsigned char *reexported = NULL;
+ size_t export_size;
+ size_t exported_length = INVALID_EXPORT_LENGTH;
+ size_t reexported_length;
+ psa_key_type_t got_type;
+ size_t got_bits;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( data->len ) );
+ export_size = (ptrdiff_t) data->len + export_size_delta;
+ exported = mbedcrypto_calloc( 1, export_size );
+ TEST_ASSERT( export_size == 0 || exported != NULL );
+ if( ! canonical_input )
+ {
+ reexported = mbedcrypto_calloc( 1, export_size );
+ TEST_ASSERT( export_size == 0 || reexported != NULL );
+ }
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, usage_arg, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ /* Import the key */
+ TEST_ASSERT( psa_import_key( slot, type,
+ data->x, data->len ) == PSA_SUCCESS );
+
+ /* Test the key information */
+ TEST_ASSERT( psa_get_key_information( slot,
+ &got_type,
+ &got_bits ) == PSA_SUCCESS );
+ TEST_ASSERT( got_type == type );
+ TEST_ASSERT( got_bits == (size_t) expected_bits );
+
+ /* Export the key */
+ status = psa_export_key( slot,
+ exported, export_size,
+ &exported_length );
+ TEST_ASSERT( status == expected_export_status );
+
+ /* The exported length must be set by psa_export_key() to a value between 0
+ * and export_size. On errors, the exported length must be 0. */
+ TEST_ASSERT( exported_length != INVALID_EXPORT_LENGTH );
+ TEST_ASSERT( status == PSA_SUCCESS || exported_length == 0 );
+ TEST_ASSERT( exported_length <= export_size );
+
+ TEST_ASSERT( mem_is_zero( exported + exported_length,
+ export_size - exported_length ) );
+ if( status != PSA_SUCCESS )
+ {
+ TEST_ASSERT( exported_length == 0 );
+ goto destroy;
+ }
+
+ if( canonical_input )
+ {
+ TEST_ASSERT( exported_length == data->len );
+ TEST_ASSERT( memcmp( exported, data->x, data->len ) == 0 );
+ }
+ else
+ {
+ TEST_ASSERT( psa_set_key_policy( slot2, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot2, type,
+ exported,
+ export_size ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_export_key( slot2,
+ reexported,
+ export_size,
+ &reexported_length ) == PSA_SUCCESS );
+ TEST_ASSERT( reexported_length == exported_length );
+ TEST_ASSERT( memcmp( reexported, exported,
+ exported_length ) == 0 );
+ }
+
+destroy:
+ /* Destroy the key */
+ TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_get_key_information(
+ slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT );
+
+exit:
+ mbedcrypto_free( exported );
+ mbedcrypto_free( reexported );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void import_export_public_key( HexParam_t *data,
+ int type_arg,
+ int alg_arg,
+ int expected_bits,
+ int public_key_expected_length,
+ int expected_export_status_arg )
+{
+ int slot = 1;
+ psa_key_type_t type = type_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_status_t expected_export_status = expected_export_status_arg;
+ psa_status_t status;
+ unsigned char *exported = NULL;
+ size_t export_size;
+ size_t exported_length = INVALID_EXPORT_LENGTH;
+ psa_key_type_t got_type;
+ size_t got_bits;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( data->len ) );
+ export_size = (ptrdiff_t) data->len;
+ exported = mbedcrypto_calloc( 1, export_size );
+ TEST_ASSERT( exported != NULL );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ /* Import the key */
+ TEST_ASSERT( psa_import_key( slot, type,
+ data->x, data->len ) == PSA_SUCCESS );
+
+ /* Test the key information */
+ TEST_ASSERT( psa_get_key_information( slot,
+ &got_type,
+ &got_bits ) == PSA_SUCCESS );
+ TEST_ASSERT( got_type == type );
+ TEST_ASSERT( got_bits == (size_t) expected_bits );
+
+ /* Export the key */
+ status = psa_export_public_key( slot,
+ exported, export_size,
+ &exported_length );
+ TEST_ASSERT( status == expected_export_status );
+ TEST_ASSERT( exported_length == (size_t) public_key_expected_length );
+ TEST_ASSERT( mem_is_zero( exported + exported_length,
+ export_size - exported_length ) );
+ if( status != PSA_SUCCESS )
+ goto destroy;
+
+destroy:
+ /* Destroy the key */
+ TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_get_key_information(
+ slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT );
+
+exit:
+ mbedcrypto_free( exported );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void import_and_exercise_key( HexParam_t *data,
+ int type_arg,
+ int bits_arg,
+ int alg_arg )
+{
+ int slot = 1;
+ psa_key_type_t type = type_arg;
+ size_t bits = bits_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_key_usage_t usage =
+ ( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) ?
+ ( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
+ PSA_KEY_USAGE_VERIFY :
+ PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY ) :
+ PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ||
+ PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ?
+ ( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
+ PSA_KEY_USAGE_ENCRYPT :
+ PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ) :
+ PSA_ALG_IS_KEY_DERIVATION( alg ) ? PSA_KEY_USAGE_DERIVE :
+ 0 );
+ psa_key_policy_t policy;
+ psa_key_type_t got_type;
+ size_t got_bits;
+ psa_status_t status;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, usage, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ /* Import the key */
+ status = psa_import_key( slot, type, data->x, data->len );
+ TEST_ASSERT( status == PSA_SUCCESS );
+
+ /* Test the key information */
+ TEST_ASSERT( psa_get_key_information( slot,
+ &got_type,
+ &got_bits ) == PSA_SUCCESS );
+ TEST_ASSERT( got_type == type );
+ TEST_ASSERT( got_bits == bits );
+
+ /* Do something with the key according to its type and permitted usage. */
+ if( ! exercise_key( slot, usage, alg ) )
+ goto exit;
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void key_policy( int usage_arg, int alg_arg )
+{
+ int key_slot = 1;
+ psa_algorithm_t alg = alg_arg;
+ psa_key_usage_t usage = usage_arg;
+ psa_key_type_t key_type = PSA_KEY_TYPE_AES;
+ unsigned char key[32] = {0};
+ psa_key_policy_t policy_set;
+ psa_key_policy_t policy_get;
+
+ memset( key, 0x2a, sizeof( key ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy_set );
+ psa_key_policy_init( &policy_get );
+
+ psa_key_policy_set_usage( &policy_set, usage, alg );
+
+ TEST_ASSERT( psa_key_policy_get_usage( &policy_set ) == usage );
+ TEST_ASSERT( psa_key_policy_get_algorithm( &policy_set ) == alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy_set ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key, sizeof( key ) ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_get_key_policy( key_slot, &policy_get ) == PSA_SUCCESS );
+
+ TEST_ASSERT( policy_get.usage == policy_set.usage );
+ TEST_ASSERT( policy_get.alg == policy_set.alg );
+
+exit:
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mac_key_policy( int policy_usage,
+ int policy_alg,
+ int key_type,
+ HexParam_t *key_data,
+ int exercise_alg )
+{
+ int key_slot = 1;
+ psa_key_policy_t policy;
+ psa_mac_operation_t operation;
+ psa_status_t status;
+ unsigned char mac[PSA_MAC_MAX_SIZE];
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key_data->x, key_data->len ) == PSA_SUCCESS );
+
+ status = psa_mac_sign_setup( &operation, key_slot, exercise_alg );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_SIGN ) != 0 )
+ TEST_ASSERT( status == PSA_SUCCESS );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+ psa_mac_abort( &operation );
+
+ memset( mac, 0, sizeof( mac ) );
+ status = psa_mac_verify_setup( &operation, key_slot, exercise_alg );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_VERIFY ) != 0 )
+ TEST_ASSERT( status == PSA_SUCCESS );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+
+exit:
+ psa_mac_abort( &operation );
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_key_policy( int policy_usage,
+ int policy_alg,
+ int key_type,
+ HexParam_t *key_data,
+ int exercise_alg )
+{
+ int key_slot = 1;
+ psa_key_policy_t policy;
+ psa_cipher_operation_t operation;
+ psa_status_t status;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key_data->x, key_data->len ) == PSA_SUCCESS );
+
+ status = psa_cipher_encrypt_setup( &operation, key_slot, exercise_alg );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_ENCRYPT ) != 0 )
+ TEST_ASSERT( status == PSA_SUCCESS );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+ psa_cipher_abort( &operation );
+
+ status = psa_cipher_decrypt_setup( &operation, key_slot, exercise_alg );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_DECRYPT ) != 0 )
+ TEST_ASSERT( status == PSA_SUCCESS );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+
+exit:
+ psa_cipher_abort( &operation );
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_key_policy( int policy_usage,
+ int policy_alg,
+ int key_type,
+ HexParam_t *key_data,
+ int nonce_length_arg,
+ int tag_length_arg,
+ int exercise_alg )
+{
+ int key_slot = 1;
+ psa_key_policy_t policy;
+ psa_status_t status;
+ unsigned char nonce[16] = {0};
+ size_t nonce_length = nonce_length_arg;
+ unsigned char tag[16];
+ size_t tag_length = tag_length_arg;
+ size_t output_length;
+
+ TEST_ASSERT( nonce_length <= sizeof( nonce ) );
+ TEST_ASSERT( tag_length <= sizeof( tag ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key_data->x, key_data->len ) == PSA_SUCCESS );
+
+ status = psa_aead_encrypt( key_slot, exercise_alg,
+ nonce, nonce_length,
+ NULL, 0,
+ NULL, 0,
+ tag, tag_length,
+ &output_length );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_ENCRYPT ) != 0 )
+ TEST_ASSERT( status == PSA_SUCCESS );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+
+ memset( tag, 0, sizeof( tag ) );
+ status = psa_aead_decrypt( key_slot, exercise_alg,
+ nonce, nonce_length,
+ NULL, 0,
+ tag, tag_length,
+ NULL, 0,
+ &output_length );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_DECRYPT ) != 0 )
+ TEST_ASSERT( status == PSA_ERROR_INVALID_SIGNATURE );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+
+exit:
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void asymmetric_encryption_key_policy( int policy_usage,
+ int policy_alg,
+ int key_type,
+ HexParam_t *key_data,
+ int exercise_alg )
+{
+ int key_slot = 1;
+ psa_key_policy_t policy;
+ psa_status_t status;
+ size_t key_bits;
+ size_t buffer_length;
+ unsigned char *buffer = NULL;
+ size_t output_length;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key_data->x, key_data->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_get_key_information( key_slot,
+ NULL,
+ &key_bits ) == PSA_SUCCESS );
+ buffer_length = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits,
+ exercise_alg );
+ buffer = mbedcrypto_calloc( 1, buffer_length );
+ TEST_ASSERT( buffer != NULL );
+
+ status = psa_asymmetric_encrypt( key_slot, exercise_alg,
+ NULL, 0,
+ NULL, 0,
+ buffer, buffer_length,
+ &output_length );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_ENCRYPT ) != 0 )
+ TEST_ASSERT( status == PSA_SUCCESS );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+
+ memset( buffer, 0, buffer_length );
+ status = psa_asymmetric_decrypt( key_slot, exercise_alg,
+ buffer, buffer_length,
+ NULL, 0,
+ buffer, buffer_length,
+ &output_length );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_DECRYPT ) != 0 )
+ TEST_ASSERT( status == PSA_ERROR_INVALID_PADDING );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+
+exit:
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+ mbedcrypto_free( buffer );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void asymmetric_signature_key_policy( int policy_usage,
+ int policy_alg,
+ int key_type,
+ HexParam_t *key_data,
+ int exercise_alg )
+{
+ int key_slot = 1;
+ psa_key_policy_t policy;
+ psa_status_t status;
+ unsigned char payload[16] = {1};
+ size_t payload_length = sizeof( payload );
+ unsigned char signature[PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE] = {0};
+ size_t signature_length;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key_data->x, key_data->len ) == PSA_SUCCESS );
+
+ status = psa_asymmetric_sign( key_slot, exercise_alg,
+ payload, payload_length,
+ signature, sizeof( signature ),
+ &signature_length );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_SIGN ) != 0 )
+ TEST_ASSERT( status == PSA_SUCCESS );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+
+ memset( signature, 0, sizeof( signature ) );
+ status = psa_asymmetric_verify( key_slot, exercise_alg,
+ payload, payload_length,
+ signature, sizeof( signature ) );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_VERIFY ) != 0 )
+ TEST_ASSERT( status == PSA_ERROR_INVALID_SIGNATURE );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+
+exit:
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void derive_key_policy( int policy_usage,
+ int policy_alg,
+ int key_type,
+ HexParam_t *key_data,
+ int exercise_alg )
+{
+ int key_slot = 1;
+ psa_key_policy_t policy;
+ psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ psa_status_t status;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key_data->x, key_data->len ) == PSA_SUCCESS );
+
+ status = psa_key_derivation( &generator, key_slot,
+ exercise_alg,
+ NULL, 0,
+ NULL, 0,
+ 1 );
+ if( policy_alg == exercise_alg &&
+ ( policy_usage & PSA_KEY_USAGE_DERIVE ) != 0 )
+ TEST_ASSERT( status == PSA_SUCCESS );
+ else
+ TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
+
+exit:
+ psa_generator_abort( &generator );
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void key_lifetime( int lifetime_arg )
+{
+ int key_slot = 1;
+ psa_key_type_t key_type = PSA_ALG_CBC_BASE;
+ unsigned char key[32] = {0};
+ psa_key_lifetime_t lifetime_set = lifetime_arg;
+ psa_key_lifetime_t lifetime_get;
+
+ memset( key, 0x2a, sizeof( key ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_set_key_lifetime( key_slot,
+ lifetime_set ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key, sizeof( key ) ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_get_key_lifetime( key_slot,
+ &lifetime_get ) == PSA_SUCCESS );
+
+ TEST_ASSERT( lifetime_get == lifetime_set );
+
+exit:
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void key_lifetime_set_fail( int key_slot_arg,
+ int lifetime_arg,
+ int expected_status_arg )
+{
+ psa_key_slot_t key_slot = key_slot_arg;
+ psa_key_lifetime_t lifetime_set = lifetime_arg;
+ psa_status_t actual_status;
+ psa_status_t expected_status = expected_status_arg;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ actual_status = psa_set_key_lifetime( key_slot, lifetime_set );
+
+ if( actual_status == PSA_SUCCESS )
+ actual_status = psa_set_key_lifetime( key_slot, lifetime_set );
+
+ TEST_ASSERT( expected_status == actual_status );
+
+exit:
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void hash_setup( int alg_arg,
+ int expected_status_arg )
+{
+ psa_algorithm_t alg = alg_arg;
+ psa_status_t expected_status = expected_status_arg;
+ psa_hash_operation_t operation;
+ psa_status_t status;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ status = psa_hash_setup( &operation, alg );
+ psa_hash_abort( &operation );
+ TEST_ASSERT( status == expected_status );
+
+exit:
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void hash_finish( int alg_arg, HexParam_t *input, HexParam_t *expected_hash )
+{
+ psa_algorithm_t alg = alg_arg;
+ unsigned char actual_hash[PSA_HASH_MAX_SIZE];
+ size_t actual_hash_length;
+ psa_hash_operation_t operation;
+
+ TEST_ASSERT( expected_hash->len == PSA_HASH_SIZE( alg ) );
+ TEST_ASSERT( expected_hash->len <= PSA_HASH_MAX_SIZE );
+
+ TEST_ASSERT( input != NULL );
+ TEST_ASSERT( expected_hash != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( expected_hash->len ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_hash_setup( &operation, alg ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_hash_update( &operation,
+ input->x, input->len ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_hash_finish( &operation,
+ actual_hash, sizeof( actual_hash ),
+ &actual_hash_length ) == PSA_SUCCESS );
+ TEST_ASSERT( actual_hash_length == expected_hash->len );
+ TEST_ASSERT( memcmp( expected_hash->x, actual_hash,
+ expected_hash->len ) == 0 );
+
+exit:
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void hash_verify( int alg_arg, HexParam_t *input, HexParam_t *expected_hash )
+{
+ psa_algorithm_t alg = alg_arg;
+ psa_hash_operation_t operation;
+
+ TEST_ASSERT( expected_hash->len == PSA_HASH_SIZE( alg ) );
+ TEST_ASSERT( expected_hash->len <= PSA_HASH_MAX_SIZE );
+
+ TEST_ASSERT( input != NULL );
+ TEST_ASSERT( expected_hash != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( expected_hash->len ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_hash_setup( &operation, alg ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_hash_update( &operation,
+ input->x,
+ input->len ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_hash_verify( &operation,
+ expected_hash->x,
+ expected_hash->len ) == PSA_SUCCESS );
+
+exit:
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mac_setup( int key_type_arg,
+ HexParam_t *key,
+ int alg_arg,
+ int expected_status_arg )
+{
+ int key_slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_status_t expected_status = expected_status_arg;
+ psa_mac_operation_t operation;
+ psa_key_policy_t policy;
+ psa_status_t status;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy,
+ PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY,
+ alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key->x, key->len ) == PSA_SUCCESS );
+
+ status = psa_mac_sign_setup( &operation, key_slot, alg );
+ psa_mac_abort( &operation );
+ TEST_ASSERT( status == expected_status );
+
+exit:
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mac_verify( int key_type_arg,
+ HexParam_t *key,
+ int alg_arg,
+ HexParam_t *input,
+ HexParam_t *expected_mac )
+{
+ int key_slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_mac_operation_t operation;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( expected_mac->len <= PSA_MAC_MAX_SIZE );
+
+ TEST_ASSERT( key != NULL );
+ TEST_ASSERT( input != NULL );
+ TEST_ASSERT( expected_mac != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( expected_mac->len ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key->x, key->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_mac_verify_setup( &operation,
+ key_slot, alg ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_destroy_key( key_slot ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_mac_update( &operation,
+ input->x, input->len ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_mac_verify_finish( &operation,
+ expected_mac->x,
+ expected_mac->len ) == PSA_SUCCESS );
+
+exit:
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_setup( int key_type_arg,
+ HexParam_t *key,
+ int alg_arg,
+ int expected_status_arg )
+{
+ int key_slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_status_t expected_status = expected_status_arg;
+ psa_cipher_operation_t operation;
+ psa_key_policy_t policy;
+ psa_status_t status;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key->x, key->len ) == PSA_SUCCESS );
+
+ status = psa_cipher_encrypt_setup( &operation, key_slot, alg );
+ psa_cipher_abort( &operation );
+ TEST_ASSERT( status == expected_status );
+
+exit:
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_encrypt( int alg_arg, int key_type_arg,
+ HexParam_t *key,
+ HexParam_t *input, HexParam_t *expected_output,
+ int expected_status_arg )
+{
+ int key_slot = 1;
+ psa_status_t status;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_status_t expected_status = expected_status_arg;
+ unsigned char iv[16] = {0};
+ size_t iv_size;
+ unsigned char *output = NULL;
+ size_t output_buffer_size = 0;
+ size_t function_output_length = 0;
+ size_t total_output_length = 0;
+ psa_cipher_operation_t operation;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key != NULL );
+ TEST_ASSERT( input != NULL );
+ TEST_ASSERT( expected_output != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( expected_output->len ) );
+
+ iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
+ memset( iv, 0x2a, iv_size );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key->x, key->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_encrypt_setup( &operation,
+ key_slot, alg ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_set_iv( &operation,
+ iv, iv_size ) == PSA_SUCCESS );
+ output_buffer_size = (size_t) input->len +
+ PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
+ output = mbedcrypto_calloc( 1, output_buffer_size );
+ TEST_ASSERT( output != NULL );
+
+ TEST_ASSERT( psa_cipher_update( &operation,
+ input->x, input->len,
+ output, output_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ total_output_length += function_output_length;
+ status = psa_cipher_finish( &operation,
+ output + function_output_length,
+ output_buffer_size,
+ &function_output_length );
+ total_output_length += function_output_length;
+
+ TEST_ASSERT( status == expected_status );
+ if( expected_status == PSA_SUCCESS )
+ {
+ TEST_ASSERT( psa_cipher_abort( &operation ) == PSA_SUCCESS );
+ TEST_ASSERT( total_output_length == expected_output->len );
+ TEST_ASSERT( memcmp( expected_output->x, output,
+ expected_output->len ) == 0 );
+ }
+
+exit:
+ mbedcrypto_free( output );
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_encrypt_multipart( int alg_arg, int key_type_arg,
+ HexParam_t *key,
+ HexParam_t *input,
+ int first_part_size,
+ HexParam_t *expected_output )
+{
+ int key_slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ unsigned char iv[16] = {0};
+ size_t iv_size;
+ unsigned char *output = NULL;
+ size_t output_buffer_size = 0;
+ size_t function_output_length = 0;
+ size_t total_output_length = 0;
+ psa_cipher_operation_t operation;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key != NULL );
+ TEST_ASSERT( input != NULL );
+ TEST_ASSERT( expected_output != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( expected_output->len ) );
+
+ iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
+ memset( iv, 0x2a, iv_size );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key->x, key->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_encrypt_setup( &operation,
+ key_slot, alg ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_set_iv( &operation,
+ iv, sizeof( iv ) ) == PSA_SUCCESS );
+ output_buffer_size = (size_t) input->len +
+ PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
+ output = mbedcrypto_calloc( 1, output_buffer_size );
+ TEST_ASSERT( output != NULL );
+
+ TEST_ASSERT( (unsigned int) first_part_size < input->len );
+ TEST_ASSERT( psa_cipher_update( &operation, input->x, first_part_size,
+ output, output_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ total_output_length += function_output_length;
+ TEST_ASSERT( psa_cipher_update( &operation,
+ input->x + first_part_size,
+ input->len - first_part_size,
+ output, output_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ total_output_length += function_output_length;
+ TEST_ASSERT( psa_cipher_finish( &operation,
+ output + function_output_length,
+ output_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ total_output_length += function_output_length;
+ TEST_ASSERT( psa_cipher_abort( &operation ) == PSA_SUCCESS );
+
+ TEST_ASSERT( total_output_length == expected_output->len );
+ TEST_ASSERT( memcmp( expected_output->x, output,
+ expected_output->len ) == 0 );
+
+exit:
+ mbedcrypto_free( output );
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_decrypt_multipart( int alg_arg, int key_type_arg,
+ HexParam_t *key,
+ HexParam_t *input,
+ int first_part_size,
+ HexParam_t *expected_output )
+{
+ int key_slot = 1;
+
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ unsigned char iv[16] = {0};
+ size_t iv_size;
+ unsigned char *output = NULL;
+ size_t output_buffer_size = 0;
+ size_t function_output_length = 0;
+ size_t total_output_length = 0;
+ psa_cipher_operation_t operation;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key != NULL );
+ TEST_ASSERT( input != NULL );
+ TEST_ASSERT( expected_output != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( expected_output->len ) );
+
+ iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
+ memset( iv, 0x2a, iv_size );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key->x, key->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_decrypt_setup( &operation,
+ key_slot, alg ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_set_iv( &operation,
+ iv, sizeof( iv ) ) == PSA_SUCCESS );
+
+ output_buffer_size = (size_t) input->len +
+ PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
+ output = mbedcrypto_calloc( 1, output_buffer_size );
+ TEST_ASSERT( output != NULL );
+
+ TEST_ASSERT( (unsigned int) first_part_size < input->len );
+ TEST_ASSERT( psa_cipher_update( &operation,
+ input->x, first_part_size,
+ output, output_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ total_output_length += function_output_length;
+ TEST_ASSERT( psa_cipher_update( &operation,
+ input->x + first_part_size,
+ input->len - first_part_size,
+ output, output_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ total_output_length += function_output_length;
+ TEST_ASSERT( psa_cipher_finish( &operation,
+ output + function_output_length,
+ output_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ total_output_length += function_output_length;
+ TEST_ASSERT( psa_cipher_abort( &operation ) == PSA_SUCCESS );
+
+ TEST_ASSERT( total_output_length == expected_output->len );
+ TEST_ASSERT( memcmp( expected_output->x, output,
+ expected_output->len ) == 0 );
+
+exit:
+ mbedcrypto_free( output );
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_decrypt( int alg_arg, int key_type_arg,
+ HexParam_t *key,
+ HexParam_t *input, HexParam_t *expected_output,
+ int expected_status_arg )
+{
+ int key_slot = 1;
+ psa_status_t status;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_status_t expected_status = expected_status_arg;
+ unsigned char iv[16] = {0};
+ size_t iv_size;
+ unsigned char *output = NULL;
+ size_t output_buffer_size = 0;
+ size_t function_output_length = 0;
+ size_t total_output_length = 0;
+ psa_cipher_operation_t operation;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key != NULL );
+ TEST_ASSERT( input != NULL );
+ TEST_ASSERT( expected_output != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( expected_output->len ) );
+
+ iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
+ memset( iv, 0x2a, iv_size );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key->x, key->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_decrypt_setup( &operation,
+ key_slot, alg ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_set_iv( &operation,
+ iv, iv_size ) == PSA_SUCCESS );
+
+ output_buffer_size = (size_t) input->len +
+ PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
+ output = mbedcrypto_calloc( 1, output_buffer_size );
+ TEST_ASSERT( output != NULL );
+
+ TEST_ASSERT( psa_cipher_update( &operation,
+ input->x, input->len,
+ output, output_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ total_output_length += function_output_length;
+ status = psa_cipher_finish( &operation,
+ output + function_output_length,
+ output_buffer_size,
+ &function_output_length );
+ total_output_length += function_output_length;
+ TEST_ASSERT( status == expected_status );
+
+ if( expected_status == PSA_SUCCESS )
+ {
+ TEST_ASSERT( psa_cipher_abort( &operation ) == PSA_SUCCESS );
+ TEST_ASSERT( total_output_length == expected_output->len );
+ TEST_ASSERT( memcmp( expected_output->x, output,
+ expected_output->len ) == 0 );
+ }
+
+exit:
+ mbedcrypto_free( output );
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_verify_output( int alg_arg, int key_type_arg,
+ HexParam_t *key,
+ HexParam_t *input )
+{
+ int key_slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ unsigned char iv[16] = {0};
+ size_t iv_size = 16;
+ size_t iv_length = 0;
+ unsigned char *output1 = NULL;
+ size_t output1_size = 0;
+ size_t output1_length = 0;
+ unsigned char *output2 = NULL;
+ size_t output2_size = 0;
+ size_t output2_length = 0;
+ size_t function_output_length = 0;
+ psa_cipher_operation_t operation1;
+ psa_cipher_operation_t operation2;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key != NULL );
+ TEST_ASSERT( input != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input->len ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key->x, key->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_encrypt_setup( &operation1,
+ key_slot, alg ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_cipher_decrypt_setup( &operation2,
+ key_slot, alg ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_generate_iv( &operation1,
+ iv, iv_size,
+ &iv_length ) == PSA_SUCCESS );
+ output1_size = (size_t) input->len +
+ PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
+ output1 = mbedcrypto_calloc( 1, output1_size );
+ TEST_ASSERT( output1 != NULL );
+
+ TEST_ASSERT( psa_cipher_update( &operation1, input->x, input->len,
+ output1, output1_size,
+ &output1_length ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_cipher_finish( &operation1,
+ output1 + output1_length, output1_size,
+ &function_output_length ) == PSA_SUCCESS );
+
+ output1_length += function_output_length;
+
+ TEST_ASSERT( psa_cipher_abort( &operation1 ) == PSA_SUCCESS );
+
+ output2_size = output1_length;
+ output2 = mbedcrypto_calloc( 1, output2_size );
+ TEST_ASSERT( output2 != NULL );
+
+ TEST_ASSERT( psa_cipher_set_iv( &operation2,
+ iv, iv_length ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_cipher_update( &operation2, output1, output1_length,
+ output2, output2_size,
+ &output2_length ) == PSA_SUCCESS );
+ function_output_length = 0;
+ TEST_ASSERT( psa_cipher_finish( &operation2,
+ output2 + output2_length,
+ output2_size,
+ &function_output_length ) == PSA_SUCCESS );
+
+ output2_length += function_output_length;
+
+ TEST_ASSERT( psa_cipher_abort( &operation2 ) == PSA_SUCCESS );
+
+ TEST_ASSERT( input->len == output2_length );
+ TEST_ASSERT( memcmp( input->x, output2, input->len ) == 0 );
+
+exit:
+ mbedcrypto_free( output1 );
+ mbedcrypto_free( output2 );
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_verify_output_multipart( int alg_arg,
+ int key_type_arg,
+ HexParam_t *key,
+ HexParam_t *input,
+ int first_part_size )
+{
+ int key_slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ unsigned char iv[16] = {0};
+ size_t iv_size = 16;
+ size_t iv_length = 0;
+ unsigned char *output1 = NULL;
+ size_t output1_buffer_size = 0;
+ size_t output1_length = 0;
+ unsigned char *output2 = NULL;
+ size_t output2_buffer_size = 0;
+ size_t output2_length = 0;
+ size_t function_output_length;
+ psa_cipher_operation_t operation1;
+ psa_cipher_operation_t operation2;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key != NULL );
+ TEST_ASSERT( input != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input->len ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg );
+ TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( key_slot, key_type,
+ key->x, key->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_encrypt_setup( &operation1,
+ key_slot, alg ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_cipher_decrypt_setup( &operation2,
+ key_slot, alg ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_generate_iv( &operation1,
+ iv, iv_size,
+ &iv_length ) == PSA_SUCCESS );
+ output1_buffer_size = (size_t) input->len +
+ PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
+ output1 = mbedcrypto_calloc( 1, output1_buffer_size );
+ TEST_ASSERT( output1 != NULL );
+
+ TEST_ASSERT( (unsigned int) first_part_size < input->len );
+
+ TEST_ASSERT( psa_cipher_update( &operation1, input->x, first_part_size,
+ output1, output1_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ output1_length += function_output_length;
+
+ TEST_ASSERT( psa_cipher_update( &operation1,
+ input->x + first_part_size,
+ input->len - first_part_size,
+ output1, output1_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ output1_length += function_output_length;
+
+ TEST_ASSERT( psa_cipher_finish( &operation1,
+ output1 + output1_length,
+ output1_buffer_size - output1_length,
+ &function_output_length ) == PSA_SUCCESS );
+ output1_length += function_output_length;
+
+ TEST_ASSERT( psa_cipher_abort( &operation1 ) == PSA_SUCCESS );
+
+ output2_buffer_size = output1_length;
+ output2 = mbedcrypto_calloc( 1, output2_buffer_size );
+ TEST_ASSERT( output2 != NULL );
+
+ TEST_ASSERT( psa_cipher_set_iv( &operation2,
+ iv, iv_length ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_cipher_update( &operation2, output1, first_part_size,
+ output2, output2_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ output2_length += function_output_length;
+
+ TEST_ASSERT( psa_cipher_update( &operation2,
+ output1 + first_part_size,
+ output1_length - first_part_size,
+ output2, output2_buffer_size,
+ &function_output_length ) == PSA_SUCCESS );
+ output2_length += function_output_length;
+
+ TEST_ASSERT( psa_cipher_finish( &operation2,
+ output2 + output2_length,
+ output2_buffer_size - output2_length,
+ &function_output_length ) == PSA_SUCCESS );
+ output2_length += function_output_length;
+
+ TEST_ASSERT( psa_cipher_abort( &operation2 ) == PSA_SUCCESS );
+
+ TEST_ASSERT( input->len == output2_length );
+ TEST_ASSERT( memcmp( input->x, output2, input->len ) == 0 );
+
+exit:
+ mbedcrypto_free( output1 );
+ mbedcrypto_free( output2 );
+ psa_destroy_key( key_slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_encrypt_decrypt( int key_type_arg,
+ HexParam_t * key_data,
+ int alg_arg,
+ HexParam_t * input_data,
+ HexParam_t * nonce,
+ HexParam_t * additional_data,
+ int expected_result_arg )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ unsigned char *output_data = NULL;
+ size_t output_size = 0;
+ size_t output_length = 0;
+ unsigned char *output_data2 = NULL;
+ size_t output_length2 = 0;
+ size_t tag_length = 16;
+ psa_status_t expected_result = expected_result_arg;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key_data != NULL );
+ TEST_ASSERT( input_data != NULL );
+ TEST_ASSERT( nonce != NULL );
+ TEST_ASSERT( additional_data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( nonce->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( additional_data->len ) );
+
+ output_size = input_data->len + tag_length;
+ output_data = mbedcrypto_calloc( 1, output_size );
+ TEST_ASSERT( output_data != NULL );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy,
+ PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
+ alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x, key_data->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_aead_encrypt( slot, alg,
+ nonce->x, nonce->len,
+ additional_data->x,
+ additional_data->len,
+ input_data->x, input_data->len,
+ output_data, output_size,
+ &output_length ) == expected_result );
+
+ if( PSA_SUCCESS == expected_result )
+ {
+ output_data2 = mbedcrypto_calloc( 1, output_length );
+ TEST_ASSERT( output_data2 != NULL );
+
+ TEST_ASSERT( psa_aead_decrypt( slot, alg,
+ nonce->x, nonce->len,
+ additional_data->x,
+ additional_data->len,
+ output_data, output_length,
+ output_data2, output_length,
+ &output_length2 ) == expected_result );
+
+ TEST_ASSERT( memcmp( input_data->x, output_data2,
+ input_data->len ) == 0 );
+ }
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_free( output_data );
+ mbedcrypto_free( output_data2 );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_encrypt( int key_type_arg, HexParam_t * key_data,
+ int alg_arg, HexParam_t * input_data,
+ HexParam_t * additional_data, HexParam_t * nonce,
+ HexParam_t * expected_result )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ unsigned char *output_data = NULL;
+ size_t output_size = 0;
+ size_t output_length = 0;
+ size_t tag_length = 16;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key_data != NULL );
+ TEST_ASSERT( input_data != NULL );
+ TEST_ASSERT( additional_data != NULL );
+ TEST_ASSERT( nonce != NULL );
+ TEST_ASSERT( expected_result != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( additional_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( nonce->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( expected_result->len ) );
+
+ output_size = input_data->len + tag_length;
+ output_data = mbedcrypto_calloc( 1, output_size );
+ TEST_ASSERT( output_data != NULL );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT , alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_aead_encrypt( slot, alg,
+ nonce->x, nonce->len,
+ additional_data->x, additional_data->len,
+ input_data->x, input_data->len,
+ output_data, output_size,
+ &output_length ) == PSA_SUCCESS );
+
+ TEST_ASSERT( memcmp( output_data, expected_result->x,
+ output_length ) == 0 );
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_free( output_data );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_decrypt( int key_type_arg, HexParam_t * key_data,
+ int alg_arg, HexParam_t * input_data,
+ HexParam_t * additional_data, HexParam_t * nonce,
+ HexParam_t * expected_data, int expected_result_arg )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ unsigned char *output_data = NULL;
+ size_t output_size = 0;
+ size_t output_length = 0;
+ size_t tag_length = 16;
+ psa_key_policy_t policy;
+ psa_status_t expected_result = expected_result_arg;
+
+ TEST_ASSERT( key_data != NULL );
+ TEST_ASSERT( input_data != NULL );
+ TEST_ASSERT( additional_data != NULL );
+ TEST_ASSERT( nonce != NULL );
+ TEST_ASSERT( expected_data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( additional_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( nonce->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( expected_data->len ) );
+
+ output_size = input_data->len + tag_length;
+ output_data = mbedcrypto_calloc( 1, output_size );
+ TEST_ASSERT( output_data != NULL );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT , alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_aead_decrypt( slot, alg,
+ nonce->x, nonce->len,
+ additional_data->x,
+ additional_data->len,
+ input_data->x, input_data->len,
+ output_data, output_size,
+ &output_length ) == expected_result );
+
+ if( expected_result == PSA_SUCCESS )
+ {
+ TEST_ASSERT( memcmp( output_data, expected_data->x,
+ output_length ) == 0 );
+ }
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_free( output_data );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void signature_size( int type_arg,
+ int bits,
+ int alg_arg,
+ int expected_size_arg )
+{
+ psa_key_type_t type = type_arg;
+ psa_algorithm_t alg = alg_arg;
+ size_t actual_size = PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( type, bits, alg );
+ TEST_ASSERT( actual_size == (size_t) expected_size_arg );
+exit:
+ ;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void sign_deterministic( int key_type_arg, HexParam_t *key_data,
+ int alg_arg, HexParam_t *input_data,
+ HexParam_t *output_data )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ size_t key_bits;
+ unsigned char *signature = NULL;
+ size_t signature_size;
+ size_t signature_length = 0xdeadbeef;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key_data != NULL );
+ TEST_ASSERT( input_data != NULL );
+ TEST_ASSERT( output_data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( output_data->len ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_get_key_information( slot,
+ NULL,
+ &key_bits ) == PSA_SUCCESS );
+
+ /* Allocate a buffer which has the size advertized by the
+ * library. */
+ signature_size = PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type,
+ key_bits, alg );
+ TEST_ASSERT( signature_size != 0 );
+ TEST_ASSERT( signature_size <= PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE );
+ signature = mbedcrypto_calloc( 1, signature_size );
+ TEST_ASSERT( signature != NULL );
+
+ /* Perform the signature. */
+ TEST_ASSERT( psa_asymmetric_sign( slot, alg,
+ input_data->x, input_data->len,
+ signature, signature_size,
+ &signature_length ) == PSA_SUCCESS );
+ /* Verify that the signature is what is expected. */
+ TEST_ASSERT( signature_length == output_data->len );
+ TEST_ASSERT( memcmp( signature, output_data->x,
+ output_data->len ) == 0 );
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_free( signature );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void sign_fail( int key_type_arg, HexParam_t *key_data,
+ int alg_arg, HexParam_t *input_data,
+ int signature_size_arg, int expected_status_arg )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ size_t signature_size = signature_size_arg;
+ psa_status_t actual_status;
+ psa_status_t expected_status = expected_status_arg;
+ unsigned char *signature = NULL;
+ size_t signature_length = 0xdeadbeef;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key_data != NULL );
+ TEST_ASSERT( input_data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input_data->len ) );
+
+ signature = mbedcrypto_calloc( 1, signature_size );
+ TEST_ASSERT( signature != NULL );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ actual_status = psa_asymmetric_sign( slot, alg,
+ input_data->x, input_data->len,
+ signature, signature_size,
+ &signature_length );
+ TEST_ASSERT( actual_status == expected_status );
+ /* The value of *signature_length is unspecified on error, but
+ * whatever it is, it should be less than signature_size, so that
+ * if the caller tries to read *signature_length bytes without
+ * checking the error code then they don't overflow a buffer. */
+ TEST_ASSERT( signature_length <= signature_size );
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_free( signature );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void sign_verify( int key_type_arg, HexParam_t *key_data,
+ int alg_arg, HexParam_t *input_data )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ size_t key_bits;
+ unsigned char *signature = NULL;
+ size_t signature_size;
+ size_t signature_length = 0xdeadbeef;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy,
+ PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY,
+ alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_get_key_information( slot,
+ NULL,
+ &key_bits ) == PSA_SUCCESS );
+
+ /* Allocate a buffer which has the size advertized by the
+ * library. */
+ signature_size = PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type,
+ key_bits, alg );
+ TEST_ASSERT( signature_size != 0 );
+ TEST_ASSERT( signature_size <= PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE );
+ signature = mbedcrypto_calloc( 1, signature_size );
+ TEST_ASSERT( signature != NULL );
+
+ /* Perform the signature. */
+ TEST_ASSERT( psa_asymmetric_sign( slot, alg,
+ input_data->x, input_data->len,
+ signature, signature_size,
+ &signature_length ) == PSA_SUCCESS );
+ /* Check that the signature length looks sensible. */
+ TEST_ASSERT( signature_length <= signature_size );
+ TEST_ASSERT( signature_length > 0 );
+
+ /* Use the library to verify that the signature is correct. */
+ TEST_ASSERT( psa_asymmetric_verify(
+ slot, alg,
+ input_data->x, input_data->len,
+ signature, signature_length ) == PSA_SUCCESS );
+
+ if( input_data->len != 0 )
+ {
+ /* Flip a bit in the input and verify that the signature is now
+ * detected as invalid. Flip a bit at the beginning, not at the end,
+ * because ECDSA may ignore the last few bits of the input. */
+ input_data->x[0] ^= 1;
+ TEST_ASSERT( psa_asymmetric_verify(
+ slot, alg,
+ input_data->x, input_data->len,
+ signature,
+ signature_length ) == PSA_ERROR_INVALID_SIGNATURE );
+ }
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_free( signature );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void asymmetric_verify( int key_type_arg, HexParam_t *key_data,
+ int alg_arg, HexParam_t *hash_data,
+ HexParam_t *signature_data )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( signature_data->len <= PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE );
+
+ TEST_ASSERT( key_data != NULL );
+ TEST_ASSERT( hash_data != NULL );
+ TEST_ASSERT( signature_data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( hash_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( signature_data->len ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_asymmetric_verify( slot, alg,
+ hash_data->x, hash_data->len,
+ signature_data->x,
+ signature_data->len ) == PSA_SUCCESS );
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void asymmetric_verify_fail( int key_type_arg, HexParam_t *key_data,
+ int alg_arg, HexParam_t *hash_data,
+ HexParam_t *signature_data,
+ int expected_status_arg )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_status_t actual_status;
+ psa_status_t expected_status = expected_status_arg;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key_data != NULL );
+ TEST_ASSERT( hash_data != NULL );
+ TEST_ASSERT( signature_data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( hash_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( signature_data->len ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ actual_status = psa_asymmetric_verify( slot, alg,
+ hash_data->x, hash_data->len,
+ signature_data->x,
+ signature_data->len );
+
+ TEST_ASSERT( actual_status == expected_status );
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void asymmetric_encrypt( int key_type_arg,
+ HexParam_t *key_data,
+ int alg_arg,
+ HexParam_t *input_data,
+ HexParam_t *label,
+ int expected_output_length_arg,
+ int expected_status_arg )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ size_t expected_output_length = expected_output_length_arg;
+ size_t key_bits;
+ unsigned char *output = NULL;
+ size_t output_size;
+ size_t output_length = ~0;
+ psa_status_t actual_status;
+ psa_status_t expected_status = expected_status_arg;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ /* Import the key */
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ /* Determine the maximum output length */
+ TEST_ASSERT( psa_get_key_information( slot,
+ NULL,
+ &key_bits ) == PSA_SUCCESS );
+ output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, alg );
+ output = mbedcrypto_calloc( 1, output_size );
+ TEST_ASSERT( output_size == 0 || output != NULL );
+
+ /* Encrypt the input */
+ actual_status = psa_asymmetric_encrypt( slot, alg,
+ input_data->x, input_data->len,
+ label->x, label->len,
+ output, output_size,
+ &output_length );
+ TEST_ASSERT( actual_status == expected_status );
+ TEST_ASSERT( output_length == expected_output_length );
+
+ /* If the label is empty, the test framework puts a non-null pointer
+ * in label->x. Test that a null pointer works as well. */
+ if( label->len == 0 )
+ {
+ output_length = ~0;
+ memset( output, 0, output_size );
+ actual_status = psa_asymmetric_encrypt( slot, alg,
+ input_data->x, input_data->len,
+ NULL, label->len,
+ output, output_size,
+ &output_length );
+ TEST_ASSERT( actual_status == expected_status );
+ TEST_ASSERT( output_length == expected_output_length );
+ }
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_free( output );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void asymmetric_encrypt_decrypt( int key_type_arg,
+ HexParam_t *key_data,
+ int alg_arg,
+ HexParam_t *input_data,
+ HexParam_t *label )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ size_t key_bits;
+ unsigned char *output = NULL;
+ size_t output_size;
+ size_t output_length = ~0;
+ unsigned char *output2 = NULL;
+ size_t output2_size;
+ size_t output2_length = ~0;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key_data != NULL );
+ TEST_ASSERT( input_data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input_data->len ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy,
+ PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
+ alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+
+ /* Determine the maximum ciphertext length */
+ TEST_ASSERT( psa_get_key_information( slot,
+ NULL,
+ &key_bits ) == PSA_SUCCESS );
+ output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, alg );
+ output = mbedcrypto_calloc( 1, output_size );
+ TEST_ASSERT( output != NULL );
+ output2_size = input_data->len;
+ output2 = mbedcrypto_calloc( 1, output2_size );
+ TEST_ASSERT( output2 != NULL );
+
+ /* We test encryption by checking that encrypt-then-decrypt gives back
+ * the original plaintext because of the non-optional random
+ * part of encryption process which prevents using fixed vectors. */
+ TEST_ASSERT( psa_asymmetric_encrypt( slot, alg,
+ input_data->x, input_data->len,
+ label->x, label->len,
+ output, output_size,
+ &output_length ) == PSA_SUCCESS );
+ /* We don't know what ciphertext length to expect, but check that
+ * it looks sensible. */
+ TEST_ASSERT( output_length <= output_size );
+
+ TEST_ASSERT( psa_asymmetric_decrypt( slot, alg,
+ output, output_length,
+ label->x, label->len,
+ output2, output2_size,
+ &output2_length ) == PSA_SUCCESS );
+ TEST_ASSERT( output2_length == input_data->len );
+ TEST_ASSERT( memcmp( input_data->x, output2,
+ input_data->len ) == 0 );
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_free( output );
+ mbedcrypto_free( output2 );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void asymmetric_decrypt( int key_type_arg,
+ HexParam_t *key_data,
+ int alg_arg,
+ HexParam_t *input_data,
+ HexParam_t *label,
+ HexParam_t *expected_data )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ unsigned char *output = NULL;
+ size_t output_size = 0;
+ size_t output_length = ~0;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key_data != NULL );
+ TEST_ASSERT( input_data != NULL );
+ TEST_ASSERT( expected_data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( expected_data->len ) );
+
+ output_size = key_data->len;
+ output = mbedcrypto_calloc( 1, output_size );
+ TEST_ASSERT( output != NULL );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_asymmetric_decrypt( slot, alg,
+ input_data->x, input_data->len,
+ label->x, label->len,
+ output,
+ output_size,
+ &output_length ) == PSA_SUCCESS );
+ TEST_ASSERT( expected_data->len == output_length );
+ TEST_ASSERT( memcmp( expected_data->x, output, output_length ) == 0 );
+
+ /* If the label is empty, the test framework puts a non-null pointer
+ * in label->x. Test that a null pointer works as well. */
+ if( label->len == 0 )
+ {
+ output_length = ~0;
+ memset( output, 0, output_size );
+ TEST_ASSERT( psa_asymmetric_decrypt( slot, alg,
+ input_data->x, input_data->len,
+ NULL, label->len,
+ output,
+ output_size,
+ &output_length ) == PSA_SUCCESS );
+ TEST_ASSERT( expected_data->len == output_length );
+ TEST_ASSERT( memcmp( expected_data->x, output, output_length ) == 0 );
+ }
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_free( output );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void asymmetric_decrypt_fail( int key_type_arg,
+ HexParam_t *key_data,
+ int alg_arg,
+ HexParam_t *input_data,
+ HexParam_t *label,
+ int expected_status_arg )
+{
+ int slot = 1;
+ psa_key_type_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ unsigned char *output = NULL;
+ size_t output_size = 0;
+ size_t output_length = ~0;
+ psa_status_t actual_status;
+ psa_status_t expected_status = expected_status_arg;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( key_data != NULL );
+ TEST_ASSERT( input_data != NULL );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( key_data->len ) );
+ TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( input_data->len ) );
+
+ output_size = key_data->len;
+ output = mbedcrypto_calloc( 1, output_size );
+ TEST_ASSERT( output != NULL );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ actual_status = psa_asymmetric_decrypt( slot, alg,
+ input_data->x, input_data->len,
+ label->x, label->len,
+ output, output_size,
+ &output_length );
+ TEST_ASSERT( actual_status == expected_status );
+ TEST_ASSERT( output_length <= output_size );
+
+ /* If the label is empty, the test framework puts a non-null pointer
+ * in label->x. Test that a null pointer works as well. */
+ if( label->len == 0 )
+ {
+ output_length = ~0;
+ memset( output, 0, output_size );
+ actual_status = psa_asymmetric_decrypt( slot, alg,
+ input_data->x, input_data->len,
+ NULL, label->len,
+ output, output_size,
+ &output_length );
+ TEST_ASSERT( actual_status == expected_status );
+ TEST_ASSERT( output_length <= output_size );
+ }
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_free( output );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void derive_setup( int key_type_arg,
+ HexParam_t *key_data,
+ int alg_arg,
+ HexParam_t *salt,
+ HexParam_t *label,
+ int requested_capacity_arg,
+ int expected_status_arg )
+{
+ psa_key_slot_t slot = 1;
+ size_t key_type = key_type_arg;
+ psa_algorithm_t alg = alg_arg;
+ size_t requested_capacity = requested_capacity_arg;
+ psa_status_t expected_status = expected_status_arg;
+ psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, key_type,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_key_derivation( &generator, slot, alg,
+ salt->x, salt->len,
+ label->x, label->len,
+ requested_capacity ) == expected_status );
+
+exit:
+ psa_generator_abort( &generator );
+ psa_destroy_key( slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void derive_output( int alg_arg,
+ HexParam_t *key_data,
+ HexParam_t *salt,
+ HexParam_t *label,
+ int requested_capacity_arg,
+ HexParam_t *expected_output1,
+ HexParam_t *expected_output2 )
+{
+ psa_key_slot_t slot = 1;
+ psa_algorithm_t alg = alg_arg;
+ size_t requested_capacity = requested_capacity_arg;
+ psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ uint8_t *expected_outputs[2] =
+ {expected_output1->x, expected_output2->x};
+ size_t output_sizes[2] =
+ {expected_output1->len, expected_output2->len};
+ size_t output_buffer_size = 0;
+ uint8_t *output_buffer = NULL;
+ size_t expected_capacity;
+ size_t current_capacity;
+ psa_key_policy_t policy;
+ psa_status_t status;
+ unsigned i;
+
+ for( i = 0; i < ARRAY_LENGTH( expected_outputs ); i++ )
+ {
+ if( output_sizes[i] > output_buffer_size )
+ output_buffer_size = output_sizes[i];
+ if( output_sizes[i] == 0 )
+ expected_outputs[i] = NULL;
+ }
+ output_buffer = mbedcrypto_calloc( 1, output_buffer_size );
+ TEST_ASSERT( output_buffer != NULL );
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, PSA_KEY_TYPE_DERIVE,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ /* Extraction phase. */
+ TEST_ASSERT( psa_key_derivation( &generator, slot, alg,
+ salt->x, salt->len,
+ label->x, label->len,
+ requested_capacity ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_get_generator_capacity( &generator,
+ ¤t_capacity ) ==
+ PSA_SUCCESS );
+ TEST_ASSERT( current_capacity == requested_capacity );
+ expected_capacity = requested_capacity;
+
+ /* Expansion phase. */
+ for( i = 0; i < ARRAY_LENGTH( expected_outputs ); i++ )
+ {
+ /* Read some bytes. */
+ status = psa_generator_read( &generator,
+ output_buffer, output_sizes[i] );
+ if( expected_capacity == 0 && output_sizes[i] == 0 )
+ {
+ /* Reading 0 bytes when 0 bytes are available can go either way. */
+ TEST_ASSERT( status == PSA_SUCCESS ||
+ status == PSA_ERROR_INSUFFICIENT_CAPACITY );
+ continue;
+ }
+ else if( expected_capacity == 0 ||
+ output_sizes[i] > expected_capacity )
+ {
+ /* Capacity exceeded. */
+ TEST_ASSERT( status == PSA_ERROR_INSUFFICIENT_CAPACITY );
+ expected_capacity = 0;
+ continue;
+ }
+ /* Success. Check the read data. */
+ TEST_ASSERT( status == PSA_SUCCESS );
+ if( output_sizes[i] != 0 )
+ TEST_ASSERT( memcmp( output_buffer, expected_outputs[i],
+ output_sizes[i] ) == 0 );
+ /* Check the generator status. */
+ expected_capacity -= output_sizes[i];
+ TEST_ASSERT( psa_get_generator_capacity( &generator,
+ ¤t_capacity ) ==
+ PSA_SUCCESS );
+ TEST_ASSERT( expected_capacity == current_capacity );
+ }
+ TEST_ASSERT( psa_generator_abort( &generator ) == PSA_SUCCESS );
+
+exit:
+ mbedcrypto_free( output_buffer );
+ psa_generator_abort( &generator );
+ psa_destroy_key( slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void derive_full( int alg_arg,
+ HexParam_t *key_data,
+ HexParam_t *salt,
+ HexParam_t *label,
+ int requested_capacity_arg )
+{
+ psa_key_slot_t slot = 1;
+ psa_algorithm_t alg = alg_arg;
+ size_t requested_capacity = requested_capacity_arg;
+ psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ unsigned char output_buffer[16];
+ size_t expected_capacity = requested_capacity;
+ size_t current_capacity;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_import_key( slot, PSA_KEY_TYPE_DERIVE,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ /* Extraction phase. */
+ TEST_ASSERT( psa_key_derivation( &generator, slot, alg,
+ salt->x, salt->len,
+ label->x, label->len,
+ requested_capacity ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_get_generator_capacity( &generator,
+ ¤t_capacity ) ==
+ PSA_SUCCESS );
+ TEST_ASSERT( current_capacity == expected_capacity );
+
+ /* Expansion phase. */
+ while( current_capacity > 0 )
+ {
+ size_t read_size = sizeof( output_buffer );
+ if( read_size > current_capacity )
+ read_size = current_capacity;
+ TEST_ASSERT( psa_generator_read( &generator,
+ output_buffer,
+ read_size ) == PSA_SUCCESS );
+ expected_capacity -= read_size;
+ TEST_ASSERT( psa_get_generator_capacity( &generator,
+ ¤t_capacity ) ==
+ PSA_SUCCESS );
+ TEST_ASSERT( current_capacity == expected_capacity );
+ }
+
+ /* Check that the generator refuses to go over capacity. */
+ TEST_ASSERT( psa_generator_read( &generator,
+ output_buffer,
+ 1 ) == PSA_ERROR_INSUFFICIENT_CAPACITY );
+
+ TEST_ASSERT( psa_generator_abort( &generator ) == PSA_SUCCESS );
+
+exit:
+ psa_generator_abort( &generator );
+ psa_destroy_key( slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void derive_key_exercise( int alg_arg,
+ HexParam_t *key_data,
+ HexParam_t *salt,
+ HexParam_t *label,
+ int derived_type_arg,
+ int derived_bits_arg,
+ int derived_usage_arg,
+ int derived_alg_arg )
+{
+ psa_key_slot_t base_key = 1;
+ psa_key_slot_t derived_key = 2;
+ psa_algorithm_t alg = alg_arg;
+ psa_key_type_t derived_type = derived_type_arg;
+ size_t derived_bits = derived_bits_arg;
+ psa_key_usage_t derived_usage = derived_usage_arg;
+ psa_algorithm_t derived_alg = derived_alg_arg;
+ size_t capacity = PSA_BITS_TO_BYTES( derived_bits );
+ psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ psa_key_policy_t policy;
+ psa_key_type_t got_type;
+ size_t got_bits;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
+ TEST_ASSERT( psa_set_key_policy( base_key, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_import_key( base_key, PSA_KEY_TYPE_DERIVE,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ /* Derive a key. */
+ TEST_ASSERT( psa_key_derivation( &generator, base_key, alg,
+ salt->x, salt->len,
+ label->x, label->len,
+ capacity ) == PSA_SUCCESS );
+ psa_key_policy_set_usage( &policy, derived_usage, derived_alg );
+ TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_import_key( derived_key,
+ derived_type,
+ derived_bits,
+ &generator ) == PSA_SUCCESS );
+
+ /* Test the key information */
+ TEST_ASSERT( psa_get_key_information( derived_key,
+ &got_type,
+ &got_bits ) == PSA_SUCCESS );
+ TEST_ASSERT( got_type == derived_type );
+ TEST_ASSERT( got_bits == derived_bits );
+
+ /* Exercise the derived key. */
+ if( ! exercise_key( derived_key, derived_usage, derived_alg ) )
+ goto exit;
+
+exit:
+ psa_generator_abort( &generator );
+ psa_destroy_key( base_key );
+ psa_destroy_key( derived_key );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void derive_key_export( int alg_arg,
+ HexParam_t *key_data,
+ HexParam_t *salt,
+ HexParam_t *label,
+ int bytes1_arg,
+ int bytes2_arg )
+{
+ psa_key_slot_t base_key = 1;
+ psa_key_slot_t derived_key = 2;
+ psa_algorithm_t alg = alg_arg;
+ size_t bytes1 = bytes1_arg;
+ size_t bytes2 = bytes2_arg;
+ size_t capacity = bytes1 + bytes2;
+ psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ uint8_t *output_buffer = mbedcrypto_calloc( 1, capacity );
+ uint8_t *export_buffer = mbedcrypto_calloc( 1, capacity );
+ psa_key_policy_t policy;
+ size_t length;
+
+ TEST_ASSERT( output_buffer != NULL );
+ TEST_ASSERT( export_buffer != NULL );
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
+ TEST_ASSERT( psa_set_key_policy( base_key, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_import_key( base_key, PSA_KEY_TYPE_DERIVE,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ /* Derive some material and output it. */
+ TEST_ASSERT( psa_key_derivation( &generator, base_key, alg,
+ salt->x, salt->len,
+ label->x, label->len,
+ capacity ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_read( &generator,
+ output_buffer,
+ capacity ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_abort( &generator ) == PSA_SUCCESS );
+
+ /* Derive the same output again, but this time store it in key objects. */
+ TEST_ASSERT( psa_key_derivation( &generator, base_key, alg,
+ salt->x, salt->len,
+ label->x, label->len,
+ capacity ) == PSA_SUCCESS );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 );
+ TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_import_key( derived_key,
+ PSA_KEY_TYPE_RAW_DATA,
+ PSA_BYTES_TO_BITS( bytes1 ),
+ &generator ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_export_key( derived_key,
+ export_buffer, bytes1,
+ &length ) == PSA_SUCCESS );
+ TEST_ASSERT( length == bytes1 );
+ TEST_ASSERT( psa_destroy_key( derived_key ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_import_key( derived_key,
+ PSA_KEY_TYPE_RAW_DATA,
+ PSA_BYTES_TO_BITS( bytes2 ),
+ &generator ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_export_key( derived_key,
+ export_buffer + bytes1, bytes2,
+ &length ) == PSA_SUCCESS );
+ TEST_ASSERT( length == bytes2 );
+
+ /* Compare the outputs from the two runs. */
+ TEST_ASSERT( memcmp( output_buffer, export_buffer, capacity ) == 0 );
+
+exit:
+ mbedcrypto_free( output_buffer );
+ mbedcrypto_free( export_buffer );
+ psa_generator_abort( &generator );
+ psa_destroy_key( base_key );
+ psa_destroy_key( derived_key );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void generate_random( int bytes_arg )
+{
+ size_t bytes = bytes_arg;
+ const unsigned char trail[] = "don't overwrite me";
+ unsigned char *output = mbedcrypto_calloc( 1, bytes + sizeof( trail ) );
+ unsigned char *changed = mbedcrypto_calloc( 1, bytes );
+ size_t i;
+ unsigned run;
+
+ TEST_ASSERT( output != NULL );
+ TEST_ASSERT( bytes == 0 || changed != NULL );
+ memcpy( output + bytes, trail, sizeof( trail ) );
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ /* Run several times, to ensure that every output byte will be
+ * nonzero at least once with overwhelming probability
+ * (2^(-8*number_of_runs)). */
+ for( run = 0; run < 10; run++ )
+ {
+ memset( output, 0, bytes );
+ TEST_ASSERT( psa_generate_random( output, bytes ) == PSA_SUCCESS );
+
+ /* Check that no more than bytes have been overwritten */
+ TEST_ASSERT( memcmp( output + bytes, trail, sizeof( trail ) ) == 0 );
+
+ for( i = 0; i < bytes; i++ )
+ {
+ if( output[i] != 0 )
+ ++changed[i];
+ }
+ }
+
+ /* Check that every byte was changed to nonzero at least once. This
+ * validates that psa_generate_random is overwriting every byte of
+ * the output buffer. */
+ for( i = 0; i < bytes; i++ )
+ {
+ TEST_ASSERT( changed[i] != 0 );
+ }
+
+exit:
+ mbedcrypto_psa_crypto_free( );
+ mbedcrypto_free( output );
+ mbedcrypto_free( changed );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void generate_key( int type_arg,
+ int bits_arg,
+ int usage_arg,
+ int alg_arg,
+ int expected_status_arg )
+{
+ int slot = 1;
+ psa_key_type_t type = type_arg;
+ psa_key_usage_t usage = usage_arg;
+ size_t bits = bits_arg;
+ psa_algorithm_t alg = alg_arg;
+ psa_status_t expected_status = expected_status_arg;
+ psa_key_type_t got_type;
+ size_t got_bits;
+ unsigned char exported[616] = {0}; /* enough for a 1024-bit RSA key */
+ size_t exported_length;
+ psa_status_t expected_export_status =
+ usage & PSA_KEY_USAGE_EXPORT ? PSA_SUCCESS : PSA_ERROR_NOT_PERMITTED;
+ psa_status_t expected_info_status =
+ expected_status == PSA_SUCCESS ? PSA_SUCCESS : PSA_ERROR_EMPTY_SLOT;
+ psa_key_policy_t policy;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, usage, alg );
+ TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+
+ /* Generate a key */
+ TEST_ASSERT( psa_generate_key( slot, type, bits,
+ NULL, 0 ) == expected_status );
+
+ /* Test the key information */
+ TEST_ASSERT( psa_get_key_information( slot,
+ &got_type,
+ &got_bits ) == expected_info_status );
+ if( expected_info_status != PSA_SUCCESS )
+ goto exit;
+ TEST_ASSERT( got_type == type );
+ TEST_ASSERT( got_bits == bits );
+
+ /* Export the key */
+ TEST_ASSERT( psa_export_key( slot,
+ exported, sizeof( exported ),
+ &exported_length ) == expected_export_status );
+ if( expected_export_status == PSA_SUCCESS )
+ {
+ if( key_type_is_raw_bytes( type ) )
+ TEST_ASSERT( exported_length == ( bits + 7 ) / 8 );
+#if defined(MBEDCRYPTO_DES_C)
+ if( type == PSA_KEY_TYPE_DES )
+ {
+ /* Check the parity bits. */
+ unsigned i;
+ for( i = 0; i < bits / 8; i++ )
+ {
+ unsigned bit_count = 0;
+ unsigned m;
+ for( m = 1; m <= 0x100; m <<= 1 )
+ {
+ if( exported[i] & m )
+ ++bit_count;
+ }
+ TEST_ASSERT( bit_count % 2 != 0 );
+ }
+ }
+#endif
+#if defined(MBEDCRYPTO_RSA_C) && defined(MBEDCRYPTO_PK_PARSE_C)
+ if( type == PSA_KEY_TYPE_RSA_KEYPAIR )
+ {
+ /* Sanity check: does this look like the beginning of a PKCS#8
+ * RSA key pair? Assumes bits is a multiple of 8. */
+ size_t n_bytes = bits / 8 + 1;
+ size_t n_encoded_bytes;
+ unsigned char *n_end;
+ TEST_ASSERT( exported_length >= 7 + ( n_bytes + 3 ) * 9 / 2 );
+ TEST_ASSERT( exported[0] == 0x30 );
+ TEST_ASSERT( exported[1] == 0x82 ); // assumes >=416-bit key
+ TEST_ASSERT( exported[4] == 0x02 );
+ TEST_ASSERT( exported[5] == 0x01 );
+ TEST_ASSERT( exported[6] == 0x00 );
+ TEST_ASSERT( exported[7] == 0x02 );
+ n_encoded_bytes = exported[8];
+ n_end = exported + 9 + n_encoded_bytes;
+ if( n_encoded_bytes & 0x80 )
+ {
+ n_encoded_bytes = ( n_encoded_bytes & 0x7f ) << 7;
+ n_encoded_bytes |= exported[9] & 0x7f;
+ n_end += 1;
+ }
+ /* The encoding of n should start with a 0 byte since it should
+ * have its high bit set. However Mbed Crypto is not compliant and
+ * generates an invalid, but widely tolerated, encoding of
+ * positive INTEGERs with a bit size that is a multiple of 8
+ * with no leading 0 byte. Accept this here. */
+ TEST_ASSERT( n_bytes == n_encoded_bytes ||
+ n_bytes == n_encoded_bytes + 1 );
+ if( n_bytes == n_encoded_bytes )
+ TEST_ASSERT( exported[n_encoded_bytes <= 127 ? 9 : 10] == 0x00 );
+ /* Sanity check: e must be 3 */
+ TEST_ASSERT( n_end[0] == 0x02 );
+ TEST_ASSERT( n_end[1] == 0x03 );
+ TEST_ASSERT( n_end[2] == 0x01 );
+ TEST_ASSERT( n_end[3] == 0x00 );
+ TEST_ASSERT( n_end[4] == 0x01 );
+ TEST_ASSERT( n_end[5] == 0x02 );
+ }
+#endif /* MBEDCRYPTO_RSA_C */
+#if defined(MBEDCRYPTO_ECP_C)
+ if( PSA_KEY_TYPE_IS_ECC( type ) )
+ {
+ /* Sanity check: does this look like the beginning of a PKCS#8
+ * elliptic curve key pair? */
+ TEST_ASSERT( exported_length >= bits * 3 / 8 + 10 );
+ TEST_ASSERT( exported[0] == 0x30 );
+ }
+#endif /* MBEDCRYPTO_ECP_C */
+ }
+
+ /* Do something with the key according to its type and permitted usage. */
+ if( ! exercise_key( slot, usage, alg ) )
+ goto exit;
+
+exit:
+ psa_destroy_key( slot );
+ mbedcrypto_psa_crypto_free( );
+}
+/* END_CASE */