1 /*
2  * Copyright (c) 2024 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 
16 #include "key_utils.h"
17 
18 #include <cstdlib>
19 #include <dlfcn.h>
20 #include <fcntl.h>
21 #include <string>
22 #include <unistd.h>
23 #include <securec.h>
24 
25 #include "log.h"
26 #include "parameter.h"
27 
28 using namespace OHOS::Security::CodeSign;
29 
30 enum DeviceMode {
31     NOT_INITIALIZE = 0,
32     DEVICE_MODE_RD,
33     DEVICE_MODE_NOT_RD
34 };
35 
36 constexpr int32_t CMDLINE_MAX_BUF_LEN = 4096;
37 static const std::string PROC_CMDLINE_FILE_PATH = "/proc/cmdline";
38 static int32_t g_isRdDevice = NOT_INITIALIZE;
39 
CheckDeviceMode(char * buf,ssize_t bunLen)40 static bool CheckDeviceMode(char *buf, ssize_t bunLen)
41 {
42     if (strstr(buf, "oemmode=rd")) {
43         LOG_DEBUG(LABEL, "Oemode is rd");
44         return true;
45     } else {
46         LOG_DEBUG(LABEL, "Not rd mode, cmdline = %{private}s", buf);
47     }
48     return false;
49 }
50 
CheckEfuseStatus(char * buf,ssize_t bunLen)51 static int32_t CheckEfuseStatus(char *buf, ssize_t bunLen)
52 {
53     if (strstr(buf, "efuse_status=1")) {
54         LOG_DEBUG(LABEL, "device is not efused");
55         return true;
56     } else {
57         LOG_DEBUG(LABEL, "Not efused, cmdline = %{private}s", buf);
58     }
59     return false;
60 }
61 
ParseCMDLine()62 static void ParseCMDLine()
63 {
64     int32_t fd = open(PROC_CMDLINE_FILE_PATH.c_str(), O_RDONLY);
65     if (fd < 0) {
66         g_isRdDevice = DEVICE_MODE_NOT_RD;
67         LOG_ERROR(LABEL, "open %{public}s failed, %{public}s",
68             PROC_CMDLINE_FILE_PATH.c_str(), strerror(errno));
69         return;
70     }
71     char *buf = nullptr;
72     int32_t status = DEVICE_MODE_NOT_RD;
73     do {
74         buf = static_cast<char *>(malloc(CMDLINE_MAX_BUF_LEN));
75         if (buf == nullptr) {
76             LOG_ERROR(LABEL, "Alloc buffer for reading cmdline failed.");
77             break;
78         }
79         (void) memset_s(buf, CMDLINE_MAX_BUF_LEN, 0, CMDLINE_MAX_BUF_LEN);
80         ssize_t bufLen = read(fd, buf, CMDLINE_MAX_BUF_LEN - 1);
81         if (bufLen < 0) {
82             LOG_ERROR(LABEL, "Read %{public}s failed, %{public}s.",
83                 PROC_CMDLINE_FILE_PATH.c_str(), strerror(errno));
84             break;
85         }
86         if (CheckDeviceMode(buf, bufLen) || CheckEfuseStatus(buf, bufLen)) {
87             status = DEVICE_MODE_RD;
88         }
89     } while (0);
90     g_isRdDevice = status;
91     (void) close(fd);
92     free(buf);
93 }
94 
IsRdDevice()95 bool IsRdDevice()
96 {
97     if (g_isRdDevice == NOT_INITIALIZE) {
98         ParseCMDLine();
99     }
100     return g_isRdDevice == DEVICE_MODE_RD;
101 }