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_rust.h"
26
27 using namespace OHOS::Security::CodeSign;
28
29 enum DeviceMode {
30 NOT_INITIALIZE = 0,
31 DEVICE_MODE_RD,
32 DEVICE_MODE_NOT_RD
33 };
34
35 constexpr int32_t CMDLINE_MAX_BUF_LEN = 4096;
36 #ifndef KEY_ENABLE_UTILS_TEST
37 static const std::string PROC_CMDLINE_FILE_PATH = "/proc/cmdline";
38 static int32_t g_isRdDevice = NOT_INITIALIZE;
39 #else
40 const std::string PROC_CMDLINE_FILE_PATH = "/data/test/tmp/cmdline";
41 int32_t g_isRdDevice = NOT_INITIALIZE;
42 #endif
43
CheckDeviceMode(char * buf,ssize_t bufLen)44 static bool CheckDeviceMode(char *buf, ssize_t bufLen)
45 {
46 bool status = false;
47 char *onStr = strstr(buf, "oemmode=rd");
48 char *offStr = strstr(buf, "oemmode=user");
49 char *statusStr = strstr(buf, "oemmode=");
50 if (onStr == nullptr && offStr == nullptr) {
51 LOG_INFO(LABEL, "Not rd mode, cmdline = %{private}s", buf);
52 } else if (offStr != nullptr && statusStr != nullptr && offStr != statusStr) {
53 LOG_ERROR(LABEL, "cmdline attacked, cmdline = %{private}s", buf);
54 } else if (onStr != nullptr && offStr == nullptr) {
55 status = true;
56 LOG_DEBUG(LABEL, "Oemode is rd");
57 }
58 return status;
59 }
60
CheckEfuseStatus(char * buf,ssize_t bufLen)61 static bool CheckEfuseStatus(char *buf, ssize_t bufLen)
62 {
63 bool status = false;
64 char *onStr = strstr(buf, "efuse_status=1");
65 char *offStr = strstr(buf, "efuse_status=0");
66 char *statusStr = strstr(buf, "efuse_status=");
67 if (onStr == nullptr && offStr == nullptr) {
68 LOG_INFO(LABEL, "device is efused, cmdline = %{private}s", buf);
69 } else if (offStr != nullptr && statusStr != nullptr && offStr != statusStr) {
70 LOG_ERROR(LABEL, "cmdline attacked, cmdline = %{private}s", buf);
71 } else if (onStr != nullptr && offStr == nullptr) {
72 status = true;
73 LOG_DEBUG(LABEL, "device is not efused");
74 }
75 return status;
76 }
77
ParseCMDLine()78 static void ParseCMDLine()
79 {
80 int32_t fd = open(PROC_CMDLINE_FILE_PATH.c_str(), O_RDONLY);
81 if (fd < 0) {
82 g_isRdDevice = DEVICE_MODE_NOT_RD;
83 LOG_ERROR(LABEL, "open %{public}s failed, %{public}s",
84 PROC_CMDLINE_FILE_PATH.c_str(), strerror(errno));
85 return;
86 }
87 char *buf = nullptr;
88 int32_t status = DEVICE_MODE_NOT_RD;
89 do {
90 buf = static_cast<char *>(malloc(CMDLINE_MAX_BUF_LEN));
91 if (buf == nullptr) {
92 LOG_ERROR(LABEL, "Alloc buffer for reading cmdline failed.");
93 break;
94 }
95 (void) memset_s(buf, CMDLINE_MAX_BUF_LEN, 0, CMDLINE_MAX_BUF_LEN);
96 ssize_t bufLen = read(fd, buf, CMDLINE_MAX_BUF_LEN - 1);
97 if (bufLen < 0) {
98 LOG_ERROR(LABEL, "Read %{public}s failed, %{public}s.",
99 PROC_CMDLINE_FILE_PATH.c_str(), strerror(errno));
100 break;
101 }
102 if (CheckDeviceMode(buf, bufLen) || CheckEfuseStatus(buf, bufLen)) {
103 status = DEVICE_MODE_RD;
104 }
105 } while (0);
106 g_isRdDevice = status;
107 (void) close(fd);
108 free(buf);
109 }
110
IsRdDevice()111 bool IsRdDevice()
112 {
113 if (g_isRdDevice == NOT_INITIALIZE) {
114 ParseCMDLine();
115 }
116 return g_isRdDevice == DEVICE_MODE_RD;
117 }