• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 #define RSA_KEYWORD "sha256"
25 #define SM_KEYWORD "sm3"
26 
cmdline_append_option(struct hvb_verified_data * vd,const char * key,const char * value)27 static int cmdline_append_option(struct hvb_verified_data *vd, const char *key, const char *value)
28 {
29     uint64_t option_len = 0;
30     uint64_t key_len, value_len;
31     struct hvb_cmdline_data *cmdline = NULL;
32 
33     if (vd == NULL || vd->cmdline.buf == NULL)
34         return 0;
35 
36     cmdline = &vd->cmdline;
37 
38     key_len = hvb_strlen(key);
39     value_len = hvb_strlen(value);
40     /* 2 for blank space and = */
41     option_len = key_len + value_len + 2;
42     if (option_len > cmdline->max_size - cmdline->cur_pos - 1)
43         return 0;
44 
45     /* append blank space */
46     cmdline->buf[cmdline->cur_pos] = ' ';
47     cmdline->cur_pos++;
48     /* append key */
49     hvb_memcpy(cmdline->buf + cmdline->cur_pos, key, key_len);
50     cmdline->cur_pos += key_len;
51     /* append = */
52     cmdline->buf[cmdline->cur_pos] = '=';
53     cmdline->cur_pos++;
54     /* append value */
55     hvb_memcpy(cmdline->buf + cmdline->cur_pos, value, value_len);
56     cmdline->cur_pos += value_len;
57 
58     return 1;
59 }
60 
hvb_append_version_cmdline(struct hvb_verified_data * vd,const char * key_value,uint64_t version_major,uint64_t version_minor)61 static int hvb_append_version_cmdline(struct hvb_verified_data *vd, const char *key_value,
62                                       uint64_t version_major, uint64_t version_minor)
63 {
64     char major_digits[HVB_MAX_DIGITS_UINT64];
65     char minor_digits[HVB_MAX_DIGITS_UINT64];
66     char combined[HVB_MAX_DIGITS_UINT64 * 2 + 1];
67     uint64_t num_major_digits, num_minor_digits;
68 
69     num_major_digits = hvb_uint64_to_base10(version_major, major_digits);
70     num_minor_digits = hvb_uint64_to_base10(version_minor, minor_digits);
71 
72     hvb_memcpy(combined, major_digits, num_major_digits);
73     combined[num_major_digits] = '.';
74     hvb_memcpy(combined + num_major_digits + 1, minor_digits, num_minor_digits);
75     combined[num_major_digits + 1 + num_minor_digits] = '\0';
76 
77     return cmdline_append_option(vd, key_value, combined);
78 }
79 
cmdline_append_uint64_base10(struct hvb_verified_data * vd,const char * key,uint64_t value)80 static int cmdline_append_uint64_base10(struct hvb_verified_data *vd, const char *key, uint64_t value)
81 {
82     char digits[HVB_MAX_DIGITS_UINT64];
83 
84     hvb_uint64_to_base10(value, digits);
85 
86     return cmdline_append_option(vd, key, digits);
87 }
88 
cmdline_append_hex(struct hvb_verified_data * vd,const char * key,const uint8_t * data,uint64_t data_len)89 static int cmdline_append_hex(struct hvb_verified_data *vd, const char* key,
90                               const uint8_t *data, uint64_t data_len)
91 {
92     int ret;
93     char *hex_data = hvb_bin2hex(data, data_len);
94 
95     if (hex_data == NULL) {
96         return 0;
97     }
98 
99     ret = cmdline_append_option(vd, key, hex_data);
100     hvb_free(hex_data);
101 
102     return ret;
103 }
104 
hvb_creat_cmdline(struct hvb_ops * ops,struct hvb_verified_data * vd)105 enum hvb_errno hvb_creat_cmdline(struct hvb_ops *ops, struct hvb_verified_data *vd)
106 {
107     hvb_return_hvb_err_if_null(ops);
108     hvb_return_hvb_err_if_null(vd);
109 
110     enum hvb_errno ret = HVB_OK;
111     enum hvb_io_errno io_ret = HVB_IO_OK;
112     bool device_locked = false;
113     ret = check_hvb_ops(ops);
114     if (ret != HVB_OK) {
115         hvb_print("error, check ops\n");
116         return HVB_ERROR_INVALID_ARGUMENT;
117     }
118 
119     /* set ohos.boot.hvb.version. */
120     if (!hvb_append_version_cmdline(vd, HVB_CMDLINE_VERSION,
121                                     HVB_VERSION_MAJOR, HVB_VERSION_MINOR)) {
122         ret = HVB_ERROR_OOM;
123         goto fail;
124     }
125 
126     /* set ohos.boot.device_state to "locked" or "unlocked". */
127     io_ret = ops->read_lock_state(ops, &device_locked);
128     if (io_ret == HVB_IO_ERROR_OOM) {
129         ret = HVB_ERROR_OOM;
130         goto fail;
131     } else if (io_ret != HVB_IO_OK) {
132         hvb_print("Error getting device state.\n");
133         ret = HVB_ERROR_IO;
134         goto fail;
135     }
136 
137     if (!cmdline_append_option(vd, HVB_CMDLINE_DEV_STATE,
138                                device_locked ? "locked" : "unlocked")) {
139         ret = HVB_ERROR_OOM;
140         goto fail;
141     }
142 
143     /*
144      * set ohos.boot.hvb.{hash_algo, size, digest} - use same hash
145      * function as is used to sign rvt.
146      */
147     uint8_t rvt_digest[HVB_SHA256_DIGEST_BYTES] = {0};
148     uint64_t rvt_size = 0;
149     for (uint64_t n = 0; n < vd->num_loaded_certs; n++) {
150         rvt_size += vd->certs[n].data.size;
151     }
152 
153     if (hvb_calculate_certs_digest(vd, rvt_digest) != HVB_OK) {
154         hvb_print("Error calculate rvt digest.\n");
155         ret = HVB_ERROR_OOM;
156         goto fail;
157     }
158 
159     switch (vd->algorithm) {
160         case 0: // SHA256_RSA3072
161         case 1: // SHA256_RSA4096
162         case 2: { // SHA256_RSA2048
163             if (!cmdline_append_option(vd, HVB_CMDLINE_HASH_ALG, RSA_KEYWORD)) {
164                 ret = HVB_ERROR_OOM;
165                 goto fail;
166             }
167             break;
168         }
169         case 3: { // sm2_sm3
170             if (!cmdline_append_option(vd, HVB_CMDLINE_HASH_ALG, SM_KEYWORD)) {
171                 ret = HVB_ERROR_OOM;
172                 goto fail;
173             }
174             break;
175         }
176         default: {
177             hvb_print("hvb_creat_cmdline error: invalid algorithm\n");
178             return HVB_ERROR_INVALID_ARGUMENT;
179         }
180     }
181 
182     if (!cmdline_append_uint64_base10(vd, HVB_CMDLINE_RVT_SIZE, rvt_size) ||
183         !cmdline_append_hex(vd, HVB_CMDLINE_CERT_DIGEST, rvt_digest, HVB_SHA256_DIGEST_BYTES)) {
184         ret = HVB_ERROR_OOM;
185         goto fail;
186     }
187 
188 fail:
189     return ret;
190 }
191