xref: /aosp_15_r20/external/vboot_reference/firmware/lib20/api_kernel.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2015 The ChromiumOS Authors
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  * (Kernel portion)
7  */
8 
9 #include "2api.h"
10 #include "2common.h"
11 #include "2misc.h"
12 #include "2nvstorage.h"
13 #include "2rsa.h"
14 #include "2secdata.h"
15 #include "2sha.h"
16 #include "2sysincludes.h"
17 
vb2api_load_kernel_vblock(struct vb2_context * ctx)18 vb2_error_t vb2api_load_kernel_vblock(struct vb2_context *ctx)
19 {
20 	/* Verify kernel keyblock */
21 	VB2_TRY(vb2_load_kernel_keyblock(ctx));
22 
23 	/* Verify kernel preamble */
24 	VB2_TRY(vb2_load_kernel_preamble(ctx));
25 
26 	return VB2_SUCCESS;
27 }
28 
vb2api_get_kernel_size(struct vb2_context * ctx,uint32_t * offset_ptr,uint32_t * size_ptr)29 vb2_error_t vb2api_get_kernel_size(struct vb2_context *ctx,
30 				   uint32_t *offset_ptr, uint32_t *size_ptr)
31 {
32 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
33 	const struct vb2_kernel_preamble *pre;
34 
35 	/* Get preamble pointer */
36 	if (!sd->preamble_size)
37 		return VB2_ERROR_API_GET_KERNEL_SIZE_PREAMBLE;
38 
39 	pre = (const struct vb2_kernel_preamble *)
40 		vb2_member_of(sd, sd->preamble_offset);
41 
42 	if (offset_ptr) {
43 		/* The kernel implicitly follows the preamble */
44 		*offset_ptr = sd->vblock_preamble_offset +
45 			sd->preamble_size;
46 	}
47 
48 	if (size_ptr) {
49 		/* Expect the kernel to be the size of data we signed */
50 		*size_ptr = pre->body_signature.data_size;
51 	}
52 
53 	return VB2_SUCCESS;
54 }
55 
vb2api_verify_kernel_data(struct vb2_context * ctx,const void * buf,uint32_t size)56 vb2_error_t vb2api_verify_kernel_data(struct vb2_context *ctx, const void *buf,
57 				      uint32_t size)
58 {
59 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
60 	struct vb2_kernel_preamble *pre;
61 	struct vb2_digest_context *dc;
62 	struct vb2_public_key key;
63 	struct vb2_workbuf wb;
64 
65 	uint8_t *digest;
66 	uint32_t digest_size;
67 
68 	vb2_workbuf_from_ctx(ctx, &wb);
69 
70 	/* Get preamble pointer */
71 	if (!sd->preamble_size)
72 		return VB2_ERROR_API_VERIFY_KDATA_PREAMBLE;
73 
74 	pre = (struct vb2_kernel_preamble *)
75 		vb2_member_of(sd, sd->preamble_offset);
76 
77 	/* Make sure we were passed the right amount of data */
78 	if (size != pre->body_signature.data_size)
79 		return VB2_ERROR_API_VERIFY_KDATA_SIZE;
80 
81 	/* Allocate workbuf space for the hash */
82 	dc = vb2_workbuf_alloc(&wb, sizeof(*dc));
83 	if (!dc)
84 		return VB2_ERROR_API_VERIFY_KDATA_WORKBUF;
85 
86 	/*
87 	 * Unpack the kernel data key to see which hashing algorithm we
88 	 * should use.
89 	 *
90 	 * TODO: really, the kernel body should be hashed, and not signed,
91 	 * because the signature we're checking is already signed as part of
92 	 * the kernel preamble.  But until we can change the signing scripts,
93 	 * we're stuck with a signature here instead of a hash.
94 	 */
95 	if (!sd->data_key_size)
96 		return VB2_ERROR_API_VERIFY_KDATA_KEY;
97 
98 	VB2_TRY(vb2_unpack_key_buffer(&key,
99 				      vb2_member_of(sd, sd->data_key_offset),
100 				      sd->data_key_size));
101 
102 	VB2_TRY(vb2_digest_init(dc, vb2api_hwcrypto_allowed(ctx),
103 				key.hash_alg, size));
104 
105 	VB2_TRY(vb2_digest_extend(dc, buf, size));
106 
107 	digest_size = vb2_digest_size(key.hash_alg);
108 	digest = vb2_workbuf_alloc(&wb, digest_size);
109 	if (!digest)
110 		return VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST;
111 
112 	VB2_TRY(vb2_digest_finalize(dc, digest, digest_size));
113 
114 	/*
115 	 * The body signature is currently a *signature* of the body data, not
116 	 * just its hash.  So we need to verify the signature.
117 	 */
118 
119 	/*
120 	 * Check digest vs. signature.  Note that this destroys the signature.
121 	 * That's ok, because we only check each signature once per boot.
122 	 */
123 	return vb2_verify_digest(&key, &pre->body_signature, digest, &wb);
124 }
125 
vb2api_kernel_phase3(struct vb2_context * ctx)126 vb2_error_t vb2api_kernel_phase3(struct vb2_context *ctx)
127 {
128 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
129 
130 	/*
131 	 * If the kernel is a newer version than in secure storage, and the
132 	 * kernel signature is valid, and we're not in recovery mode, and we're
133 	 * allowed to, roll forward the version in secure storage.
134 	 */
135 	if (sd->kernel_version > sd->kernel_version_secdata &&
136 	    (sd->flags & VB2_SD_FLAG_KERNEL_SIGNED) &&
137 	    !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE) &&
138 	    (ctx->flags & VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD)) {
139 		vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS,
140 					    sd->kernel_version);
141 		sd->kernel_version_secdata = sd->kernel_version;
142 	}
143 
144 	return VB2_SUCCESS;
145 }
146