aboutsummaryrefslogtreecommitdiff
path: root/doc/secvar/driver-api.html
blob: 50c61bd73b54b3a8155b3e2e98ec061f920ef953 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

<!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="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Secvar Drivers &#8212; skiboot 4d27f03
 documentation</title>
    <link rel="stylesheet" href="../_static/classic.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/language_data.js"></script>
    
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" /> 
  </head><body>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="nav-item nav-item-0"><a href="../index.html">skiboot 4d27f03
 documentation</a> &#187;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <div class="section" id="secvar-drivers">
<span id="secvar-driver-api"></span><h1>Secvar Drivers<a class="headerlink" href="#secvar-drivers" title="Permalink to this headline"></a></h1>
<p>This document will attempt to define the expected behavior of the two secvar
drivers, and how a developer should implement a new one.</p>
<div class="section" id="storage-vs-backend-drivers">
<h2>Storage vs Backend drivers<a class="headerlink" href="#storage-vs-backend-drivers" title="Permalink to this headline"></a></h2>
<p>There are two types of drivers for secure variable support, storage and backend
drivers. Storage drivers are the most simple: they control how and where secure
variables are stored for a given platform. Backend drivers on the other hand,
can be bit more complex. They control the overall scheme of OS secureboot –
from what variables are used, what format the variables are intended to be, how
they are updated, and how to determine the platform’s OS secure boot state.</p>
<p>These drivers are intended to be as self-contained as possible, so that ideally
any combination of storage and backend drivers in the future should be
compatible.</p>
</div>
<div class="section" id="storage-driver-api">
<h2>Storage Driver API<a class="headerlink" href="#storage-driver-api" title="Permalink to this headline"></a></h2>
<dl class="docutils">
<dt>The storage driver is expected to:</dt>
<dd><ul class="first last simple">
<li>persist secure variables in a tamper-resistant manner</li>
<li>handle two logical types of variable lists (referred to as “banks”)
* the “variable bank” stores the active list of variables
* the “update bank” stores proposed updates to the variable bank</li>
<li>handle variables using a specific secvar flag in a sensible manner</li>
</ul>
</dd>
</dl>
<p>Storage drivers must implement the following hooks for secvar to properly
utilize:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">struct</span> <span class="n">secvar_storage_driver</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">load_bank</span><span class="p">)(</span><span class="k">struct</span> <span class="n">list_head</span> <span class="o">*</span><span class="n">bank</span><span class="p">,</span> <span class="kt">int</span> <span class="n">section</span><span class="p">);</span>
    <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">write_bank</span><span class="p">)(</span><span class="k">struct</span> <span class="n">list_head</span> <span class="o">*</span><span class="n">bank</span><span class="p">,</span> <span class="kt">int</span> <span class="n">section</span><span class="p">);</span>
    <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">store_init</span><span class="p">)(</span><span class="kt">void</span><span class="p">);</span>
    <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">lock</span><span class="p">)(</span><span class="kt">void</span><span class="p">);</span>
    <span class="kt">uint64_t</span> <span class="n">max_var_size</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>The following subsections will give a summary of each hook, when they are used,
