blob: dd8e2f359992103c0657fb4545d645a2f24d83b9 [file] [log] [blame]
Gilles Peskine6c723a22020-04-17 16:57:52 +02001
2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
5<html xmlns="http://www.w3.org/1999/xhtml">
6 <head>
7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Gilles Peskinec2db5f02021-01-18 20:36:53 +01008 <title>6. Implementation considerations &#8212; PSA Crypto API 1.0.1 documentation</title>
Gilles Peskine6c723a22020-04-17 16:57:52 +02009 <link rel="stylesheet" href="../_static/alabaster.css" type="text/css" />
10 <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
11 <script type="text/javascript">
12 var DOCUMENTATION_OPTIONS = {
13 URL_ROOT: '../',
Gilles Peskinec2db5f02021-01-18 20:36:53 +010014 VERSION: '1.0.1',
Gilles Peskine6c723a22020-04-17 16:57:52 +020015 COLLAPSE_INDEX: false,
16 FILE_SUFFIX: '.html',
Gilles Peskinec2db5f02021-01-18 20:36:53 +010017 HAS_SOURCE: false,
Gilles Peskine6c723a22020-04-17 16:57:52 +020018 SOURCELINK_SUFFIX: '.txt'
19 };
20 </script>
21 <script type="text/javascript" src="../_static/jquery.js"></script>
22 <script type="text/javascript" src="../_static/underscore.js"></script>
23 <script type="text/javascript" src="../_static/doctools.js"></script>
Gilles Peskinec2db5f02021-01-18 20:36:53 +010024 <link rel="author" title="About these documents" href="../about.html" />
Gilles Peskine6c723a22020-04-17 16:57:52 +020025 <link rel="index" title="Index" href="../genindex.html" />
26 <link rel="search" title="Search" href="../search.html" />
Gilles Peskinec2db5f02021-01-18 20:36:53 +010027 <link rel="next" title="7. Usage considerations" href="usage.html" />
28 <link rel="prev" title="5. Library conventions" href="conventions.html" />
Gilles Peskine6c723a22020-04-17 16:57:52 +020029
30 <link rel="stylesheet" href="../_static/custom.css" type="text/css" />
31
32 <meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
33
34 </head>
35 <body>
36
37
38 <div class="document">
39 <div class="documentwrapper">
40 <div class="bodywrapper">
41 <div class="body" role="main">
42
43 <div class="section" id="implementation-considerations">
Gilles Peskinec2db5f02021-01-18 20:36:53 +010044<span id="id1"></span><h1>6. Implementation considerations</h1>
Gilles Peskine6c723a22020-04-17 16:57:52 +020045<div class="section" id="implementation-specific-aspects-of-the-interface">
Gilles Peskinec2db5f02021-01-18 20:36:53 +010046<h2>6.1. Implementation-specific aspects of the interface</h2>
Gilles Peskine6c723a22020-04-17 16:57:52 +020047<div class="section" id="implementation-profile">
Gilles Peskinec2db5f02021-01-18 20:36:53 +010048<h3>6.1.1. Implementation profile</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +020049<p>Implementations can implement a subset of the API and a subset of the available
50algorithms. The implemented subset is known as the implementation’s profile. The
51documentation for each implementation must describe the profile that it
52implements. This specification’s companion documents also define a number of
53standard profiles.</p>
54</div>
55<div class="section" id="implementation-specific-types">
Gilles Peskinec2db5f02021-01-18 20:36:53 +010056<span id="implementation-defined-type"></span><h3>6.1.2. Implementation-specific types</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +020057<p>This specification defines a number of implementation-specific types, which
58represent objects whose content depends on the implementation. These are defined
59as C <code class="docutils literal"><span class="pre">typedef</span></code> types in this specification, with a comment
60<em><a class="reference internal" href="#implementation-defined-type"><span class="std std-ref">/* implementation-defined type */</span></a></em> in place of the underlying type
61definition. For some types the specification constrains the type, for example,
62by requiring that the type is a <code class="docutils literal"><span class="pre">struct</span></code>, or that it is convertible to and
Gilles Peskinec2db5f02021-01-18 20:36:53 +010063from an unsigned integer. In the implementation’s version of <code class="file docutils literal"><span class="pre">psa/crypto.h</span></code>,
Gilles Peskine6c723a22020-04-17 16:57:52 +020064these types need to be defined as complete C types so that objects of these
65types can be instantiated by application code.</p>
66<p>Applications that rely on the implementation specific definition of any of these
67types might not be portable to other implementations of this specification.</p>
68</div>
69<div class="section" id="implementation-specific-macros">
Gilles Peskinec2db5f02021-01-18 20:36:53 +010070<span id="implementation-specific-macro"></span><h3>6.1.3. Implementation-specific macros</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +020071<p>Some macro constants and function-like macros are precisely defined by this
72specification. The use of an exact definition is essential if the definition can
73appear in more than one header file within a compilation.</p>
74<p>Other macros that are defined by this specification have a macro body that is
75implementation-specific. The description of an implementation-specific macro can
76optionally specify each of the following requirements:</p>
77<ul class="simple">
78<li>Input domains: the macro must be valid for arguments within the input domain.</li>
79<li>A return type: the macro result must be compatible with this type.</li>
80<li>Output range: the macro result must lie in the output range.</li>
81<li>Computed value: A precise mapping of valid input to output values.</li>
82</ul>
83<p>Each implementation-specific macro is in one of following categories:</p>
84<p id="specification-defined-value"><em>Specification-defined value</em></p>
85<blockquote>
86<div><p>The result type and computed value of the macro expression is defined by
87this specification, but the definition of the macro body is provided by the
88implementation.</p>
89<p>These macros are indicated in this specification using the comment
90<em><a class="reference internal" href="#specification-defined-value"><span class="std std-ref">/* specification-defined value */</span></a></em>.</p>
91<p>For function-like macros with specification-defined values:</p>
92<ul class="simple">
93<li>Example implementations are provided in an appendix to this specification.
Gilles Peskinec2db5f02021-01-18 20:36:53 +010094See <a class="reference internal" href="../appendix/specdef_values.html#appendix-specdef-values"><span class="secref">Example macro implementations</span></a>.</li>
Gilles Peskine6c723a22020-04-17 16:57:52 +020095<li>The expected computation for valid and supported input arguments will be
96defined as pseudo-code in a future version of this specification.</li>
97</ul>
98</div></blockquote>
99<p id="implementation-defined-value"><em>Implementation-defined value</em></p>
100<blockquote>
101<div><p>The value of the macro expression is implementation-defined.</p>
102<p>For some macros, the computed value is derived from the specification of one
103or more cryptographic algorithms. In these cases, the result must exactly
104match the value in those external specifications.</p>
105<p>These macros are indicated in this specification using the comment
106<em><a class="reference internal" href="#implementation-defined-value"><span class="std std-ref">/* implementation-defined value */</span></a></em>.</p>
107</div></blockquote>
108<p>Some of these macros compute a result based on an algorithm or key type.
109If an implementation defines vendor-specific algorithms or
110key types, then it must provide an implementation for such macros that takes all
111relevant algorithms and types into account. Conversely, an implementation that
112does not support a certain algorithm or key type can define such macros in a
113simpler way that does not take unsupported argument values into account.</p>
114<p>Some macros define the minimum sufficient output buffer size for certain
115functions. In some cases, an implementation is allowed to require a buffer size
116that is larger than the theoretical minimum. An implementation must define
117minimum-size macros in such a way that it guarantees that the buffer of the
118resulting size is sufficient for the output of the corresponding function. Refer
119to each macro’s documentation for the applicable requirements.</p>
120</div>
121</div>
122<div class="section" id="porting-to-a-platform">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100123<h2>6.2. Porting to a platform</h2>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200124<div class="section" id="platform-assumptions">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100125<h3>6.2.1. Platform assumptions</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200126<p>This specification is designed for a C99 platform. The interface is defined in
127terms of C macros, functions and objects.</p>
128<p>The specification assumes 8-bit bytes, and “byte” and “octet” are used
129synonymously.</p>
130</div>
131<div class="section" id="platform-specific-types">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100132<h3>6.2.2. Platform-specific types</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200133<p>The specification makes use of some types defined in C99. These types must be
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100134defined in the implementation version of <code class="file docutils literal"><span class="pre">psa/crypto.h</span></code> or by a header
Gilles Peskine6c723a22020-04-17 16:57:52 +0200135included in this file. The following C99 types are used:</p>
136<dl class="docutils">
137<dt><code class="docutils literal"><span class="pre">uint8_t</span></code>, <code class="docutils literal"><span class="pre">uint16_t</span></code>, <code class="docutils literal"><span class="pre">uint32_t</span></code></dt>
138<dd>Unsigned integer types with 8, 16 and 32 value bits respectively.
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100139These types are defined by the C99 header <code class="file docutils literal"><span class="pre">stdint.h</span></code>.</dd>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200140</dl>
141</div>
142<div class="section" id="cryptographic-hardware-support">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100143<h3>6.2.3. Cryptographic hardware support</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200144<p>Implementations are encouraged to make use of hardware accelerators where
145available. A future version of this specification will define a function
146interface that calls drivers for hardware accelerators and external
147cryptographic hardware.</p>
148</div>
149</div>
150<div class="section" id="security-requirements-and-recommendations">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100151<h2>6.3. Security requirements and recommendations</h2>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200152<div class="section" id="error-detection">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100153<h3>6.3.1. Error detection</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200154<p>Implementations that provide isolation between the caller and the cryptography
155processing environment must validate parameters to ensure that the cryptography
156processing environment is protected from attacks caused by passing invalid
157parameters.</p>
158<p>Even implementations that do not provide isolation are recommended to detect bad
159parameters and fail-safe where possible.</p>
160</div>
161<div class="section" id="indirect-object-references">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100162<h3>6.3.2. Indirect object references</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200163<p>Implementations can use different strategies for allocating key identifiers,
164and other types of indirect object reference.</p>
165<p>Implementations that provide isolation between the caller and the cryptography
166processing environment must consider the threats relating to abuse and misuse
167of key identifiers and other indirect resource references. For example,
168multi-part operations can be implemented as backend state to which the client
169only maintains an indirect reference in the application’s multi-part operation
170object.</p>
171<p>An implementation that supports multiple callers must implement strict isolation
172of API resources between different callers. For example, a client must not be
173able to obtain a reference to another client’s key by guessing the key
174identifier value. Isolation of key identifiers can be achieved in several ways.
175For example:</p>
176<ul class="simple">
177<li>There is a single identifier namespace for all clients, and the
178implementation verifies that the client is the owner of the identifier when
179looking up the key.</li>
180<li>Each client has an independent identifier namespace, and the implementation
181uses a client specific identifier-to-key mapping when looking up the key.</li>
182</ul>
183<p>After a volatile key identifier is destroyed, it is recommended that the
184implementation does not immediately reuse the same identifier value for a
185different key. This reduces the risk of an attack that is able to exploit a key
186identifier reuse vulnerability within an application.</p>
187</div>
188<div class="section" id="memory-cleanup">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100189<span id="id2"></span><h3>6.3.3. Memory cleanup</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200190<p>Implementations must wipe all sensitive data from memory when it is no longer
191used. It is recommended that they wipe this sensitive data as soon as possible. All
192temporary data used during the execution of a function, such as stack buffers,
193must be wiped before the function returns. All data associated with an object,
194such as a multi-part operation, must be wiped, at the latest, when the object
195becomes inactive, for example, when a multi-part operation is aborted.</p>
196<p>The rationale for this non-functional requirement is to minimize impact if the
197system is compromised. If sensitive data is wiped immediately after use, only
198data that is currently in use can be leaked. It does not compromise past data.</p>
199</div>
200<div class="section" id="managing-key-material">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100201<span id="key-material"></span><h3>6.3.4. Managing key material</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200202<p>In implementations that have limited volatile memory for keys, the
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100203implementation is permitted to store a <a class="reference internal" href="../api/keys/lifetimes.html#key-lifetimes"><span class="std std-ref">volatile key</span></a> to a
Gilles Peskine6c723a22020-04-17 16:57:52 +0200204temporary location in non-volatile memory. The implementation must delete any
205such copies when the key is destroyed, and it is recommended that these copies
206are deleted as soon as the key is reloaded into volatile memory. An
207implementation that uses this method must clear any stored volatile key material
208on startup.</p>
209<p>Implementing the <a class="reference internal" href="#memory-cleanup"><span class="std std-ref">memory cleanup rule</span></a> for persistent keys
210can result in inefficiencies when the same persistent key is used sequentially
211in multiple cryptographic operations. The inefficiency stems from loading the
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100212key from non-volatile storage on each use of the key. The <a class="reference internal" href="../api/keys/policy.html#c.PSA_KEY_USAGE_CACHE" title="PSA_KEY_USAGE_CACHE"><code class="xref any c c-macro docutils literal"><span class="pre">PSA_KEY_USAGE_CACHE</span></code></a>
213usage flag in a key policy allows an application to request that the implementation does not cleanup
Gilles Peskine6c723a22020-04-17 16:57:52 +0200214non-essential copies of persistent key material, effectively suspending the
215cleanup rules for that key. The effects of this policy depend on the
216implementation and the key, for example:</p>
217<ul class="simple">
218<li>For volatile keys or keys in a secure element with no open/close mechanism,
219this is likely to have no effect.</li>
220<li>For persistent keys that are not in a secure element, this allows the
221implementation to keep the key in a memory cache outside of the memory used
222by ongoing operations.</li>
223<li>For keys in a secure element with an open/close mechanism, this is a hint to
224keep the key open in the secure element.</li>
225</ul>
226<p>The application can indicate when it has finished using the key by calling
227<a class="reference internal" href="../api/keys/management.html#c.psa_purge_key" title="psa_purge_key"><code class="xref any c c-func docutils literal"><span class="pre">psa_purge_key()</span></code></a>, to request that the key material is cleaned from memory.</p>
228</div>
229<div class="section" id="safe-outputs-on-error">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100230<h3>6.3.5. Safe outputs on error</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200231<p>Implementations must ensure that confidential data is not written to output
232parameters before validating that the disclosure of this confidential data is
233authorized. This requirement is particularly important for implementations where
234the caller can share memory with another security context, as described in the
235<a class="reference internal" href="conventions.html#stability-of-parameters"><span class="std std-ref">Stability of parameters</span></a> section.</p>
236<p>In most cases, the specification does not define the content of output
237parameters when an error occurs. It is recommended that implementations try to
238ensure that the content of output parameters is as safe as possible, in case an
239application flaw or a data leak causes it to be used. In particular, Arm
240recommends that implementations avoid placing partial output in output buffers
241when an action is interrupted. The meaning of “safe as possible” depends on the
242implementation, as different environments require different compromises between
243implementation complexity, overall robustness and performance. Some common
244strategies are to leave output parameters unchanged, in case of errors, or
245zeroing them out.</p>
246</div>
247<div class="section" id="attack-resistance">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100248<h3>6.3.6. Attack resistance</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200249<p>Cryptographic code tends to manipulate high-value secrets, from which other
250secrets can be unlocked. As such, it is a high-value target for attacks. There
251is a vast body of literature on attack types, such as side channel attacks and
252glitch attacks. Typical side channels include timing, cache access patterns,
253branch-prediction access patterns, power consumption, radio emissions and more.</p>
254<p>This specification does not specify particular requirements for attack
255resistance. Implementers are encouraged to consider the attack resistance
256desired in each use case and design their implementation accordingly. Security
257standards for attack resistance for particular targets might be applicable in
258certain use cases.</p>
259</div>
260</div>
261<div class="section" id="other-implementation-considerations">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100262<h2>6.4. Other implementation considerations</h2>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200263<div class="section" id="philosophy-of-resource-management">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100264<h3>6.4.1. Philosophy of resource management</h3>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200265<p>The specification allows most functions to return
266<a class="reference internal" href="../api/library/status.html#c.PSA_ERROR_INSUFFICIENT_MEMORY" title="PSA_ERROR_INSUFFICIENT_MEMORY"><code class="xref any c c-macro docutils literal"><span class="pre">PSA_ERROR_INSUFFICIENT_MEMORY</span></code></a>. This gives implementations the freedom to
267manage memory as they please.</p>
268<p>Alternatively, the interface is also designed for conservative strategies of
269memory management. An implementation can avoid dynamic memory allocation
270altogether by obeying certain restrictions:</p>
271<ul class="simple">
272<li>Pre-allocate memory for a predefined number of keys, each with sufficient
273memory for all key types that can be stored.</li>
274<li>For multi-part operations, in an implementation without isolation, place all
275the data that needs to be carried over from one step to the next in the
276operation object. The application is then fully in control of how memory is
277allocated for the operation.</li>
278<li>In an implementation with isolation, pre-allocate memory for a predefined
279number of operations inside the cryptoprocessor.</li>
280</ul>
281</div>
282</div>
283</div>
284
285
286 </div>
287 </div>
288 </div>
289 <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100290 <div class="sphinxsidebarwrapper"><h3><a href="../index.html"><b>PSA Crypto API</b></a></h3>
291IHI 0086<br/>
292Non-confidential<br/>
293Version 1.0.1
294<span style="color: red; font-weight: bold;"></span>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200295<ul>
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100296<li class="toctree-l1"><a class="reference internal" href="../about.html">About this document</a></li>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200297</ul>
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100298<ul class="current">
299<li class="toctree-l1"><a class="reference internal" href="intro.html">1. Introduction</a></li>
300<li class="toctree-l1"><a class="reference internal" href="goals.html">2. Design goals</a></li>
301<li class="toctree-l1"><a class="reference internal" href="functionality.html">3. Functionality overview</a></li>
302<li class="toctree-l1"><a class="reference internal" href="sample-arch.html">4. Sample architectures</a></li>
303<li class="toctree-l1"><a class="reference internal" href="conventions.html">5. Library conventions</a></li>
304<li class="toctree-l1 current"><a class="current reference internal" href="#">6. Implementation considerations</a><ul>
305<li class="toctree-l2"><a class="reference internal" href="#implementation-specific-aspects-of-the-interface">6.1. Implementation-specific aspects of the interface</a><ul>
306<li class="toctree-l3"><a class="reference internal" href="#implementation-profile">6.1.1. Implementation profile</a></li>
307<li class="toctree-l3"><a class="reference internal" href="#implementation-specific-types">6.1.2. Implementation-specific types</a></li>
308<li class="toctree-l3"><a class="reference internal" href="#implementation-specific-macros">6.1.3. Implementation-specific macros</a></li>
309</ul>
310</li>
311<li class="toctree-l2"><a class="reference internal" href="#porting-to-a-platform">6.2. Porting to a platform</a><ul>
312<li class="toctree-l3"><a class="reference internal" href="#platform-assumptions">6.2.1. Platform assumptions</a></li>
313<li class="toctree-l3"><a class="reference internal" href="#platform-specific-types">6.2.2. Platform-specific types</a></li>
314<li class="toctree-l3"><a class="reference internal" href="#cryptographic-hardware-support">6.2.3. Cryptographic hardware support</a></li>
315</ul>
316</li>
317<li class="toctree-l2"><a class="reference internal" href="#security-requirements-and-recommendations">6.3. Security requirements and recommendations</a><ul>
318<li class="toctree-l3"><a class="reference internal" href="#error-detection">6.3.1. Error detection</a></li>
319<li class="toctree-l3"><a class="reference internal" href="#indirect-object-references">6.3.2. Indirect object references</a></li>
320<li class="toctree-l3"><a class="reference internal" href="#memory-cleanup">6.3.3. Memory cleanup</a></li>
321<li class="toctree-l3"><a class="reference internal" href="#managing-key-material">6.3.4. Managing key material</a></li>
322<li class="toctree-l3"><a class="reference internal" href="#safe-outputs-on-error">6.3.5. Safe outputs on error</a></li>
323<li class="toctree-l3"><a class="reference internal" href="#attack-resistance">6.3.6. Attack resistance</a></li>
324</ul>
325</li>
326<li class="toctree-l2"><a class="reference internal" href="#other-implementation-considerations">6.4. Other implementation considerations</a><ul>
327<li class="toctree-l3"><a class="reference internal" href="#philosophy-of-resource-management">6.4.1. Philosophy of resource management</a></li>
328</ul>
329</li>
330</ul>
331</li>
332<li class="toctree-l1"><a class="reference internal" href="usage.html">7. Usage considerations</a></li>
333<li class="toctree-l1"><a class="reference internal" href="../api/library/index.html">8. Library management reference</a></li>
334<li class="toctree-l1"><a class="reference internal" href="../api/keys/index.html">9. Key management reference</a></li>
335<li class="toctree-l1"><a class="reference internal" href="../api/ops/index.html">10. Cryptographic operation reference</a></li>
336</ul>
337<ul>
338<li class="toctree-l1"><a class="reference internal" href="../appendix/example_header.html">Example header file</a></li>
339<li class="toctree-l1"><a class="reference internal" href="../appendix/specdef_values.html">Example macro implementations</a></li>
340<li class="toctree-l1"><a class="reference internal" href="../appendix/history.html">Changes to the API</a></li>
341</ul>
342<ul>
343<li class="toctree-l1"><a class="reference internal" href="../psa_c-identifiers.html">Index of API elements</a></li>
344</ul>
Gilles Peskine6c723a22020-04-17 16:57:52 +0200345<div id="searchbox" style="display: none" role="search">
346 <h3>Quick search</h3>
347 <form class="search" action="../search.html" method="get">
348 <div><input type="text" name="q" /></div>
349 <div><input type="submit" value="Go" /></div>
350 <input type="hidden" name="check_keywords" value="yes" />
351 <input type="hidden" name="area" value="default" />
352 </form>
353</div>
354<script type="text/javascript">$('#searchbox').show(0);</script>
355 </div>
356 </div>
357 <div class="clearer"></div>
358 </div>
359 <div class="footer">
Gilles Peskinec2db5f02021-01-18 20:36:53 +0100360 &copy; 2018-2020, Arm Limited or its affiliates. All rights reserved.
Gilles Peskine6c723a22020-04-17 16:57:52 +0200361
362 |
363 Powered by <a href="http://sphinx-doc.org/">Sphinx 1.6.7</a>
364 &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.8</a>
365
Gilles Peskine6c723a22020-04-17 16:57:52 +0200366 </div>
367
368
369
370
371 </body>
372</html>