capability device: get it to compile
[akaros.git] / kern / lib / crypto / 2api.c
1 /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Externally-callable APIs
6  * (Firmware portion)
7  */
8
9 #include "2sysincludes.h"
10 #include "2api.h"
11 #include "2common.h"
12 #include "2misc.h"
13 #include "2nvstorage.h"
14 #include "2secdata.h"
15 #include "2sha.h"
16 #include "2rsa.h"
17 #include "2tpm_bootmode.h"
18
19 int vb2api_secdata_check(const struct vb2_context *ctx)
20 {
21         return vb2_secdata_check_crc(ctx);
22 }
23
24 int vb2api_secdata_create(struct vb2_context *ctx)
25 {
26         return vb2_secdata_create(ctx);
27 }
28
29 void vb2api_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode)
30 {
31         /* Initialize the vboot context if it hasn't been yet */
32         vb2_init_context(ctx);
33
34         vb2_fail(ctx, reason, subcode);
35 }
36
37 int vb2api_fw_phase1(struct vb2_context *ctx)
38 {
39         int rv;
40
41         /* Initialize the vboot context if it hasn't been yet */
42         vb2_init_context(ctx);
43
44         /* Initialize NV context */
45         vb2_nv_init(ctx);
46
47         /*
48          * Handle caller-requested reboot due to secdata.  Do this before we
49          * even look at secdata.  If we fail because of a reboot loop we'll be
50          * the first failure so will get to set the recovery reason.
51          */
52         if (!(ctx->flags & VB2_CONTEXT_SECDATA_WANTS_REBOOT)) {
53                 /* No reboot requested */
54                 vb2_nv_set(ctx, VB2_NV_TPM_REQUESTED_REBOOT, 0);
55         } else if (vb2_nv_get(ctx, VB2_NV_TPM_REQUESTED_REBOOT)) {
56                 /*
57                  * Reboot requested... again.  Fool me once, shame on you.
58                  * Fool me twice, shame on me.  Fail into recovery to avoid
59                  * a reboot loop.
60                  */
61                 vb2_fail(ctx, VB2_RECOVERY_RO_TPM_REBOOT, 0);
62         } else {
63                 /* Reboot requested for the first time */
64                 vb2_nv_set(ctx, VB2_NV_TPM_REQUESTED_REBOOT, 1);
65                 return VB2_ERROR_API_PHASE1_SECDATA_REBOOT;
66         }
67
68         /* Initialize secure data */
69         rv = vb2_secdata_init(ctx);
70         if (rv)
71                 vb2_fail(ctx, VB2_RECOVERY_SECDATA_INIT, rv);
72
73         /* Load and parse the GBB header */
74         rv = vb2_fw_parse_gbb(ctx);
75         if (rv)
76                 vb2_fail(ctx, VB2_RECOVERY_GBB_HEADER, rv);
77
78         /*
79          * Check for recovery.  Note that this function returns void, since any
80          * errors result in requesting recovery.  That's also why we don't
81          * return error from failures in the preceding two steps; those
82          * failures simply cause us to detect recovery mode here.
83          */
84         vb2_check_recovery(ctx);
85
86         /* Check for dev switch */
87         rv = vb2_check_dev_switch(ctx);
88         if (rv && !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
89                 /*
90                  * Error in dev switch processing, and we weren't already
91                  * headed for recovery mode.  Reboot into recovery mode, since
92                  * it's too late to handle those errors this boot, and we need
93                  * to take a different path through the dev switch checking
94                  * code in that case.
95                  */
96                 vb2_fail(ctx, VB2_RECOVERY_DEV_SWITCH, rv);
97                 return rv;
98         }
99
100         /* Return error if recovery is needed */
101         if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
102                 /* Always clear RAM when entering recovery mode */
103                 ctx->flags |= VB2_CONTEXT_CLEAR_RAM;
104                 return VB2_ERROR_API_PHASE1_RECOVERY;
105         }
106
107         return VB2_SUCCESS;
108 }
109
110 int vb2api_fw_phase2(struct vb2_context *ctx)
111 {
112         int rv;
113
114         /*
115          * Use the slot from the last boot if this is a resume.  Do not set
116          * VB2_SD_STATUS_CHOSE_SLOT so the try counter is not decremented on
117          * failure as we are explicitly not attempting to boot from a new slot.
118          */
119         if (ctx->flags & VB2_CONTEXT_S3_RESUME) {
120                 struct vb2_shared_data *sd = vb2_get_sd(ctx);
121
122                 /* Set the current slot to the last booted slot */
123                 sd->fw_slot = vb2_nv_get(ctx, VB2_NV_FW_TRIED);
124
125                 /* Set context flag if we're using slot B */
126                 if (sd->fw_slot)
127                         ctx->flags |= VB2_CONTEXT_FW_SLOT_B;
128
129                 return VB2_SUCCESS;
130         }
131
132         /* Always clear RAM when entering developer mode */
133         if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)
134                 ctx->flags |= VB2_CONTEXT_CLEAR_RAM;
135
136         /* Check for explicit request to clear TPM */
137         rv = vb2_check_tpm_clear(ctx);
138         if (rv) {
139                 vb2_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
140                 return rv;
141         }
142
143         /* Decide which firmware slot to try this boot */
144         rv = vb2_select_fw_slot(ctx);
145         if (rv) {
146                 vb2_fail(ctx, VB2_RECOVERY_FW_SLOT, rv);
147                 return rv;
148         }
149
150         return VB2_SUCCESS;
151 }
152
153 int vb2api_extend_hash(struct vb2_context *ctx,
154                        const void *buf,
155                        uint32_t size)
156 {
157         struct vb2_shared_data *sd = vb2_get_sd(ctx);
158         struct vb2_digest_context *dc = (struct vb2_digest_context *)
159                 (ctx->workbuf + sd->workbuf_hash_offset);
160
161         /* Must have initialized hash digest work area */
162         if (!sd->workbuf_hash_size)
163                 return VB2_ERROR_API_EXTEND_HASH_WORKBUF;
164
165         /* Don't extend past the data we expect to hash */
166         if (!size || size > sd->hash_remaining_size)
167                 return VB2_ERROR_API_EXTEND_HASH_SIZE;
168
169         sd->hash_remaining_size -= size;
170
171         if (dc->using_hwcrypto)
172                 return vb2ex_hwcrypto_digest_extend(buf, size);
173         else
174                 return vb2_digest_extend(dc, buf, size);
175 }
176
177 int vb2api_get_pcr_digest(struct vb2_context *ctx,
178                           enum vb2_pcr_digest which_digest,
179                           uint8_t *dest,
180                           uint32_t *dest_size)
181 {
182         const uint8_t *digest;
183         uint32_t digest_size;
184
185         switch (which_digest) {
186         case BOOT_MODE_PCR:
187                 digest = vb2_get_boot_state_digest(ctx);
188                 digest_size = VB2_SHA1_DIGEST_SIZE;
189                 break;
190         case HWID_DIGEST_PCR:
191                 digest = vb2_get_sd(ctx)->gbb_hwid_digest;
192                 digest_size = VB2_GBB_HWID_DIGEST_SIZE;
193                 break;
194         default:
195                 return VB2_ERROR_API_PCR_DIGEST;
196         }
197
198         if (digest == NULL || *dest_size < digest_size)
199                 return VB2_ERROR_API_PCR_DIGEST_BUF;
200
201         memcpy(dest, digest, digest_size);
202         if (digest_size < *dest_size)
203                 memset(dest + digest_size, 0, *dest_size - digest_size);
204
205         *dest_size = digest_size;
206
207         return VB2_SUCCESS;
208 }