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 * Secure storage APIs
6 */
7
8#include "2sysincludes.h"
9#include "2common.h"
10#include "2crc8.h"
11#include "2misc.h"
12#include "2secdata.h"
13
14int vb2_secdata_check_crc(const struct vb2_context *ctx)
15{
16	const struct vb2_secdata *sec =
17		(const struct vb2_secdata *)ctx->secdata;
18
19	/* Verify CRC */
20	if (sec->crc8 != vb2_crc8(sec, offsetof(struct vb2_secdata, crc8)))
21		return VB2_ERROR_SECDATA_CRC;
22
23	return VB2_SUCCESS;
24}
25
26int vb2_secdata_create(struct vb2_context *ctx)
27{
28	struct vb2_secdata *sec = (struct vb2_secdata *)ctx->secdata;
29
30	/* Clear the entire struct */
31	memset(sec, 0, sizeof(*sec));
32
33	/* Set to current version */
34	sec->struct_version = VB2_SECDATA_VERSION;
35
36	/* Calculate initial CRC */
37	sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdata, crc8));
38	ctx->flags |= VB2_CONTEXT_SECDATA_CHANGED;
39	return VB2_SUCCESS;
40}
41
42int vb2_secdata_init(struct vb2_context *ctx)
43{
44	struct vb2_shared_data *sd = vb2_get_sd(ctx);
45	int rv;
46
47	rv = vb2_secdata_check_crc(ctx);
48	if (rv)
49		return rv;
50
51	/* Set status flag */
52	sd->status |= VB2_SD_STATUS_SECDATA_INIT;
53	// TODO: unit test for that
54
55	/* Read this now to make sure crossystem has it even in rec mode. */
56	rv = vb2_secdata_get(ctx, VB2_SECDATA_VERSIONS,
57			     &sd->fw_version_secdata);
58	if (rv)
59		return rv;
60
61	return VB2_SUCCESS;
62}
63
64int vb2_secdata_get(struct vb2_context *ctx,
65		    enum vb2_secdata_param param,
66		    uint32_t *dest)
67{
68	struct vb2_secdata *sec = (struct vb2_secdata *)ctx->secdata;
69
70	if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATA_INIT))
71		return VB2_ERROR_SECDATA_GET_UNINITIALIZED;
72
73	switch(param) {
74	case VB2_SECDATA_FLAGS:
75		*dest = sec->flags;
76		return VB2_SUCCESS;
77
78	case VB2_SECDATA_VERSIONS:
79		*dest = sec->fw_versions;
80		return VB2_SUCCESS;
81
82	default:
83		return VB2_ERROR_SECDATA_GET_PARAM;
84	}
85}
86
87int vb2_secdata_set(struct vb2_context *ctx,
88		    enum vb2_secdata_param param,
89		    uint32_t value)
90{
91	struct vb2_secdata *sec = (struct vb2_secdata *)ctx->secdata;
92	uint32_t now;
93
94	if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATA_INIT))
95		return VB2_ERROR_SECDATA_SET_UNINITIALIZED;
96
97	/* If not changing the value, don't regenerate the CRC. */
98	if (vb2_secdata_get(ctx, param, &now) == VB2_SUCCESS && now == value)
99		return VB2_SUCCESS;
100
101	switch(param) {
102	case VB2_SECDATA_FLAGS:
103		/* Make sure flags is in valid range */
104		if (value > 0xff)
105			return VB2_ERROR_SECDATA_SET_FLAGS;
106
107		sec->flags = value;
108		break;
109
110	case VB2_SECDATA_VERSIONS:
111		sec->fw_versions = value;
112		break;
113
114	default:
115		return VB2_ERROR_SECDATA_SET_PARAM;
116	}
117
118	/* Regenerate CRC */
119	sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdata, crc8));
120	ctx->flags |= VB2_CONTEXT_SECDATA_CHANGED;
121	return VB2_SUCCESS;
122}
123