1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "hvb_cmdline.h"
16 #include "hvb_util.h"
17 #include "hvb_cert.h"
18 #include "hvb_rvt.h"
19 #include "hvb_ops.h"
20 #include "hvb.h"
21 #include "hvb_sysdeps.h"
22 #include "hvb_crypto.h"
23
cmdline_append_option(struct hvb_verified_data *vd, const char *key, const char *value)24 static int cmdline_append_option(struct hvb_verified_data *vd, const char *key, const char *value)
25 {
26 uint64_t option_len = 0;
27 uint64_t key_len, value_len;
28 struct hvb_cmdline_data *cmdline = NULL;
29
30 if (vd == NULL || vd->cmdline.buf == NULL)
31 return 0;
32
33 cmdline = &vd->cmdline;
34
35 key_len = hvb_strlen(key);
36 value_len = hvb_strlen(value);
37 /* 2 for blank space and = */
38 option_len = key_len + value_len + 2;
39 if (option_len > cmdline->max_size - cmdline->cur_pos - 1)
40 return 0;
41
42 /* append blank space */
43 cmdline->buf[cmdline->cur_pos] = ' ';
44 cmdline->cur_pos++;
45 /* append key */
46 hvb_memcpy(cmdline->buf + cmdline->cur_pos, key, key_len);
47 cmdline->cur_pos += key_len;
48 /* append = */
49 cmdline->buf[cmdline->cur_pos] = '=';
50 cmdline->cur_pos++;
51 /* append value */
52 hvb_memcpy(cmdline->buf + cmdline->cur_pos, value, value_len);
53 cmdline->cur_pos += value_len;
54
55 return 1;
56 }
57
hvb_append_version_cmdline(struct hvb_verified_data *vd, const char *key_value, uint64_t version_major, uint64_t version_minor)58 static int hvb_append_version_cmdline(struct hvb_verified_data *vd, const char *key_value,
59 uint64_t version_major, uint64_t version_minor)
60 {
61 char major_digits[HVB_MAX_DIGITS_UINT64];
62 char minor_digits[HVB_MAX_DIGITS_UINT64];
63 char combined[HVB_MAX_DIGITS_UINT64 * 2 + 1];
64 uint64_t num_major_digits, num_minor_digits;
65
66 num_major_digits = hvb_uint64_to_base10(version_major, major_digits);
67 num_minor_digits = hvb_uint64_to_base10(version_minor, minor_digits);
68
69 hvb_memcpy(combined, major_digits, num_major_digits);
70 combined[num_major_digits] = '.';
71 hvb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
72 combined[num_major_digits + 1 + num_minor_digits] = '\0';
73
74 return cmdline_append_option(vd, key_value, combined);
75 }
76
cmdline_append_uint64_base10(struct hvb_verified_data *vd, const char *key, uint64_t value)77 static int cmdline_append_uint64_base10(struct hvb_verified_data *vd, const char *key, uint64_t value)
78 {
79 char digits[HVB_MAX_DIGITS_UINT64];
80
81 hvb_uint64_to_base10(value, digits);
82
83 return cmdline_append_option(vd, key, digits);
84 }
85
cmdline_append_hex(struct hvb_verified_data *vd, const char* key, const uint8_t *data, uint64_t data_len)86 static int cmdline_append_hex(struct hvb_verified_data *vd, const char* key,
87 const uint8_t *data, uint64_t data_len)
88 {
89 int ret;
90 char *hex_data = hvb_bin2hex(data, data_len);
91
92 if (hex_data == NULL) {
93 return 0;
94 }
95
96 ret = cmdline_append_option(vd, key, hex_data);
97 hvb_free(hex_data);
98
99 return ret;
100 }
101
hvb_creat_cmdline(struct hvb_ops *ops, struct hvb_verified_data *vd)102 enum hvb_errno hvb_creat_cmdline(struct hvb_ops *ops, struct hvb_verified_data *vd)
103 {
104 hvb_return_hvb_err_if_null(ops);
105 hvb_return_hvb_err_if_null(vd);
106
107 enum hvb_errno ret = HVB_OK;
108 enum hvb_io_errno io_ret = HVB_IO_OK;
109 bool device_locked = false;
110 ret = check_hvb_ops(ops);
111 if (ret != HVB_OK) {
112 hvb_print("error, check ops\n");
113 return HVB_ERROR_INVALID_ARGUMENT;
114 }
115
116 /* set ohos.boot.hvb.version. */
117 if (!hvb_append_version_cmdline(vd, HVB_CMDLINE_VERSION,
118 HVB_VERSION_MAJOR, HVB_VERSION_MINOR)) {
119 ret = HVB_ERROR_OOM;
120 goto fail;
121 }
122
123 /* set ohos.boot.device_state to "locked" or "unlocked". */
124 io_ret = ops->read_lock_state(ops, &device_locked);
125 if (io_ret == HVB_IO_ERROR_OOM) {
126 ret = HVB_ERROR_OOM;
127 goto fail;
128 } else if (io_ret != HVB_IO_OK) {
129 hvb_print("Error getting device state.\n");
130 ret = HVB_ERROR_IO;
131 goto fail;
132 }
133
134 if (!cmdline_append_option(vd, HVB_CMDLINE_DEV_STATE,
135 device_locked ? "locked" : "unlocked")) {
136 ret = HVB_ERROR_OOM;
137 goto fail;
138 }
139
140 /*
141 * set ohos.boot.hvb.{hash_algo, size, digest} - use same hash
142 * function as is used to sign rvt.
143 */
144 uint8_t rvt_digest[HVB_SHA256_DIGEST_BYTES] = {0};
145 uint64_t rvt_size = 0;
146 for (uint64_t n = 0; n < vd->num_loaded_certs; n++) {
147 rvt_size += vd->certs[n].data.size;
148 }
149
150 if (hvb_calculate_certs_digest(vd, rvt_digest) != HVB_OK) {
151 hvb_print("Error calculate rvt digest.\n");
152 ret = HVB_ERROR_OOM;
153 goto fail;
154 }
155
156 if (!cmdline_append_option(vd, HVB_CMDLINE_HASH_ALG, "sha256") ||
157 !cmdline_append_uint64_base10(vd, HVB_CMDLINE_RVT_SIZE, rvt_size) ||
158 !cmdline_append_hex(vd, HVB_CMDLINE_CERT_DIGEST, rvt_digest, HVB_SHA256_DIGEST_BYTES)) {
159 ret = HVB_ERROR_OOM;
160 goto fail;
161 }
162
163 fail:
164 return ret;
165 }
166