and their expected behavior.</p>
<div class="section" id="store-init">
<h3>store_init<a class="headerlink" href="#store-init" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">store_init</span></code> hook is called at the beginning of secure variable
intialization. This hook should perform any initialization logic required for
the other hooks to operate.</p>
<p>IMPORTANT: If this hook returns an error (non-zero) code, secvar will
immediately halt the boot. When implementing this hook, consider the
implications of any errors in initialization, and whether they may affect the
secure state. For example, if secure state is indeterminable due to some
hardware failure, this is grounds for a halt.</p>
<p>This hook should only be called once. Subsequent calls should have no effect,
or raise an error.</p>
</div>
<div class="section" id="load-bank">
<h3>load_bank<a class="headerlink" href="#load-bank" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">load_bank</span></code> hook should load variables from persistent storage into the
in-memory linked lists, for the rest of secvar to operate on.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">bank</span></code> parameter should be an initialized linked list. This list may not
be empty, and this hook should only append variables to the list.</p>
<dl class="docutils">
<dt>The variables this hook loads should depend on the <code class="docutils literal notranslate"><span class="pre">section</span></code> flag:</dt>
<dd><ul class="first last simple">
<li>if <code class="docutils literal notranslate"><span class="pre">SECVAR_VARIABLE_BANK</span></code>, load the active variables</li>
<li>if <code class="docutils literal notranslate"><span class="pre">SECVAR_UPDATE_BANK</span></code>, load the proposed updates</li>
</ul>
</dd>
</dl>
<p>This hook is called twice at the beginning of secure variable initialization,
one for loading each bank type into their respective lists. This hook may be
called again afterwards (e.g. a reset mechanism by a backend).</p>
</div>
<div class="section" id="write-bank">
<h3>write_bank<a class="headerlink" href="#write-bank" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">write_bank</span></code> hook should persist variables using some non-volatile
storage (e.g. flash).</p>
<p>The <code class="docutils literal notranslate"><span class="pre">bank</span></code> parameter should be an initialized linked list. This list may be
empty. It is up to the storage driver to determine how to handle this, but it is
strongly recommended to zeroize the storage location.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">section</span></code> parameter indicates which list of variables is to be written
following the same pattern as in <code class="docutils literal notranslate"><span class="pre">load_bank</span></code>.</p>
<p>This hook is called for the variable bank if the backend driver reports that
updates were processed. This hook is called for the update bank in all cases
EXCEPT where no updates were found by the backend (this includes error cases).</p>
<p>This hook should not be called more than once for the variable bank. This hook
is called once in the secvar initialization procedure, and then each time
<code class="docutils literal notranslate"><span class="pre">opal_secvar_enqueue_update()</span></code> is successfully called.</p>
</div>
<div class="section" id="lock">
<h3>lock<a class="headerlink" href="#lock" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">lock</span></code> hook may perform any write-lock protections as necessary by the
platform. This hook is unconditionally called after the processing step
performed in the main secure variable logic, and should only be called once.
Subsequent calls should have no effect, or raise an error.</p>
<p>This hook MUST also be called in any error cases that may interrupt the regular
secure variable initialization flow, to prevent leaving the storage mechanism
open to unauthorized writes.</p>
<p>This hook MUST halt the boot if any internal errors arise that may compromise
the protection of the storage.</p>
<p>If locking is not applicable to the storage mechanism, this hook may be
implemented as a no-op.</p>
</div>
<div class="section" id="max-var-size">
<h3>max_var_size<a class="headerlink" href="#max-var-size" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">max_var_size</span></code> field is not a function hook, but a value to be referenced
by other components to determine the maximum variable size. As this driver is
responsible for persisting variables somewhere, it has the option to determine
the maximum size to use.</p>
</div>
<div class="section" id="a-quick-note-on-secvar-flags">
<h3>A Quick Note on Secvar Flags<a class="headerlink" href="#a-quick-note-on-secvar-flags" title="Permalink to this headline"></a></h3>
<p>While “communication” between the storage and backend drivers has been
minimized as best as possible, there are a few cases where the storage driver
may need to take a few hints from the backend.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">flags</span></code> field in <code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">secvar_node</span></code> may contain one of the following
values:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#define SECVAR_FLAG_VOLATILE          0x1</span>
<span class="cp">#define SECVAR_FLAG_PROTECTED         0x2</span>
</pre></div>
</div>
<p>At time of writing this document, the flags are mutually exclusive, however
this may change in the future.</p>
<p><code class="docutils literal notranslate"><span class="pre">VOLATILE</span></code> indicates that the storage driver should NOT persist this variable
to storage.</p>
<p><code class="docutils literal notranslate"><span class="pre">PROTECTED</span></code> indicates that this variable has a heightened importance than
other variables, and if applicable to the storage driver, stored in a more
secure/tamper-resistant region (e.g. store variables important to secureboot
state in TPM NV rather than PNOR on p9).</p>
</div>
</div>
<div class="section" id="backend-driver-api">
<h2>Backend Driver API<a class="headerlink" href="#backend-driver-api" title="Permalink to this headline"></a></h2>
<p>The backend driver at the core defines how secure variables are defined and
processed, and by extension, also how operate the platform’s secure boot modes.</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">struct</span> <span class="n">secvar_backend_driver</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">pre_process</span><span class="p">)(</span><span class="k">struct</span> <span class="n">list_head</span> <span class="o">*</span><span class="n">variable_bank</span>
                       <span class="k">struct</span> <span class="n">list_head</span> <span class="o">*</span><span class="n">update_bank</span><span class="p">);</span>
    <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">process</span><span class="p">)(</span><span class="k">struct</span> <span class="n">list_head</span> <span class="o">*</span><span class="n">variable_bank</span>
                   <span class="k">struct</span> <span class="n">list_head</span> <span class="o">*</span><span class="n">update_bank</span><span class="p">);</span>
    <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">post_process</span><span class="p">)(</span><span class="k">struct</span> <span class="n">list_head</span> <span class="o">*</span><span class="n">variable_bank</span>
                        <span class="k">struct</span> <span class="n">list_head</span> <span class="o">*</span><span class="n">update_bank</span><span class="p">);</span>
    <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">validate</span><span class="p">)(</span><span class="k">struct</span> <span class="n">secvar</span> <span class="o">*</span><span class="n">var</span><span class="p">);</span>
    <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">compatible</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>The following subsections will give a summary of each hook, when they are used,
