1 /*
2 * Copyright (c) 2023-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 <cstdio>
17 #include <cstring>
18 #include <fcntl.h>
19 #include <gtest/gtest.h>
20 #include <sys/ioctl.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include "code_sign_utils.h"
25 #include "code_sign_block.h"
26 #include "directory_ex.h"
27 #include "enable_key_utils.h"
28 #include "xpm_common.h"
29
30 namespace OHOS {
31 namespace Security {
32 namespace CodeSign {
33 using namespace testing::ext;
34 using namespace std;
35
36 static const std::string TMP_BASE_PATH = "/data/service/el1/public/bms/bundle_manager_service/tmp";
37 static const std::string TEST_APP_DTAT_DIR = "/data/app/el1/bundle/public/com.example.codesignaturetest";
38 static const std::string APP_BASE_PATH = "/data/app/el1/bundle/public/tmp";
39 static const string SUBJECT = "Huawei: HarmonyOS Application Code Signature";
40 static const string ISSUER = "Huawei CBG Software Signing Service CA Test";
41 static const string OH_SUBJECT = "OpenHarmony Application Release";
42 static const string OH_ISSUER = "OpenHarmony Application CA";
43 static const std::string PROFILE_BASE_PATH = "/data/service/el0/profiles/tmp";
44
45 static const EntryMap g_hapWithoutLibRetSuc = {
46 {"Hap", APP_BASE_PATH + "/demo_without_lib/demo_without_lib.hap"},
47 };
48 static const std::string g_sigWithoutLibRetSucPath =
49 TMP_BASE_PATH + "/demo_without_lib/demo_without_lib.sig";
50
51 static EntryMap g_hapWithMultiLibRetSuc = {
52 {"Hap",
53 APP_BASE_PATH + "/demo_with_multi_lib/demo_with_multi_lib.hap"},
54 {"libs/arm64-v8a/libc++_shared.so",
55 APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/libc++_shared.so"},
56 {"libs/arm64-v8a/libentry.so",
57 APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/libentry.so"}
58 };
59 static const std::string g_sigWithMultiLibRetSucPath =
60 TMP_BASE_PATH + "/demo_with_multi_lib/demo_with_multi_lib.sig";
61
62 // wrong hap and wrong lib
63 static EntryMap g_wrongHapWithMultiLibRetFail = {
64 {"Hap",
65 APP_BASE_PATH + "/demo_with_multi_lib_error/demo_with_multi_lib.hap"},
66 {"libs/arm64-v8a/libc++_shared.so",
67 APP_BASE_PATH + "/demo_with_multi_lib_error/libs/arm64-v8a/libc++_shared.so"},
68 {"libs/arm64-v8a/libentry.so",
69 APP_BASE_PATH + "/demo_with_multi_lib_error/libs/arm64-v8a/libentry.so"}};
70
71 // examples of Enforce code signature for app
72 static const std::vector<std::string> g_HapWithoutLibSigPkcs7ErrorPath = {
73 TMP_BASE_PATH + "/demo_without_lib/pkcs7_error/demo_without_lib_001.sig", // Ilegal pkcs7 format
74 TMP_BASE_PATH + "/demo_without_lib/pkcs7_error/demo_without_lib_002.sig", // Disable to find cert chain
75 TMP_BASE_PATH + "/demo_without_lib/pkcs7_error/demo_without_lib_003.sig", // Don't support digest algorithm
76 TMP_BASE_PATH + "/demo_without_lib/pkcs7_error/demo_without_lib_004.sig", // Don't support signature algorithm
77 TMP_BASE_PATH + "/demo_without_lib/pkcs7_error/demo_without_lib_005.sig", // Wrong signature
78 TMP_BASE_PATH + "/demo_without_lib/pkcs7_error/demo_without_lib_006.sig", // Expired signature
79 TMP_BASE_PATH + "/demo_without_lib/pkcs7_error/demo_without_lib_007.sig", // Cert chain validate fail
80 TMP_BASE_PATH + "/demo_without_lib/pkcs7_error/demo_without_lib_008.sig", // Wrong issuer
81 };
82
83 static const std::vector<std::string> g_HapWithMultiLibSigPkcs7ErrorPath = {
84 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/demo_with_multi_lib_001.sig", // Ilegal pkcs7 format
85 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/demo_with_multi_lib_002.sig", // Disable to find cert chain
86 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/demo_with_multi_lib_003.sig", // Don't support digest algorithm
87 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/demo_with_multi_lib_004.sig", // Don't support signature algorithm
88 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/demo_with_multi_lib_005.sig", // Wrong signature
89 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/demo_with_multi_lib_006.sig", // Expired signature
90 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/demo_with_multi_lib_007.sig", // Cert chain validate fail
91 };
92
93 // examples of Enforce code signature for file
94 static const std::string g_fileEnableSuc = APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/libentry.so";
95 static const std::string g_filesigEnablePath =
96 TMP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/libentry.so.fsv-sig";
97
98 // wrong format file
99 static const std::string g_wrongFileEnableFail =
100 APP_BASE_PATH + "/demo_with_multi_lib_error/libs/arm64-v8a/libentry.so";
101
102 static const std::vector<std::string> g_fileSigEnableFailPath = {
103 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/file/libentry_01.so.fsv-sig", // ilegal pkcs7 format
104 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/file/libentry_02.so.fsv-sig", // Disable to find cert chain
105 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/file/libentry_03.so.fsv-sig", // Don't support digest algorithm
106 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/file/libentry_04.so.fsv-sig", // Don't support signature algorithm
107 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/file/libentry_05.so.fsv-sig", // Wrong signature
108 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/file/libentry_06.so.fsv-sig", // Expired signature
109 TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/file/libentry_07.so.fsv-sig", // Cert chain validate fail
110 };
111
112 // examples of can't find the signature file
113 static const EntryMap g_hapSigNotExist = {
114 {"sigNotExist", APP_BASE_PATH + "/demo_without_lib/demo_without_lib.hap"},
115 };
116
117 static bool g_isPermissive = false;
118
119 class CodeSignUtilsTest : public testing::Test {
120 public:
CodeSignUtilsTest()121 CodeSignUtilsTest() {};
~CodeSignUtilsTest()122 virtual ~CodeSignUtilsTest() {};
SetUpTestCase()123 static void SetUpTestCase()
124 {
125 EXPECT_EQ(EnableTestKey(SUBJECT.c_str(), ISSUER.c_str()), 0);
126 EXPECT_EQ(EnableTestKey(OH_SUBJECT.c_str(), OH_ISSUER.c_str()), 0);
127 g_isPermissive = CodeSignUtils::InPermissiveMode();
128 if (g_isPermissive) {
129 SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, ENFORCE_MODE);
130 }
131 };
TearDownTestCase()132 static void TearDownTestCase()
133 {
134 if (g_isPermissive) {
135 SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, PERMISSIVE_MODE);
136 }
137 };
SetUp()138 void SetUp() {};
TearDown()139 void TearDown() {};
140 };
141
ReadSignatureFromFile(const std::string & path,ByteBuffer & data)142 static bool ReadSignatureFromFile(const std::string &path, ByteBuffer &data)
143 {
144 FILE *file = fopen(path.c_str(), "rb");
145 if (file == nullptr) {
146 return false;
147 }
148 if (fseek(file, 0L, SEEK_END) != 0) {
149 fclose(file);
150 return false;
151 }
152
153 size_t fileSize = ftell(file);
154 rewind(file);
155 if (!data.Resize(fileSize)) {
156 fclose(file);
157 return false;
158 }
159 size_t ret = fread(data.GetBuffer(), 1, fileSize, file);
160 (void)fclose(file);
161 return ret == fileSize;
162 }
163
164 // excute the exceptional examples first, because of it's always successful
165 // once the same file signature verified successfully
166
167 /**
168 * @tc.name: CodeSignUtilsTest_0001
169 * @tc.desc: enable code signature for app failed, reason = zip file wrong foramt
170 * @tc.type: Func
171 * @tc.require:
172 */
173 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0001, TestSize.Level0)
174 {
175 std::string sigPath = TMP_BASE_PATH + "/demo_with_multi_lib/pkcs7_error/file/libentry_01.so.fsv-sig";
176 int ret = CodeSignUtils::EnforceCodeSignForApp(g_hapWithoutLibRetSuc, sigPath);
177 EXPECT_EQ(ret, CS_ERR_EXTRACT_FILES);
178 }
179
180 /**
181 * @tc.name: CodeSignUtilsTest_0002
182 * @tc.desc: enable code signature for app failed, reason = no signature in the signatrue file
183 * @tc.type: Func
184 * @tc.require:
185 */
186 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0002, TestSize.Level0)
187 {
188 int ret = CodeSignUtils::EnforceCodeSignForApp(g_hapSigNotExist, g_sigWithoutLibRetSucPath);
189 EXPECT_EQ(ret, CS_ERR_NO_SIGNATURE);
190 }
191
192 /**
193 * @tc.name: CodeSignUtilsTest_0003
194 * @tc.desc: enable code signature for app failed, reason = invalied signature path
195 * @tc.type: Func
196 * @tc.require:
197 */
198 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0003, TestSize.Level0)
199 {
200 int ret = CodeSignUtils::EnforceCodeSignForApp(
201 g_hapWithoutLibRetSuc, g_sigWithoutLibRetSucPath + "invalid");
202 EXPECT_EQ(ret, CS_ERR_FILE_PATH);
203 }
204
205
206 /**
207 * @tc.name: CodeSignUtilsTest_0004
208 * @tc.desc: enable code signature for app failed, reason = invalied hap path
209 * @tc.type: Func
210 * @tc.require:
211 */
212 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0004, TestSize.Level0)
213 {
214 EntryMap invalid;
215 invalid["Hap"] = "InvalidPath";
216 int ret = CodeSignUtils::EnforceCodeSignForApp(invalid, g_sigWithoutLibRetSucPath);
217 EXPECT_EQ(ret, CS_ERR_FILE_INVALID);
218 }
219
220 /**
221 * @tc.name: CodeSignUtilsTest_0005
222 * @tc.desc: enable code signature for app failed, reason = wrong format hap
223 * @tc.type: Func
224 * @tc.require:
225 */
226 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0005, TestSize.Level0)
227 {
228 int ret = CodeSignUtils::EnforceCodeSignForApp(
229 g_wrongHapWithMultiLibRetFail, g_sigWithMultiLibRetSucPath);
230 EXPECT_EQ(ret, CS_ERR_ENABLE);
231 }
232
233 /**
234 * @tc.name: CodeSignUtilsTest_0006
235 * @tc.desc: enable code signature for app failed, reason = enable failed
236 * @tc.type: Func
237 * @tc.require:
238 */
239 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0006, TestSize.Level0)
240 {
241 size_t num = g_HapWithoutLibSigPkcs7ErrorPath.size();
242 int ret;
243 // wrong hap signature
244 for (size_t i = 0; i < num; i++) {
245 ret = CodeSignUtils::EnforceCodeSignForApp(g_hapWithoutLibRetSuc, g_HapWithoutLibSigPkcs7ErrorPath[i]);
246 EXPECT_EQ(ret, CS_ERR_ENABLE);
247 }
248
249 // wrong so signature
250 num = g_HapWithMultiLibSigPkcs7ErrorPath.size();
251 for (size_t i = 0; i < num; i++) {
252 ret = CodeSignUtils::EnforceCodeSignForApp(g_hapWithMultiLibRetSuc, g_HapWithMultiLibSigPkcs7ErrorPath[i]);
253 EXPECT_EQ(ret, CS_ERR_ENABLE);
254 }
255 }
256
257 /**
258 * @tc.name: CodeSignUtilsTest_0007
259 * @tc.desc: enable code signature for file, reason = wrong foramt pkcs7
260 * @tc.type: Func
261 * @tc.require:
262 */
263 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0007, TestSize.Level0)
264 {
265 ByteBuffer buffer;
266 bool flag = ReadSignatureFromFile(g_filesigEnablePath, buffer);
267 EXPECT_EQ(flag, true);
268 int ret = CodeSignUtils::EnforceCodeSignForFile(g_wrongFileEnableFail, buffer);
269 EXPECT_EQ(ret, CS_ERR_ENABLE);
270 }
271
272 /**
273 * @tc.name: CodeSignUtilsTest_0008
274 * @tc.desc: enable code signature for file, reason = enable failed
275 * @tc.type: Func
276 * @tc.require:
277 */
278 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0008, TestSize.Level0)
279 {
280 size_t num = g_fileSigEnableFailPath.size();
281 int ret;
282 for (size_t i = 0; i < num; i++) {
283 ByteBuffer buffer;
284 bool flag = ReadSignatureFromFile(g_fileSigEnableFailPath[i], buffer);
285 EXPECT_EQ(flag, true);
286 ret = CodeSignUtils::EnforceCodeSignForFile(g_fileEnableSuc, buffer);
287 EXPECT_EQ(ret, CS_ERR_ENABLE);
288 }
289 }
290
291 /**
292 * @tc.name: CodeSignUtilsTest_0009
293 * @tc.desc: enable code signature for file failed, reason = invalid path
294 * @tc.type: Func
295 * @tc.require:
296 */
297 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0009, TestSize.Level0)
298 {
299 ByteBuffer buffer;
300 bool flag = ReadSignatureFromFile(g_filesigEnablePath, buffer);
301 EXPECT_EQ(flag, true);
302 int ret = CodeSignUtils::EnforceCodeSignForFile("invalidPath", buffer);
303 EXPECT_EQ(ret, CS_ERR_FILE_PATH);
304 }
305
306 /**
307 * @tc.name: CodeSignUtilsTest_0010
308 * @tc.desc: enable code signature for file failed, reason = no signature
309 * @tc.type: Func
310 * @tc.require:
311 */
312 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0010, TestSize.Level0)
313 {
314 ByteBuffer buffer;
315 bool flag = ReadSignatureFromFile(g_filesigEnablePath, buffer);
316 EXPECT_EQ(flag, true);
317
318 int ret = CodeSignUtils::EnforceCodeSignForFile(g_fileEnableSuc, NULL, buffer.GetSize());
319 EXPECT_EQ(ret, CS_ERR_NO_SIGNATURE);
320
321 ret = CodeSignUtils::EnforceCodeSignForFile(g_fileEnableSuc, buffer.GetBuffer(), 0);
322 EXPECT_EQ(ret, CS_ERR_NO_SIGNATURE);
323 }
324
325 /**
326 * @tc.name: CodeSignUtilsTest_0011
327 * @tc.desc: enable code signature for file successfully
328 * @tc.type: Func
329 * @tc.require:
330 */
331 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0011, TestSize.Level0)
332 {
333 ByteBuffer buffer;
334 bool flag = ReadSignatureFromFile(g_filesigEnablePath, buffer);
335 EXPECT_EQ(flag, true);
336
337 int32_t ret = CodeSignUtils::EnforceCodeSignForFile(g_fileEnableSuc, buffer);
338 EXPECT_EQ(ret, CS_SUCCESS);
339 }
340
341 /**
342 * @tc.name: CodeSignUtilsTest_0012
343 * @tc.desc: enable code signature for app successfully
344 * @tc.type: Func
345 * @tc.require:
346 */
347 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0012, TestSize.Level0)
348 {
349 int32_t ret = CodeSignUtils::EnforceCodeSignForApp(g_hapWithoutLibRetSuc, g_sigWithoutLibRetSucPath);
350 EXPECT_EQ(ret, CS_SUCCESS);
351
352 ret = CodeSignUtils::EnforceCodeSignForApp(g_hapWithMultiLibRetSuc, g_sigWithMultiLibRetSucPath);
353 EXPECT_EQ(ret, CS_SUCCESS);
354 }
355
356 /**
357 * @tc.name: CodeSignUtilsTest_0013
358 * @tc.desc: parse owner ID from signature failed, reason = invalid signature
359 * @tc.type: Func
360 * @tc.require: issueI88PPA
361 */
362 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0013, TestSize.Level0)
363 {
364 ByteBuffer buffer;
365 std::string ownerID;
366 std::string invalid = "invalid msg";
367 buffer.CopyFrom((const uint8_t *)invalid.c_str(), invalid.length());
368 int ret = CodeSignUtils::ParseOwnerIdFromSignature(buffer, ownerID);
369 EXPECT_EQ(ret, CS_ERR_OPENSSL_PKCS7);
370 }
371
372 /**
373 * @tc.name: CodeSignUtilsTest_0014
374 * @tc.desc: Parse code signature for hap successfully
375 * @tc.type: Func
376 * @tc.require:
377 */
378 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0014, TestSize.Level0)
379 {
380 std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/demo_with_code_sign_block.hap";
381 EntryMap entryMap;
382
383 CodeSignBlock codeSignBlock;
384 int32_t ret = codeSignBlock.ParseCodeSignBlock(hapRealPath, entryMap, FILE_SELF);
385 EXPECT_EQ(ret, CS_SUCCESS);
386
387 std::string targetFile;
388 struct code_sign_enable_arg arg = {0};
389
390 ret = codeSignBlock.GetOneFileAndCodeSignInfo(targetFile, arg, 0);
391 EXPECT_EQ(ret, CS_SUCCESS);
392 EXPECT_EQ(arg.version, 1);
393 EXPECT_EQ(arg.cs_version, 1);
394 EXPECT_EQ(arg.hash_algorithm, 1);
395 EXPECT_EQ(arg.block_size, 0x1000);
396 EXPECT_EQ(arg.sig_size, 0x862);
397 EXPECT_EQ(arg.data_size, 0x5000);
398 EXPECT_EQ(arg.salt_size, 0);
399 EXPECT_EQ(arg.flags, 1);
400 EXPECT_EQ(arg.tree_offset, 0x10c000);
401
402 ret = codeSignBlock.GetOneFileAndCodeSignInfo(targetFile, arg, 0);
403 EXPECT_EQ(ret, CS_SUCCESS_END);
404 }
405
406 /**
407 * @tc.name: CodeSignUtilsTest_0015
408 * @tc.desc: parse code signature for native libs successfully
409 * @tc.type: Func
410 * @tc.require:
411 */
412 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0015, TestSize.Level0)
413 {
414 std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/demo_with_code_sign_block.hap";
415 EntryMap entryMap;
416 std::string filePath1("libs/arm64-v8a/libc++_shared.so");
417 std::string targetPath1 = TEST_APP_DTAT_DIR + "libs/arm64/libc++_shared.so";
418 entryMap.emplace(filePath1, targetPath1);
419 std::string filePath2("libs/arm64-v8a/libentry.so");
420 std::string targetPath2 = TEST_APP_DTAT_DIR + "libs/arm64/libentry.so";
421 entryMap.emplace(filePath2, targetPath2);
422
423 CodeSignBlock codeSignBlock;
424 int32_t ret = codeSignBlock.ParseCodeSignBlock(hapRealPath, entryMap, FILE_ENTRY_ONLY);
425 EXPECT_EQ(ret, CS_SUCCESS);
426
427 int32_t count = 0;
428 do {
429 std::string targetFile;
430 struct code_sign_enable_arg arg = {0};
431 ret = codeSignBlock.GetOneFileAndCodeSignInfo(targetFile, arg, 0);
432 if (ret != CS_SUCCESS_END) {
433 EXPECT_EQ(ret, CS_SUCCESS);
434 EXPECT_EQ(arg.version, 1);
435 EXPECT_EQ(arg.cs_version, 1);
436 EXPECT_EQ(arg.hash_algorithm, 1);
437 EXPECT_EQ(arg.block_size, 0x1000);
438 EXPECT_EQ(arg.salt_size, 0);
439 EXPECT_EQ(arg.flags, 0);
440 EXPECT_EQ(arg.tree_offset, 0);
441 count++;
442 continue;
443 }
444 } while (ret == CS_SUCCESS);
445 EXPECT_EQ(count, 0x2);
446 }
447
448 /**
449 * @tc.name: CodeSignUtilsTest_0016
450 * @tc.desc: enable code signature for app
451 * @tc.type: Func
452 * @tc.require:
453 */
454 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0016, TestSize.Level0)
455 {
456 std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/demo_with_code_sign_block.hap";
457 EntryMap entryMap;
458 CodeSignUtils utils;
459 int32_t ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_SELF);
460 EXPECT_EQ(ret, CS_SUCCESS);
461
462 std::string filePath1("libs/arm64-v8a/libc++_shared.so");
463 std::string targetPath1 = TEST_APP_DTAT_DIR + "libs/arm64/libc++_shared.so";
464 entryMap.emplace(filePath1, targetPath1);
465 std::string filePath2("libs/arm64-v8a/libentry.so");
466 std::string targetPath2 = TEST_APP_DTAT_DIR + "libs/arm64/libentry.so";
467 entryMap.emplace(filePath2, targetPath2);
468
469 ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ENTRY_ADD);
470 EXPECT_EQ(ret, CS_SUCCESS);
471
472 ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ALL);
473 EXPECT_EQ(ret, CS_ERR_FILE_PATH);
474 }
475
476 /**
477 * @tc.name: CodeSignUtilsTest_0017
478 * @tc.desc: enable code signature for debug app with libs
479 * @tc.type: Func
480 * @tc.require:
481 */
482 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0017, TestSize.Level0)
483 {
484 std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-debug.hap";
485 EntryMap entryMap;
486 CodeSignUtils utils;
487 int32_t ret = utils.EnforceCodeSignForAppWithOwnerId("DEBUG_LIB_ID",
488 hapRealPath, entryMap, FILE_SELF);
489 EXPECT_EQ(ret, CS_SUCCESS);
490 }
491
492 /**
493 * @tc.name: CodeSignUtilsTest_0018
494 * @tc.desc: enable code signature for release app with libs
495 * @tc.type: Func
496 * @tc.require:
497 */
498 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0018, TestSize.Level0)
499 {
500 std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-release.hap";
501 EntryMap entryMap;
502 CodeSignUtils utils;
503 int32_t ret = utils.EnforceCodeSignForAppWithOwnerId("test-app-identifier",
504 hapRealPath, entryMap, FILE_SELF);
505 EXPECT_EQ(ret, CS_SUCCESS);
506 }
507
508 /**
509 * @tc.name: CodeSignUtilsTest_0019
510 * @tc.desc: enable code signature for debug app with libs
511 * @tc.type: Func
512 * @tc.require:
513 */
514 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0019, TestSize.Level0)
515 {
516 std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-debug.hap";
517 EntryMap entryMap;
518 CodeSignUtils utils;
519 int32_t ret = utils.EnforceCodeSignForAppWithOwnerId("INVALID_ID",
520 hapRealPath, entryMap, FILE_SELF);
521 EXPECT_EQ(ret, CS_ERR_INVALID_OWNER_ID);
522 }
523
524 /**
525 * @tc.name: CodeSignUtilsTest_0020
526 * @tc.desc: enable code signature for release app with libs
527 * @tc.type: Func
528 * @tc.require:
529 */
530 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0020, TestSize.Level0)
531 {
532 std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-release.hap";
533 EntryMap entryMap;
534 CodeSignUtils utils;
535 int32_t ret = utils.EnforceCodeSignForAppWithOwnerId("INVALID_ID",
536 hapRealPath, entryMap, FILE_SELF);
537 EXPECT_EQ(ret, CS_ERR_INVALID_OWNER_ID);
538 }
539
540 /**
541 * @tc.name: CodeSignUtilsTest_0023
542 * @tc.desc: enable code signature for app
543 * @tc.type: Func
544 * @tc.require:
545 */
546 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0023, TestSize.Level0)
547 {
548 std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/demo_with_code_sign_block.hap";
549 EntryMap entryMap;
550
551 std::string filePath1("libs/arm64-v8a/libc++_shared.so");
552 std::string targetPath1 = APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/code_sign_block/libc++_shared.so";
553 entryMap.emplace(filePath1, targetPath1);
554
555 CodeSignUtils utils;
556 int32_t ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ENTRY_ONLY);
557 EXPECT_EQ(ret, CS_SUCCESS);
558
559 std::string filePath2("libs/arm64-v8a/libentry.so");
560 std::string targetPath2 = APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/code_sign_block/libentry.so";
561 entryMap.emplace(filePath2, targetPath2);
562
563 ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ENTRY_ADD);
564 EXPECT_EQ(ret, CS_SUCCESS);
565
566 entryMap.clear();
567 ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ALL);
568 EXPECT_EQ(ret, CS_SUCCESS);
569 }
570
571 /**
572 * @tc.name: CodeSignUtilsTest_0024
573 * @tc.desc: success without signature in permissive mode
574 * @tc.type: Func
575 * @tc.require: I8R8V7
576 */
577 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0024, TestSize.Level0)
578 {
579 if (!SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, PERMISSIVE_MODE)) {
580 return;
581 }
582 EntryMap entryMap;
583 CodeSignUtils utils;
584 std::string hapRealPath = APP_BASE_PATH + "/demo_without_lib/demo_without_lib.hap";
585 int32_t ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_SELF);
586 EXPECT_EQ(ret, CS_SUCCESS);
587 SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, ENFORCE_MODE);
588 }
589
590 /**
591 * @tc.name: CodeSignUtilsTest_0025
592 * @tc.desc: failed without signature in enforcing mode
593 * @tc.type: Func
594 * @tc.require: I8R8V7
595 */
596 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0025, TestSize.Level0)
597 {
598 if (CodeSignUtils::InPermissiveMode()) {
599 return;
600 }
601 std::string hapRealPath = APP_BASE_PATH + "/demo_without_lib/demo_without_lib.hap";
602 EntryMap entryMap;
603 CodeSignUtils utils;
604 int32_t ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_SELF);
605 EXPECT_EQ(ret, CS_CODE_SIGN_NOT_EXISTS);
606 }
607
608 /**
609 * @tc.name: CodeSignUtilsTest_0026
610 * @tc.desc: hap so mismatch scenarios
611 * @tc.type: Func
612 * @tc.require:
613 */
614 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0026, TestSize.Level0)
615 {
616 EntryMap entryMap;
617 CodeSignUtils utils;
618 std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-release.hap";
619
620 std::string filePath1("libs/arm64-v8a/code_sign_block/libc++_shared.so");
621 std::string targetPath1 = APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/code_sign_block/libc++_shared.so";
622 entryMap.emplace(filePath1, targetPath1);
623 std::string filePath2("libs/arm64-v8a/code_sign_block/libentry.so");
624 std::string targetPath2 = APP_BASE_PATH + "/demo_with_multi_lib/libs/arm64-v8a/code_sign_block/libentry.so";
625 entryMap.emplace(filePath2, targetPath2);
626
627 int32_t ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ENTRY_ADD);
628 EXPECT_EQ(ret, CS_SUCCESS);
629 entryMap.clear();
630
631 ret = utils.EnforceCodeSignForAppWithOwnerId("test-app-identifier", hapRealPath, entryMap, FILE_ALL);
632 EXPECT_EQ(ret, CS_ERR_NO_SIGNATURE);
633 }
634
635 /**
636 * @tc.name: CodeSignUtilsTest_0027
637 * @tc.desc: test Extension address is beyond the end of the block
638 * @tc.type: Func
639 * @tc.require:
640 */
641 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0027, TestSize.Level0)
642 {
643 CodeSignBlock codeSignBlock;
644 uintptr_t block[100] = {0};
645 uintptr_t blockAddrEnd = reinterpret_cast<uintptr_t>(block + sizeof(block));
646 uintptr_t extensionAddr = blockAddrEnd + 1;
647 code_sign_enable_arg arg = {};
648
649 int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg);
650 EXPECT_EQ(ret, CS_ERR_INVALID_EXTENSION_OFFSET);
651 }
652
653 /**
654 * @tc.name: CodeSignUtilsTest_0028
655 * @tc.desc: test Extension header size exceeds block boundary
656 * @tc.type: Func
657 * @tc.require:
658 */
659 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0028, TestSize.Level0)
660 {
661 CodeSignBlock codeSignBlock;
662 uintptr_t block[100] = {0};
663 uintptr_t blockAddrEnd = reinterpret_cast<uintptr_t>(block + sizeof(block));
664 uintptr_t extensionAddr = blockAddrEnd - sizeof(ExtensionHeader) + 1;
665 code_sign_enable_arg arg = {};
666
667 int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg);
668 EXPECT_EQ(ret, CS_ERR_INVALID_EXTENSION_OFFSET);
669 }
670
671 /**
672 * @tc.name: CodeSignUtilsTest_0029
673 * @tc.desc: test Process Merkle Tree Extension
674 * @tc.type: Func
675 * @tc.require:
676 */
677 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0029, TestSize.Level0)
678 {
679 CodeSignBlock codeSignBlock;
680 struct {
681 ExtensionHeader header;
682 MerkleTreeExtension merkleTree;
683 } block;
684 block.header.type = CodeSignBlock::CSB_EXTENSION_TYPE_MERKLE_TREE;
685 block.header.size = sizeof(MerkleTreeExtension);
686 block.merkleTree.treeOffset = 123;
687
688 uint8_t fakeRootHash[64] = {0xde, 0xad, 0xbe, 0xef};
689 std::copy(std::begin(fakeRootHash), std::end(fakeRootHash), std::begin(block.merkleTree.rootHash));
690
691 uintptr_t blockAddrEnd = reinterpret_cast<uintptr_t>(&block + 1);
692 uintptr_t extensionAddr = reinterpret_cast<uintptr_t>(&block);
693 code_sign_enable_arg arg = {};
694
695 int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg);
696 EXPECT_EQ(ret, CS_SUCCESS);
697 EXPECT_EQ(arg.tree_offset, 123);
698 EXPECT_EQ(arg.root_hash_ptr, reinterpret_cast<uintptr_t>(block.merkleTree.rootHash));
699 EXPECT_EQ(arg.flags, CodeSignBlock::CSB_SIGN_INFO_MERKLE_TREE);
700 }
701
702 /**
703 * @tc.name: CodeSignUtilsTest_0030
704 * @tc.desc: test Process Page Info Extension
705 * @tc.type: Func
706 * @tc.require:
707 */
708 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0030, TestSize.Level0)
709 {
710 CodeSignBlock codeSignBlock;
711 struct {
712 ExtensionHeader header;
713 PageInfoExtension pageInfo;
714 } block;
715 block.header.type = CodeSignBlock::CSB_EXTENSION_TYPE_PAGE_INFO;
716 block.header.size = sizeof(PageInfoExtension) + 50;
717 block.pageInfo.sign_size = 30;
718 block.pageInfo.unitSize = 2;
719
720 uint8_t fakeSignature[64] = {0xde, 0xad, 0xbe, 0xef};
721 std::copy(std::begin(fakeSignature), std::begin(fakeSignature)
722 + block.pageInfo.sign_size, block.pageInfo.signature);
723
724 block.pageInfo.mapSize = 100;
725 block.pageInfo.mapOffset = 200;
726
727 uintptr_t blockAddrEnd = reinterpret_cast<uintptr_t>(&block + 1);
728 uintptr_t extensionAddr = reinterpret_cast<uintptr_t>(&block);
729 code_sign_enable_arg arg = {};
730
731 int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg);
732 EXPECT_EQ(ret, CS_SUCCESS);
733 EXPECT_EQ(arg.sig_size, 30);
734 EXPECT_EQ(arg.sig_ptr, reinterpret_cast<uintptr_t>(block.pageInfo.signature));
735 EXPECT_EQ(arg.pgtypeinfo_size, 100);
736 EXPECT_EQ(arg.pgtypeinfo_off, 200);
737 EXPECT_EQ(arg.cs_version, CodeSignBlock::CSB_EXTENSION_TYPE_PAGE_INFO_VERSION);
738 EXPECT_EQ(arg.flags, 2 << 1);
739 }
740
741 /**
742 * @tc.name: CodeSignUtilsTest_0031
743 * @tc.desc: test Invalid Page Info Extension Sign Size
744 * @tc.type: Func
745 * @tc.require:
746 */
747 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0031, TestSize.Level0)
748 {
749 CodeSignBlock codeSignBlock;
750 struct {
751 ExtensionHeader header;
752 PageInfoExtension pageInfo;
753 } block;
754 block.header.type = CodeSignBlock::CSB_EXTENSION_TYPE_PAGE_INFO;
755 block.header.size = sizeof(PageInfoExtension);
756 block.pageInfo.sign_size = sizeof(PageInfoExtension) + 1;
757
758 uintptr_t blockAddrEnd = reinterpret_cast<uintptr_t>(&block + 1);
759 uintptr_t extensionAddr = reinterpret_cast<uintptr_t>(&block);
760 code_sign_enable_arg arg = {};
761
762 int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg);
763 EXPECT_EQ(ret, CS_ERR_EXTENSION_SIGN_SIZE);
764 }
765
766 /**
767 * @tc.name: CodeSignUtilsTest_0032
768 * @tc.desc: test invalid PageInfoExtension UnitSize
769 * @tc.type: Func
770 * @tc.require:
771 */
772 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0032, TestSize.Level0)
773 {
774 CodeSignBlock codeSignBlock;
775 struct {
776 ExtensionHeader header;
777 PageInfoExtension pageInfo;
778 } block;
779 block.header.type = CodeSignBlock::CSB_EXTENSION_TYPE_PAGE_INFO;
780 block.header.size = sizeof(PageInfoExtension);
781 block.pageInfo.unitSize = CodeSignBlock::CSB_SIGN_INFO_MAX_PAGEINFO_UNITSIZE + 1;
782
783 uintptr_t blockAddrEnd = reinterpret_cast<uintptr_t>(&block + 1);
784 uintptr_t extensionAddr = reinterpret_cast<uintptr_t>(&block);
785 code_sign_enable_arg arg = {};
786
787 int32_t ret = codeSignBlock.ProcessExtension(extensionAddr, blockAddrEnd, arg);
788 EXPECT_EQ(ret, CS_ERR_INVALID_PAGE_INFO_EXTENSION);
789 }
790
791 /**
792 * @tc.name: CodeSignUtilsTest_0033
793 * @tc.desc: enable code signature for app, entryPath is nullptr
794 * @tc.type: Func
795 * @tc.require:
796 */
797 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0033, TestSize.Level0)
798 {
799 EntryMap entryPath = {};
800 int32_t ret = CodeSignUtils::EnforceCodeSignForApp(entryPath, g_sigWithMultiLibRetSucPath);
801 EXPECT_EQ(ret, CS_SUCCESS);
802 }
803
804 /**
805 * @tc.name: CodeSignUtilsTest_0034
806 * @tc.desc: Enable key in profile content data and dump profile buffer
807 * @tc.type: Func
808 * @tc.require:
809 */
810 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0034, TestSize.Level0)
811 {
812 std::string bundleName = "";
813 const ByteBuffer profileBuffer;
814 int32_t ret = CodeSignUtils::EnableKeyInProfile(bundleName, profileBuffer);
815 #ifdef NO_USE_CLANG_COVERAGE
816 EXPECT_EQ(ret, CS_ERR_PROFILE);
817 #else
818 EXPECT_EQ(ret, CS_SUCCESS);
819 #endif
820 }
821
822 /**
823 * @tc.name: CodeSignUtilsTest_0035
824 * @tc.desc: Remove key in profile content data and remove profile
825 * @tc.type: Func
826 * @tc.require:
827 */
828 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0035, TestSize.Level0)
829 {
830 std::string bundleName = "";
831 int32_t ret = CodeSignUtils::RemoveKeyInProfile(bundleName);
832 #ifdef NO_USE_CLANG_COVERAGE
833 EXPECT_EQ(ret, CS_ERR_PROFILE);
834 #else
835 EXPECT_EQ(ret, CS_SUCCESS);
836 #endif
837 }
838
839 /**
840 * @tc.name: CodeSignUtilsTest_0036
841 * @tc.desc: enabling code signing for app compiled by oh-sdk
842 * @tc.type: Func
843 * @tc.require:
844 */
845 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0036, TestSize.Level0)
846 {
847 #ifdef SUPPORT_OH_CODE_SIGN
848 EXPECT_EQ(CodeSignUtils::IsSupportOHCodeSign(), true);
849 #else
850 EXPECT_EQ(CodeSignUtils::IsSupportOHCodeSign(), false);
851 #endif
852 }
853
854 /**
855 * @tc.name: CodeSignUtilsTest_0037
856 * @tc.desc: succ with signature in enforcing mode
857 * @tc.type: Func
858 * @tc.require: I8R8V7
859 */
860 HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0037, TestSize.Level0)
861 {
862 if (CodeSignUtils::InPermissiveMode()) {
863 return;
864 }
865 std::string hapRealPath = APP_BASE_PATH + "/demo_without_lib_signed/demo_without_lib_signed.hap";
866 EntryMap entryMap;
867 CodeSignUtils utils;
868 int32_t ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_SELF);
869 EXPECT_EQ(ret, CS_SUCCESS);
870 }
871 } // namespace CodeSign
872 } // namespace Security
873 } // namespace OHOS
874