summaryrefslogtreecommitdiff
path: root/firmware/2lib/2gbb.c
blob: 8a7c57c587cf00ef36b6455dea7bca6007733c0c (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
/* Copyright 2019 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * GBB accessor functions.
 */

#include "2common.h"
#include "2misc.h"

static int vb2_gbb_read_key(struct vb2_context *ctx,
			    uint32_t offset,
			    uint32_t *size,
			    struct vb2_packed_key **keyp,
			    struct vb2_workbuf *wb)
{
	struct vb2_workbuf wblocal = *wb;
	int rv;

	/* Check offset and size. */
	if (offset < sizeof(struct vb2_gbb_header))
		return VB2_ERROR_GBB_INVALID;
	if (*size < sizeof(**keyp))
		return VB2_ERROR_GBB_INVALID;

	/* GBB header might be padded.  Retrieve the vb2_packed_key
	   header so we can find out what the real size is. */
	*keyp = vb2_workbuf_alloc(&wblocal, sizeof(**keyp));
	if (!*keyp)
		return VB2_ERROR_GBB_WORKBUF;
	rv = vb2ex_read_resource(ctx, VB2_RES_GBB, offset, *keyp,
				 sizeof(**keyp));
	if (rv)
		return rv;

	rv = vb2_verify_packed_key_inside(*keyp, *size, *keyp);
	if (rv)
		return rv;

	/* Deal with a zero-size key (used in testing). */
	*size = (*keyp)->key_offset + (*keyp)->key_size;
	if (*size < sizeof(**keyp))
		*size = sizeof(**keyp);

	/* Now that we know the real size of the key, retrieve the key
	   data, and write it on the workbuf, directly after vb2_packed_key. */
	*keyp = vb2_workbuf_realloc(&wblocal, sizeof(**keyp), *size);
	if (!*keyp)
		return VB2_ERROR_GBB_WORKBUF;

	rv = vb2ex_read_resource(ctx, VB2_RES_GBB,
				 offset + sizeof(**keyp),
				 (void *)*keyp + sizeof(**keyp),
				 *size - sizeof(**keyp));
	if (!rv)
		*wb = wblocal;
	return rv;
}

int vb2_gbb_read_root_key(struct vb2_context *ctx,
			  struct vb2_packed_key **keyp,
			  uint32_t *size,
			  struct vb2_workbuf *wb)
{
	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
	uint32_t size_in = gbb->rootkey_size;
	int ret = vb2_gbb_read_key(ctx, gbb->rootkey_offset,
				   &size_in, keyp, wb);
	if (size)
		*size = size_in;
	return ret;
}

int vb2_gbb_read_recovery_key(struct vb2_context *ctx,
			      struct vb2_packed_key **keyp,
			      uint32_t *size,
			      struct vb2_workbuf *wb)
{
	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
	uint32_t size_in = gbb->recovery_key_size;
	int ret = vb2_gbb_read_key(ctx, gbb->recovery_key_offset,
				   &size_in, keyp, wb);
	if (size)
		*size = size_in;
	return ret;
}

int vb2api_gbb_read_hwid(struct vb2_context *ctx,
			 char *hwid,
			 uint32_t *size)
{
	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
	uint32_t i;
	int ret;

	if (gbb->hwid_size == 0) {
		VB2_DEBUG("invalid HWID size %d\n", gbb->hwid_size);
		return VB2_ERROR_GBB_INVALID;
	}

	if (*size > VB2_GBB_HWID_MAX_SIZE)
		*size = VB2_GBB_HWID_MAX_SIZE;
	if (*size > gbb->hwid_size)
		*size = gbb->hwid_size;

	ret = vb2ex_read_resource(ctx, VB2_RES_GBB, gbb->hwid_offset,
				  hwid, *size);
	if (ret) {
		VB2_DEBUG("read resource failure: %d\n", ret);
		return ret;
	}

	/* Count HWID size, and ensure that it fits in the given buffer. */
	for (i = 0; i < *size; i++) {
		if (hwid[i] == '\0') {
			*size = i + 1;
			break;
		}
	}
	if (hwid[*size - 1] != '\0')
		return VB2_ERROR_INVALID_PARAMETER;

	return VB2_SUCCESS;
}

vb2_gbb_flags_t vb2api_gbb_get_flags(struct vb2_context *ctx)
{
	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
	return gbb->flags;
}