and their expected behaviors.</p>
<div class="section" id="pre-process">
<h3>pre_process<a class="headerlink" href="#pre-process" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">pre_process</span></code> hook is an optional hook that a backend driver may implement
to handle any early logic prior to processing. If this hook is set to <code class="docutils literal notranslate"><span class="pre">NULL</span></code>,
it is skipped.</p>
<p>As this hook is called just after loading the variables from the storage driver
but just before <code class="docutils literal notranslate"><span class="pre">process</span></code>, this hook is provided for convenience to do any
early initialization logic as necessary.</p>
<p>Any error code returned by this hook will be treated as a failure, and halt
secure variable initialization.</p>
<dl class="docutils">
<dt>Example usage:</dt>
<dd><ul class="first last simple">
<li>initialize empty variables that were not loaded from storage</li>
<li>allocate any internal structures that may be needed for processing</li>
</ul>
</dd>
</dl>
</div>
<div class="section" id="process">
<h3>process<a class="headerlink" href="#process" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">process</span></code> hook is the only required hook, and should contain all variable
update process logic. Unlike the other two hooks, this hook must be defined, or
secure variable initialization will halt.</p>
<p>This hook is expected to iterate through any variables contained in the
<code class="docutils literal notranslate"><span class="pre">update_bank</span></code> list argument, and perform any action on the
<code class="docutils literal notranslate"><span class="pre">variable_bank</span></code> list argument as the backend seems appropriate for the given
update (e.g. add/remove/update variable)</p>
<p>NOTE: the state of these bank lists will be written to persistent storage as-is,
so for example, if the update bank should be cleared, it should be done prior to
returning from this hook.</p>
<p>Unlike the other two hooks, this hook may return a series of return codes
indicating various status situations. This return code is exposed in the device
tree at <code class="docutils literal notranslate"><span class="pre">secvar/update-status</span></code>. See the table below for an expected definition
of the return code meanings. Backends SHOULD document any deviations or
extensions to these definitions for their specific implementation.</p>
<p>To prevent excessive writes to flash, the main secure variable flow will only
perform writes when the <code class="docutils literal notranslate"><span class="pre">process</span></code> hook returns a status that declares
something has been changed. The variable bank is only written to storage if
<code class="docutils literal notranslate"><span class="pre">process</span></code> returns <code class="docutils literal notranslate"><span class="pre">OPAL_SUCCESS</span></code>.</p>
<p>On the other hand, the update bank is written to storage if the return code is
anything other than <code class="docutils literal notranslate"><span class="pre">OPAL_EMPTY</span></code> (which signals that there were no updates to
process). This includes all error cases, therefore the backend is responsible
for emptying the update bank prior to exiting with an error, if the bank is to
be cleared.</p>
<div class="section" id="status-codes">
<h4>Status codes<a class="headerlink" href="#status-codes" title="Permalink to this headline"></a></h4>
<table border="1" class="docutils">
<colgroup>
<col width="27%" />
<col width="73%" />
</colgroup>
<tbody valign="top">
<tr class="row-odd"><td>update-status</td>
<td>Generic Reason</td>
</tr>
<tr class="row-even"><td>OPAL_SUCCESS</td>
<td>Updates were found and processed successfully</td>
</tr>
<tr class="row-odd"><td>OPAL_EMPTY</td>
<td>No updates were found, none processed</td>
</tr>
<tr class="row-even"><td>OPAL_PARAMETER</td>
<td>Malformed, or unexpected update data blob</td>
</tr>
<tr class="row-odd"><td>OPAL_PERMISSION</td>
<td>Update failed to apply, possible auth failure</td>
</tr>
<tr class="row-even"><td>OPAL_HARDWARE</td>
<td>Misc. storage-related error</td>
</tr>
<tr class="row-odd"><td>OPAL_RESOURCE</td>
<td>Out of space (reported by storage)</td>
</tr>
<tr class="row-even"><td>OPAL_NO_MEM</td>
<td>Out of memory</td>
</tr>
</tbody>
</table>
<p>See also: <code class="docutils literal notranslate"><span class="pre">device-tree/ibm,opal/secvar/secvar.rst</span></code>.</p>
</div>
</div>
<div class="section" id="post-process">
<h3>post_process<a class="headerlink" href="#post-process" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">post_process</span></code> hook is an optional hook that a backend driver may
implement to handle any additional logic after the processing step. Like
<code class="docutils literal notranslate"><span class="pre">pre_process</span></code>, it may be set to <code class="docutils literal notranslate"><span class="pre">NULL</span></code> if unused.</p>
<p>This hook is called AFTER performing any writes to storage, and AFTER locking
the persistant storage. Any changes to the variable bank list in this hook will
NOT be persisted to storage.</p>
<p>Any error code returned by this hook will be treated as a failure, and halt
secure variable initialization.</p>
<dl class="docutils">
<dt>Example usage:</dt>
<dd><ul class="first last simple">
<li>determine secure boot state (and set <code class="docutils literal notranslate"><span class="pre">os-secure-enforcing</span></code>)</li>
<li>remove any variables from the variable bank that do not need to be exposed</li>
<li>append any additional volatile variables</li>
</ul>
</dd>
</dl>
</div>
<div class="section" id="validate">
<h3>validate<a class="headerlink" href="#validate" title="Permalink to this headline"></a></h3>
<p>!!NOTE!! This is not currently implemented, and the detail below is subject to
change.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">validate</span></code> hook is an optional hook that a backend may implement to check
if a single variable is valid. If implemented, this hook is called during
<code class="docutils literal notranslate"><span class="pre">opal_secvar_enqueue_update</span></code> to provide more immediate feedback to the caller
on proposed variable validity.</p>
<p>This hook should return <code class="docutils literal notranslate"><span class="pre">OPAL_SUCCESS</span></code> if the validity check passes. Any
other return code is treated as a failure, and will be passed through the
<code class="docutils literal notranslate"><span class="pre">enqueue_update</span></code> call.</p>
<dl class="docutils">
<dt>Example usage:</dt>
<dd><ul class="first last simple">
<li>check for valid payload data structure</li>
<li>check for valid signature format</li>
<li>validate the signature against current variables</li>
<li>implement a variable white/blacklist</li>
</ul>
</dd>
</dl>
</div>
<div class="section" id="compatible">
<h3>compatible<a class="headerlink" href="#compatible" title="Permalink to this headline"></a></h3>
<p>The compatible field is a required field that declares the compatibility of
this backend driver. This compatible field is exposed in the
<code class="docutils literal notranslate"><span class="pre">secvar/compatible</span></code> device tree node for subsequent kernels, etc to
determine how to interact with the secure variables.</p>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../index.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Secvar Drivers</a><ul>
<li><a class="reference internal" href="#storage-vs-backend-drivers">Storage vs Backend drivers</a></li>
<li><a class="reference internal" href="#storage-driver-api">Storage Driver API</a><ul>
<li><a class="reference internal" href="#store-init">store_init</a></li>
<li><a class="reference internal" href="#load-bank">load_bank</a></li>
<li><a class="reference internal" href="#write-bank">write_bank</a></li>
<li><a class="reference internal" href="#lock">lock</a></li>
<li><a class="reference internal" href="#max-var-size">max_var_size</a></li>
<li><a class="reference internal" href="#a-quick-note-on-secvar-flags">A Quick Note on Secvar Flags</a></li>
</ul>
</li>
<li><a class="reference internal" href="#backend-driver-api">Backend Driver API</a><ul>
<li><a class="reference internal" href="#pre-process">pre_process</a></li>
<li><a class="reference internal" href="#process">process</a><ul>
<li><a class="reference internal" href="#status-codes">Status codes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#post-process">post_process</a></li>
<li><a class="reference internal" href="#validate">validate</a></li>
<li><a class="reference internal" href="#compatible">compatible</a></li>
</ul>
</li>
</ul>
</li>
</ul>

  <div role="note" aria-label="source link">
    <h3>This Page</h3>
    <ul class="this-page-menu">
      <li><a href="../_sources/secvar/driver-api.rst.txt"
            rel="nofollow">Show Source</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3>Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    </div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="nav-item nav-item-0"><a href="../index.html">skiboot 4d27f03
 documentation</a> &#187;</li> 
      </ul>
    </div>
    <div class="footer" role="contentinfo">
        &#169; Copyright 2016-2017, IBM, others.
      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5.
    </div>
  </body>
</html>