xref: /aosp_15_r20/external/tpm2-tss/test/integration/sapi-nv-policy-locality.int.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1*758e9fbaSOystein Eftevaag /*
2*758e9fbaSOystein Eftevaag  * SPDX-License-Identifier: BSD-2-Clause
3*758e9fbaSOystein Eftevaag  * Copyright (c) 2019, Intel Corporation
4*758e9fbaSOystein Eftevaag  */
5*758e9fbaSOystein Eftevaag 
6*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
7*758e9fbaSOystein Eftevaag #include <config.h>
8*758e9fbaSOystein Eftevaag #endif
9*758e9fbaSOystein Eftevaag 
10*758e9fbaSOystein Eftevaag #include <assert.h>
11*758e9fbaSOystein Eftevaag #include <inttypes.h>
12*758e9fbaSOystein Eftevaag #include <stdbool.h>
13*758e9fbaSOystein Eftevaag #include <stdio.h>
14*758e9fbaSOystein Eftevaag #include <stdlib.h>
15*758e9fbaSOystein Eftevaag #include <string.h>
16*758e9fbaSOystein Eftevaag 
17*758e9fbaSOystein Eftevaag #include "tss2_sys.h"
18*758e9fbaSOystein Eftevaag 
19*758e9fbaSOystein Eftevaag #include "context-util.h"
20*758e9fbaSOystein Eftevaag #include "sapi-util.h"
21*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
22*758e9fbaSOystein Eftevaag #define LOGMODULE test
23*758e9fbaSOystein Eftevaag #include "util/log.h"
24*758e9fbaSOystein Eftevaag 
25*758e9fbaSOystein Eftevaag #define NV_INDEX 0x01800003
26*758e9fbaSOystein Eftevaag #define NV_SIZE 96
27*758e9fbaSOystein Eftevaag 
28*758e9fbaSOystein Eftevaag #define TPM2B_SIZE_MAX(type) (sizeof (type) - 2)
29*758e9fbaSOystein Eftevaag 
30*758e9fbaSOystein Eftevaag /*
31*758e9fbaSOystein Eftevaag  * This test creates an NV index governed by a policy and then performs
32*758e9fbaSOystein Eftevaag  * several operations on the NV region to exercise this policy. The NV
33*758e9fbaSOystein Eftevaag  * region created is modeled after the TXT AUX region as defined by the
34*758e9fbaSOystein Eftevaag  * Intel TXT software developers guide:
35*758e9fbaSOystein Eftevaag  * https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
36*758e9fbaSOystein Eftevaag  * Read is controlled by authValue and is unrestricted since authValue is
37*758e9fbaSOystein Eftevaag  * set to emptyBuffer.
38*758e9fbaSOystein Eftevaag  * Write is controlled by policy that allows writes from locality 3 and 4.
39*758e9fbaSOystein Eftevaag  */
40*758e9fbaSOystein Eftevaag /*
41*758e9fbaSOystein Eftevaag  * This function creates a policy session asserting that the locality is
42*758e9fbaSOystein Eftevaag  * either 3 or 4. If this policy is used when executing a command and the
43*758e9fbaSOystein Eftevaag  * policy is not satisfied (locality is not 3 or 4) then the command will
44*758e9fbaSOystein Eftevaag  * fail.
45*758e9fbaSOystein Eftevaag  */
46*758e9fbaSOystein Eftevaag static TSS2_RC
create_policy_session(TSS2_SYS_CONTEXT * sys_ctx,TPMI_SH_AUTH_SESSION * handle)47*758e9fbaSOystein Eftevaag create_policy_session (TSS2_SYS_CONTEXT *sys_ctx,
48*758e9fbaSOystein Eftevaag                        TPMI_SH_AUTH_SESSION *handle)
49*758e9fbaSOystein Eftevaag {
50*758e9fbaSOystein Eftevaag     TPMA_LOCALITY locality = TPMA_LOCALITY_TPM2_LOC_THREE |
51*758e9fbaSOystein Eftevaag         TPMA_LOCALITY_TPM2_LOC_FOUR;
52*758e9fbaSOystein Eftevaag     TPM2B_NONCE nonce = { .size = GetDigestSize (TPM2_ALG_SHA1), };
53*758e9fbaSOystein Eftevaag     TPM2B_NONCE nonce_tpm = { 0, };
54*758e9fbaSOystein Eftevaag     TSS2_RC rc;
55*758e9fbaSOystein Eftevaag     TPM2B_ENCRYPTED_SECRET salt = { 0, };
56*758e9fbaSOystein Eftevaag     TPMT_SYM_DEF symmetric = { .algorithm = TPM2_ALG_NULL, };
57*758e9fbaSOystein Eftevaag 
58*758e9fbaSOystein Eftevaag     rc = Tss2_Sys_StartAuthSession (sys_ctx,
59*758e9fbaSOystein Eftevaag                                     TPM2_RH_NULL,
60*758e9fbaSOystein Eftevaag                                     TPM2_RH_NULL,
61*758e9fbaSOystein Eftevaag                                     0,
62*758e9fbaSOystein Eftevaag                                     &nonce,
63*758e9fbaSOystein Eftevaag                                     &salt,
64*758e9fbaSOystein Eftevaag                                     TPM2_SE_POLICY,
65*758e9fbaSOystein Eftevaag                                     &symmetric,
66*758e9fbaSOystein Eftevaag                                     TPM2_ALG_SHA1,
67*758e9fbaSOystein Eftevaag                                     handle,
68*758e9fbaSOystein Eftevaag                                     &nonce_tpm,
69*758e9fbaSOystein Eftevaag                                     0);
70*758e9fbaSOystein Eftevaag     return_if_error (rc, "Tss2_Sys_StartAuthSession");
71*758e9fbaSOystein Eftevaag 
72*758e9fbaSOystein Eftevaag     rc = Tss2_Sys_PolicyLocality (sys_ctx,
73*758e9fbaSOystein Eftevaag                                   *handle,
74*758e9fbaSOystein Eftevaag                                   0,
75*758e9fbaSOystein Eftevaag                                   locality,
76*758e9fbaSOystein Eftevaag                                   0);
77*758e9fbaSOystein Eftevaag     return_if_error (rc, "Tss2_Sys_PolicyLocality");
78*758e9fbaSOystein Eftevaag     return rc;
79*758e9fbaSOystein Eftevaag }
80*758e9fbaSOystein Eftevaag /*
81*758e9fbaSOystein Eftevaag  * This function creates the NV region used in this test. The appropriate
82*758e9fbaSOystein Eftevaag  * attributes are applied using the nvPublic member of the TPM2B_NV_PUBLIC
83*758e9fbaSOystein Eftevaag  * structure.
84*758e9fbaSOystein Eftevaag  */
85*758e9fbaSOystein Eftevaag static TSS2_RC
setup_nv(TSS2_SYS_CONTEXT * sys_ctx)86*758e9fbaSOystein Eftevaag setup_nv (TSS2_SYS_CONTEXT *sys_ctx)
87*758e9fbaSOystein Eftevaag {
88*758e9fbaSOystein Eftevaag     TSS2_RC rc;
89*758e9fbaSOystein Eftevaag     TPMI_SH_AUTH_SESSION auth_handle = 0;
90*758e9fbaSOystein Eftevaag     TPM2B_DIGEST policy_hash = { 0, };
91*758e9fbaSOystein Eftevaag     TPM2B_AUTH nv_auth = { 0, };
92*758e9fbaSOystein Eftevaag     TSS2L_SYS_AUTH_RESPONSE auth_rsp = { 0, };
93*758e9fbaSOystein Eftevaag     TPM2B_NV_PUBLIC public_info = {
94*758e9fbaSOystein Eftevaag         .nvPublic = {
95*758e9fbaSOystein Eftevaag             .attributes = TPMA_NV_AUTHREAD | TPMA_NV_POLICYWRITE |
96*758e9fbaSOystein Eftevaag                 TPMA_NV_PLATFORMCREATE, /* POLICYDELETE? */
97*758e9fbaSOystein Eftevaag             .authPolicy = { .size = GetDigestSize (TPM2_ALG_SHA1), },
98*758e9fbaSOystein Eftevaag             .dataSize = NV_SIZE,
99*758e9fbaSOystein Eftevaag             .nameAlg = TPM2_ALG_SHA1,
100*758e9fbaSOystein Eftevaag             .nvIndex = NV_INDEX,
101*758e9fbaSOystein Eftevaag         },
102*758e9fbaSOystein Eftevaag     };
103*758e9fbaSOystein Eftevaag     const TSS2L_SYS_AUTH_COMMAND auth_cmd = {
104*758e9fbaSOystein Eftevaag         .count = 1,
105*758e9fbaSOystein Eftevaag         .auths= {
106*758e9fbaSOystein Eftevaag             {
107*758e9fbaSOystein Eftevaag                 .sessionHandle = TPM2_RS_PW,
108*758e9fbaSOystein Eftevaag             }
109*758e9fbaSOystein Eftevaag         }
110*758e9fbaSOystein Eftevaag     };
111*758e9fbaSOystein Eftevaag 
112*758e9fbaSOystein Eftevaag     rc = create_policy_session (sys_ctx, &auth_handle);
113*758e9fbaSOystein Eftevaag     return_if_error (rc, "create_policy_session");
114*758e9fbaSOystein Eftevaag 
115*758e9fbaSOystein Eftevaag     rc = Tss2_Sys_PolicyGetDigest (sys_ctx,
116*758e9fbaSOystein Eftevaag                                    auth_handle,
117*758e9fbaSOystein Eftevaag                                    0,
118*758e9fbaSOystein Eftevaag                                    &policy_hash,
119*758e9fbaSOystein Eftevaag                                    0);
120*758e9fbaSOystein Eftevaag     return_if_error (rc, "Tss2_Sys_PolicyGetDigest");
121*758e9fbaSOystein Eftevaag 
122*758e9fbaSOystein Eftevaag     LOGBLOB_DEBUG (policy_hash.buffer, policy_hash.size, "policy_hash");
123*758e9fbaSOystein Eftevaag     memcpy (public_info.nvPublic.authPolicy.buffer,
124*758e9fbaSOystein Eftevaag             policy_hash.buffer,
125*758e9fbaSOystein Eftevaag             policy_hash.size);
126*758e9fbaSOystein Eftevaag 
127*758e9fbaSOystein Eftevaag     rc = Tss2_Sys_NV_DefineSpace (sys_ctx,
128*758e9fbaSOystein Eftevaag                                   TPM2_RH_PLATFORM,
129*758e9fbaSOystein Eftevaag                                   &auth_cmd,
130*758e9fbaSOystein Eftevaag                                   &nv_auth,
131*758e9fbaSOystein Eftevaag                                   &public_info,
132*758e9fbaSOystein Eftevaag                                   &auth_rsp);
133*758e9fbaSOystein Eftevaag     Tss2_Sys_FlushContext (sys_ctx, auth_handle);
134*758e9fbaSOystein Eftevaag     return_if_error (rc, "Tss2_Sys_NV_DefineSpace");
135*758e9fbaSOystein Eftevaag 
136*758e9fbaSOystein Eftevaag     return rc;
137*758e9fbaSOystein Eftevaag }
138*758e9fbaSOystein Eftevaag 
139*758e9fbaSOystein Eftevaag static TSS2_RC
teardown_nv(TSS2_SYS_CONTEXT * sys_ctx)140*758e9fbaSOystein Eftevaag teardown_nv (TSS2_SYS_CONTEXT *sys_ctx)
141*758e9fbaSOystein Eftevaag {
142*758e9fbaSOystein Eftevaag     TSS2_RC rc;
143*758e9fbaSOystein Eftevaag     const TSS2L_SYS_AUTH_COMMAND auth_cmd = {
144*758e9fbaSOystein Eftevaag         .count = 1,
145*758e9fbaSOystein Eftevaag         .auths = {
146*758e9fbaSOystein Eftevaag             {
147*758e9fbaSOystein Eftevaag                 .sessionHandle = TPM2_RS_PW,
148*758e9fbaSOystein Eftevaag             },
149*758e9fbaSOystein Eftevaag         },
150*758e9fbaSOystein Eftevaag     };
151*758e9fbaSOystein Eftevaag     TSS2L_SYS_AUTH_RESPONSE auth_rsp = { 0, };
152*758e9fbaSOystein Eftevaag 
153*758e9fbaSOystein Eftevaag     rc = Tss2_Sys_NV_UndefineSpace (sys_ctx,
154*758e9fbaSOystein Eftevaag                                     TPM2_RH_PLATFORM,
155*758e9fbaSOystein Eftevaag                                     NV_INDEX,
156*758e9fbaSOystein Eftevaag                                     &auth_cmd,
157*758e9fbaSOystein Eftevaag                                     &auth_rsp);
158*758e9fbaSOystein Eftevaag     return_if_error (rc, "Tss2_Sys_NV_UndefineSpace");
159*758e9fbaSOystein Eftevaag 
160*758e9fbaSOystein Eftevaag     return rc;
161*758e9fbaSOystein Eftevaag }
162*758e9fbaSOystein Eftevaag 
163*758e9fbaSOystein Eftevaag /*
164*758e9fbaSOystein Eftevaag  * This function performs a single write operation to the NV region. This
165*758e9fbaSOystein Eftevaag  * requires we first create a policy session that satisfies the policy
166*758e9fbaSOystein Eftevaag  * governing the region. If the write fails we must manually flush the
167*758e9fbaSOystein Eftevaag  * session since the continueSession flag only guarantees the policy is
168*758e9fbaSOystein Eftevaag  * flushed after successful command execution.
169*758e9fbaSOystein Eftevaag  */
170*758e9fbaSOystein Eftevaag static TSS2_RC
nv_write(TSS2_SYS_CONTEXT * sys_ctx)171*758e9fbaSOystein Eftevaag nv_write (TSS2_SYS_CONTEXT *sys_ctx)
172*758e9fbaSOystein Eftevaag {
173*758e9fbaSOystein Eftevaag     TSS2_RC rc;
174*758e9fbaSOystein Eftevaag     TSS2L_SYS_AUTH_COMMAND auth_cmd = {
175*758e9fbaSOystein Eftevaag         .count = 1,
176*758e9fbaSOystein Eftevaag     };
177*758e9fbaSOystein Eftevaag     TSS2L_SYS_AUTH_RESPONSE auth_rsp = { 0, };
178*758e9fbaSOystein Eftevaag     TPM2B_MAX_NV_BUFFER write_data = {
179*758e9fbaSOystein Eftevaag         .size = 4,
180*758e9fbaSOystein Eftevaag         .buffer = { 0xff, 0xfe, 0xfd, 0xfc, },
181*758e9fbaSOystein Eftevaag     };
182*758e9fbaSOystein Eftevaag 
183*758e9fbaSOystein Eftevaag     rc = create_policy_session (sys_ctx,
184*758e9fbaSOystein Eftevaag                                 &auth_cmd.auths[0].sessionHandle);
185*758e9fbaSOystein Eftevaag     return_if_error (rc, "create_policy_session");
186*758e9fbaSOystein Eftevaag 
187*758e9fbaSOystein Eftevaag     rc = Tss2_Sys_NV_Write (sys_ctx,
188*758e9fbaSOystein Eftevaag                             NV_INDEX,
189*758e9fbaSOystein Eftevaag                             NV_INDEX,
190*758e9fbaSOystein Eftevaag                             &auth_cmd,
191*758e9fbaSOystein Eftevaag                             &write_data,
192*758e9fbaSOystein Eftevaag                             0,
193*758e9fbaSOystein Eftevaag                             &auth_rsp);
194*758e9fbaSOystein Eftevaag     Tss2_Sys_FlushContext (sys_ctx, auth_cmd.auths [0].sessionHandle);
195*758e9fbaSOystein Eftevaag     return_if_error (rc, "Tss2_Sys_NV_Write");
196*758e9fbaSOystein Eftevaag 
197*758e9fbaSOystein Eftevaag     return rc;
198*758e9fbaSOystein Eftevaag }
199*758e9fbaSOystein Eftevaag /*
200*758e9fbaSOystein Eftevaag  * This function executes a write operation on the NV region from each
201*758e9fbaSOystein Eftevaag  * locality. Per the policy applied to the region @ provisioning, the
202*758e9fbaSOystein Eftevaag  * write command will fail for all localities except 3 and 4.
203*758e9fbaSOystein Eftevaag  */
204*758e9fbaSOystein Eftevaag static TSS2_RC
nv_write_test(TSS2_SYS_CONTEXT * sys_ctx)205*758e9fbaSOystein Eftevaag nv_write_test (TSS2_SYS_CONTEXT *sys_ctx)
206*758e9fbaSOystein Eftevaag {
207*758e9fbaSOystein Eftevaag     TSS2_RC rc;
208*758e9fbaSOystein Eftevaag     uint8_t locality;
209*758e9fbaSOystein Eftevaag     TSS2_TCTI_CONTEXT *tcti_ctx;
210*758e9fbaSOystein Eftevaag 
211*758e9fbaSOystein Eftevaag     LOG_INFO ("TPM NV write with locality policy test");
212*758e9fbaSOystein Eftevaag 
213*758e9fbaSOystein Eftevaag     rc = Tss2_Sys_GetTctiContext (sys_ctx, &tcti_ctx);
214*758e9fbaSOystein Eftevaag     return_if_error (rc, "Tss2_Sys_GetTctiContext");
215*758e9fbaSOystein Eftevaag 
216*758e9fbaSOystein Eftevaag     for (locality = 0; locality < 5; ++locality)
217*758e9fbaSOystein Eftevaag     {
218*758e9fbaSOystein Eftevaag         LOG_INFO ("%s: writing NV from locality %" PRIu8, __func__, locality);
219*758e9fbaSOystein Eftevaag         rc = Tss2_Tcti_SetLocality (tcti_ctx, locality);
220*758e9fbaSOystein Eftevaag         return_if_error (rc, "Tss2_Tcti_SetLocality");
221*758e9fbaSOystein Eftevaag 
222*758e9fbaSOystein Eftevaag         rc = nv_write (sys_ctx);
223*758e9fbaSOystein Eftevaag         switch (locality) {
224*758e9fbaSOystein Eftevaag             case 0:
225*758e9fbaSOystein Eftevaag             case 1:
226*758e9fbaSOystein Eftevaag             case 2:
227*758e9fbaSOystein Eftevaag                 if (rc != TPM2_RC_LOCALITY) {
228*758e9fbaSOystein Eftevaag                     LOG_ERROR ("nv_write: Expecting TPM2_RC_LOCALITY, got "
229*758e9fbaSOystein Eftevaag                                "0x%08" PRIu32, rc);
230*758e9fbaSOystein Eftevaag                     return 1;
231*758e9fbaSOystein Eftevaag                 }
232*758e9fbaSOystein Eftevaag                 break;
233*758e9fbaSOystein Eftevaag             case 3:
234*758e9fbaSOystein Eftevaag             case 4:
235*758e9fbaSOystein Eftevaag                 return_if_error (rc, "nv_write");
236*758e9fbaSOystein Eftevaag                 break;
237*758e9fbaSOystein Eftevaag             default: /* locality can only be 0-4 */
238*758e9fbaSOystein Eftevaag                 assert (false);
239*758e9fbaSOystein Eftevaag                 break;
240*758e9fbaSOystein Eftevaag         }
241*758e9fbaSOystein Eftevaag     }
242*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
243*758e9fbaSOystein Eftevaag }
244*758e9fbaSOystein Eftevaag /*
245*758e9fbaSOystein Eftevaag  * This function executes a read command on the NV region from each
246*758e9fbaSOystein Eftevaag  * locality providing the required auth value (empty). Per the policy
247*758e9fbaSOystein Eftevaag  * defined a provisioning all should succeed.
248*758e9fbaSOystein Eftevaag  */
249*758e9fbaSOystein Eftevaag static TSS2_RC
nv_read_test(TSS2_SYS_CONTEXT * sys_ctx)250*758e9fbaSOystein Eftevaag nv_read_test (TSS2_SYS_CONTEXT *sys_ctx)
251*758e9fbaSOystein Eftevaag {
252*758e9fbaSOystein Eftevaag     TSS2_RC rc;
253*758e9fbaSOystein Eftevaag     uint8_t locality;
254*758e9fbaSOystein Eftevaag     TPM2B_MAX_NV_BUFFER nv_buf;
255*758e9fbaSOystein Eftevaag     TSS2_TCTI_CONTEXT *tcti_ctx;
256*758e9fbaSOystein Eftevaag     TSS2L_SYS_AUTH_RESPONSE auth_rsp = { 0, };
257*758e9fbaSOystein Eftevaag     const TSS2L_SYS_AUTH_COMMAND auth_cmd = {
258*758e9fbaSOystein Eftevaag         .count = 1,
259*758e9fbaSOystein Eftevaag         .auths = {
260*758e9fbaSOystein Eftevaag             {
261*758e9fbaSOystein Eftevaag                 .sessionHandle = TPM2_RS_PW,
262*758e9fbaSOystein Eftevaag             },
263*758e9fbaSOystein Eftevaag         },
264*758e9fbaSOystein Eftevaag     };
265*758e9fbaSOystein Eftevaag 
266*758e9fbaSOystein Eftevaag     rc = Tss2_Sys_GetTctiContext (sys_ctx, &tcti_ctx);
267*758e9fbaSOystein Eftevaag     return_if_error (rc, "Tss2_Sys_GetTctiContext");
268*758e9fbaSOystein Eftevaag 
269*758e9fbaSOystein Eftevaag     LOG_INFO ("TPM NV read with auth test");
270*758e9fbaSOystein Eftevaag     for (locality = 0; locality < 5; ++locality)
271*758e9fbaSOystein Eftevaag     {
272*758e9fbaSOystein Eftevaag         rc = Tss2_Tcti_SetLocality (tcti_ctx, locality);
273*758e9fbaSOystein Eftevaag         return_if_error (rc, "Tss2_Tcti_SetLocality");
274*758e9fbaSOystein Eftevaag 
275*758e9fbaSOystein Eftevaag         nv_buf.size = TPM2B_SIZE_MAX (nv_buf);
276*758e9fbaSOystein Eftevaag         rc = TSS2_RETRY_EXP (Tss2_Sys_NV_Read (sys_ctx,
277*758e9fbaSOystein Eftevaag                                                NV_INDEX,
278*758e9fbaSOystein Eftevaag                                                NV_INDEX,
279*758e9fbaSOystein Eftevaag                                                &auth_cmd,
280*758e9fbaSOystein Eftevaag                                                4,
281*758e9fbaSOystein Eftevaag                                                0,
282*758e9fbaSOystein Eftevaag                                                &nv_buf,
283*758e9fbaSOystein Eftevaag                                                &auth_rsp));
284*758e9fbaSOystein Eftevaag         return_if_error (rc, "Tss2_Sys_NV_Read");
285*758e9fbaSOystein Eftevaag     }
286*758e9fbaSOystein Eftevaag 
287*758e9fbaSOystein Eftevaag     rc = Tss2_Tcti_SetLocality (tcti_ctx, 3);
288*758e9fbaSOystein Eftevaag     return_if_error (rc, "Tss2_Tcti_SetLocality");
289*758e9fbaSOystein Eftevaag 
290*758e9fbaSOystein Eftevaag     return rc;
291*758e9fbaSOystein Eftevaag }
292*758e9fbaSOystein Eftevaag 
293*758e9fbaSOystein Eftevaag int
test_invoke(TSS2_SYS_CONTEXT * sys_ctx)294*758e9fbaSOystein Eftevaag test_invoke (TSS2_SYS_CONTEXT *sys_ctx)
295*758e9fbaSOystein Eftevaag {
296*758e9fbaSOystein Eftevaag     TSS2_RC rc, rc_teardown;
297*758e9fbaSOystein Eftevaag 
298*758e9fbaSOystein Eftevaag     rc = setup_nv (sys_ctx);
299*758e9fbaSOystein Eftevaag     return_if_error (rc, "setup_nv");
300*758e9fbaSOystein Eftevaag     rc = nv_write_test (sys_ctx);
301*758e9fbaSOystein Eftevaag     goto_if_error (rc, "nv_write_test", teardown);
302*758e9fbaSOystein Eftevaag     rc = nv_read_test (sys_ctx);
303*758e9fbaSOystein Eftevaag     goto_if_error (rc, "nv_read_test", teardown);
304*758e9fbaSOystein Eftevaag teardown:
305*758e9fbaSOystein Eftevaag     rc_teardown = teardown_nv (sys_ctx);
306*758e9fbaSOystein Eftevaag     return_if_error (rc, "NV policy locality test failed");
307*758e9fbaSOystein Eftevaag     return_if_error (rc_teardown, "teardown_nv");
308*758e9fbaSOystein Eftevaag 
309*758e9fbaSOystein Eftevaag     return rc;
310*758e9fbaSOystein Eftevaag }
311