1 /*
2 * Copyright (c) 2022 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 "cm_test_common.h"
17
18 #include "cert_manager_api.h"
19
20 #include "cm_cert_data_ecc.h"
21 #include "cm_cert_data_ed25519.h"
22 #include "cm_cert_data_part1_rsa.h"
23 #include "cm_cert_data_part2_rsa.h"
24 #include "cm_mem.h"
25 #include "cm_test_log.h"
26
27 #include "accesstoken_kit.h"
28 #include "nativetoken_kit.h"
29 #include "token_setproc.h"
30 #include <unistd.h>
31 #include <unordered_map>
32 #include <thread>
33 #include <sstream>
34 #include <iostream>
35
36 namespace CertmanagerTest {
37 using namespace OHOS::Security::AccessToken;
38 namespace {
39
40 static const std::unordered_map<uint32_t, const uint8_t*> ALG_CODE_TO_CERT_DATA = {
41 { CERT_KEY_ALG_RSA, g_rsa2048P12CertInfo },
42 { CERT_KEY_ALG_ECC, g_eccP256P12CertInfo },
43 { CERT_KEY_ALG_RSA_512, g_rsa512P12CertInfo },
44 { CERT_KEY_ALG_RSA_1024, g_rsa1024P12CertInfo },
45 { CERT_KEY_ALG_RSA_3072, g_rsa3072P12CertInfo },
46 { CERT_KEY_ALG_RSA_4096, g_rsa4096P12CertInfo },
47 { CERT_KEY_ALG_ECC_P224, g_eccP224P12CertInfo },
48 { CERT_KEY_ALG_ECC_P384, g_eccP384P12CertInfo },
49 { CERT_KEY_ALG_ECC_P521, g_eccP521P12CertInfo },
50 { CERT_KEY_ALG_ED25519, g_ed25519P12CertInfo },
51 { CERT_KEY_ALG_SM2_1, g_sm2PfxCertInfo },
52 { CERT_KEY_ALG_SM2_2, g_sm2PfxCertInfo2 },
53 };
54
55 static const std::unordered_map<uint32_t, uint32_t> ALG_CODE_TO_CERT_SIZE = {
56 { CERT_KEY_ALG_RSA, sizeof(g_rsa2048P12CertInfo) },
57 { CERT_KEY_ALG_ECC, sizeof(g_eccP256P12CertInfo) },
58 { CERT_KEY_ALG_RSA_512, sizeof(g_rsa512P12CertInfo) },
59 { CERT_KEY_ALG_RSA_1024, sizeof(g_rsa1024P12CertInfo) },
60 { CERT_KEY_ALG_RSA_3072, sizeof(g_rsa3072P12CertInfo) },
61 { CERT_KEY_ALG_RSA_4096, sizeof(g_rsa4096P12CertInfo) },
62 { CERT_KEY_ALG_ECC_P224, sizeof(g_eccP224P12CertInfo) },
63 { CERT_KEY_ALG_ECC_P384, sizeof(g_eccP384P12CertInfo) },
64 { CERT_KEY_ALG_ECC_P521, sizeof(g_eccP521P12CertInfo) },
65 { CERT_KEY_ALG_ED25519, sizeof(g_ed25519P12CertInfo) },
66 { CERT_KEY_ALG_SM2_1, sizeof(g_sm2PfxCertInfo) },
67 { CERT_KEY_ALG_SM2_2, sizeof(g_sm2PfxCertInfo2) },
68 };
69
70 std::mutex g_lockSetToken;
71 uint64_t g_shellTokenId = 0;
72 const std::string BUNDLE_NAME = "test.bundlename";
73 const bool IS_SYSTEM_APP = true;
74 const std::vector<std::string> PERMISSION_LIST = {
75 "ohos.permission.ACCESS_CERT_MANAGER_INTERNAL",
76 "ohos.permission.ACCESS_CERT_MANAGER",
77 "ohos.permission.ACCESS_USER_TRUSTED_CERT",
78 "ohos.permission.ACCESS_SYSTEM_APP_CERT"
79 };
80 }
81
MockNativeToken(const std::string & process)82 MockNativeToken::MockNativeToken(const std::string& process)
83 {
84 selfToken_ = GetSelfTokenID();
85 uint32_t tokenId = CmTestCommon::GetNativeTokenIdFromProcess(process);
86 SetSelfTokenID(tokenId);
87 }
88
~MockNativeToken()89 MockNativeToken::~MockNativeToken()
90 {
91 SetSelfTokenID(selfToken_);
92 }
93
MockHapToken()94 MockHapToken::MockHapToken()
95 {
96 selfToken_ = GetSelfTokenID();
97 AccessTokenIDEx tokenIdEx = CmTestCommon::SetupHapAndAllocateToken();
98 mockToken_ = tokenIdEx.tokenIdExStruct.tokenID;
99 SetSelfTokenID(tokenIdEx.tokenIDEx);
100 }
101
~MockHapToken()102 MockHapToken::~MockHapToken()
103 {
104 if (mockToken_ != INVALID_TOKENID) {
105 CmTestCommon::DeleteTestHapToken(mockToken_);
106 }
107 SetSelfTokenID(selfToken_);
108 }
109
SetTestEnvironment(uint64_t shellTokenId)110 void CmTestCommon::SetTestEnvironment(uint64_t shellTokenId)
111 {
112 std::lock_guard<std::mutex> lock(g_lockSetToken);
113 g_shellTokenId = shellTokenId;
114 }
115
ResetTestEnvironment()116 void CmTestCommon::ResetTestEnvironment()
117 {
118 std::lock_guard<std::mutex> lock(g_lockSetToken);
119 g_shellTokenId = 0;
120 }
121
GetShellTokenId()122 uint64_t CmTestCommon::GetShellTokenId()
123 {
124 std::lock_guard<std::mutex> lock(g_lockSetToken);
125 return g_shellTokenId;
126 }
127
SetHapInfoAndPolicy(const std::string & bundle,const std::vector<std::string> & reqPerm,bool isSystemApp,HapInfoParams & hapInfo,HapPolicyParams & hapPolicy)128 void CmTestCommon::SetHapInfoAndPolicy(const std::string& bundle, const std::vector<std::string>& reqPerm,
129 bool isSystemApp, HapInfoParams& hapInfo, HapPolicyParams& hapPolicy)
130 {
131 hapInfo = {
132 .userID = 0,
133 .bundleName = bundle,
134 .instIndex = 0,
135 .appIDDesc = "CmTestAppID",
136 .apiVersion = CmTestCommon::DEFAULT_API_VERSION,
137 .isSystemApp = isSystemApp,
138 .appDistributionType = "",
139 };
140
141 hapPolicy = {
142 .apl = APL_NORMAL,
143 .domain = "test.domain",
144 };
145 for (size_t i = 0; i < reqPerm.size(); ++i) {
146 PermissionDef permDefResult;
147 if (AccessTokenKit::GetDefPermission(reqPerm[i], permDefResult) != RET_SUCCESS) {
148 continue;
149 }
150 PermissionStateFull permState = {
151 .permissionName = reqPerm[i],
152 .isGeneral = true,
153 .resDeviceID = {"local3"},
154 .grantStatus = {PermissionState::PERMISSION_DENIED},
155 .grantFlags = {PermissionFlag::PERMISSION_DEFAULT_FLAG}
156 };
157 hapPolicy.permStateList.emplace_back(permState);
158 if (permDefResult.availableLevel > hapPolicy.apl) {
159 hapPolicy.aclRequestedList.emplace_back(reqPerm[i]);
160 }
161 }
162 }
163
AllocTestHapToken(const HapInfoParams & hapInfo,HapPolicyParams & hapPolicy)164 AccessTokenIDEx CmTestCommon::AllocTestHapToken(
165 const HapInfoParams& hapInfo, HapPolicyParams& hapPolicy)
166 {
167 AccessTokenIDEx tokenIdEx = {0};
168 uint64_t selfTokenId = GetSelfTokenID();
169 for (auto& permissionStateFull : hapPolicy.permStateList) {
170 PermissionDef permDefResult;
171 if (AccessTokenKit::GetDefPermission(permissionStateFull.permissionName, permDefResult) != RET_SUCCESS) {
172 continue;
173 }
174 if (permDefResult.availableLevel > hapPolicy.apl) {
175 hapPolicy.aclRequestedList.emplace_back(permissionStateFull.permissionName);
176 }
177 }
178 if (CmTestCommon::GetNativeTokenIdFromProcess("foundation") == selfTokenId) {
179 AccessTokenKit::InitHapToken(hapInfo, hapPolicy, tokenIdEx);
180 } else {
181 // set sh token for self
182 MockNativeToken mock("foundation");
183 AccessTokenKit::InitHapToken(hapInfo, hapPolicy, tokenIdEx);
184
185 // restore
186 SetSelfTokenID(selfTokenId);
187 }
188 return tokenIdEx;
189 }
190
SetupHapAndAllocateToken()191 AccessTokenIDEx CmTestCommon::SetupHapAndAllocateToken()
192 {
193 HapInfoParams hapInfo;
194 HapPolicyParams hapPolicy;
195 CmTestCommon::SetHapInfoAndPolicy(BUNDLE_NAME, PERMISSION_LIST, IS_SYSTEM_APP,
196 hapInfo, hapPolicy);
197 AccessTokenIDEx tokenIdEx = CmTestCommon::AllocTestHapToken(hapInfo, hapPolicy);
198 return tokenIdEx;
199 }
200
DeleteTestHapToken(AccessTokenID tokenID)201 int32_t CmTestCommon::DeleteTestHapToken(AccessTokenID tokenID)
202 {
203 uint64_t selfTokenId = GetSelfTokenID();
204 if (CmTestCommon::GetNativeTokenIdFromProcess("foundation") == selfTokenId) {
205 return AccessTokenKit::DeleteToken(tokenID);
206 }
207
208 // set sh token for self
209 MockNativeToken mock("foundation");
210
211 int32_t ret = AccessTokenKit::DeleteToken(tokenID);
212 // restore
213 SetSelfTokenID(selfTokenId);
214 return ret;
215 }
216
GetNativeTokenIdFromProcess(const std::string & process)217 AccessTokenID CmTestCommon::GetNativeTokenIdFromProcess(const std::string &process)
218 {
219 uint64_t selfTokenId = GetSelfTokenID();
220 SetSelfTokenID(CmTestCommon::GetShellTokenId()); // set shell token
221
222 std::string dumpInfo;
223 AtmToolsParamInfo info;
224 info.processName = process;
225 AccessTokenKit::DumpTokenInfo(info, dumpInfo);
226 size_t pos = dumpInfo.find("\"tokenID\": ");
227 if (pos == std::string::npos) {
228 return 0;
229 }
230 pos += std::string("\"tokenID\": ").length();
231 std::string numStr;
232 while (pos < dumpInfo.length() && std::isdigit(dumpInfo[pos])) {
233 numStr += dumpInfo[pos];
234 ++pos;
235 }
236 // restore
237 SetSelfTokenID(selfTokenId);
238
239 std::istringstream iss(numStr);
240 AccessTokenID tokenID;
241 iss >> tokenID;
242 return tokenID;
243 }
244
InitCertInfo(struct CertInfo * certInfo)245 int32_t InitCertInfo(struct CertInfo *certInfo)
246 {
247 if (certInfo == nullptr) {
248 return CMR_ERROR_MALLOC_FAIL;
249 }
250
251 certInfo->certInfo.data = static_cast<uint8_t *>(CmMalloc(MAX_LEN_CERTIFICATE));
252 if (certInfo->certInfo.data == NULL) {
253 return CMR_ERROR_MALLOC_FAIL;
254 }
255 certInfo->certInfo.size = MAX_LEN_CERTIFICATE;
256
257 return CM_SUCCESS;
258 }
259
InitCertList(struct CertList ** cList)260 int32_t InitCertList(struct CertList **cList)
261 {
262 *cList = static_cast<struct CertList *>(CmMalloc(sizeof(struct CertList)));
263 if (*cList == nullptr) {
264 return CMR_ERROR_MALLOC_FAIL;
265 }
266
267 uint32_t buffSize = MAX_COUNT_CERTIFICATE_ALL * sizeof(struct CertAbstract);
268 (*cList)->certAbstract = static_cast<struct CertAbstract *>(CmMalloc(buffSize));
269 if ((*cList)->certAbstract == NULL) {
270 return CMR_ERROR_MALLOC_FAIL;
271 }
272 (void)memset_s((*cList)->certAbstract, buffSize, 0, buffSize);
273 (*cList)->certsCount = MAX_COUNT_CERTIFICATE_ALL;
274
275 return CM_SUCCESS;
276 }
277
InitUserCertInfo(struct CertInfo ** cInfo)278 int32_t InitUserCertInfo(struct CertInfo **cInfo)
279 {
280 *cInfo = static_cast<struct CertInfo *>(CmMalloc(sizeof(struct CertInfo)));
281 if (*cInfo == nullptr) {
282 return CMR_ERROR_MALLOC_FAIL;
283 }
284 (void)memset_s(*cInfo, sizeof(struct CertInfo), 0, sizeof(struct CertInfo));
285
286 (*cInfo)->certInfo.data = static_cast<uint8_t *>(CmMalloc(MAX_LEN_CERTIFICATE));
287 if ((*cInfo)->certInfo.data == NULL) {
288 return CMR_ERROR_MALLOC_FAIL;
289 }
290 (*cInfo)->certInfo.size = MAX_LEN_CERTIFICATE;
291
292 return CM_SUCCESS;
293 }
294
FreeCertList(struct CertList * certList)295 void FreeCertList(struct CertList *certList)
296 {
297 if (certList == nullptr || certList->certAbstract == nullptr) {
298 return;
299 }
300
301 CmFree(certList->certAbstract);
302 certList->certAbstract = nullptr;
303
304 CmFree(certList);
305 }
306
307
FreeCMBlobData(struct CmBlob * blob)308 void FreeCMBlobData(struct CmBlob *blob)
309 {
310 if (blob == nullptr) {
311 return;
312 }
313
314 if (blob->data != nullptr) {
315 CmFree(blob->data);
316 blob->data = nullptr;
317 }
318 blob->size = 0;
319 }
320
FreeCertInfo(struct CertInfo * cInfo)321 void FreeCertInfo(struct CertInfo *cInfo)
322 {
323 if (cInfo == nullptr || (cInfo->certInfo).data == nullptr) {
324 return;
325 }
326
327 FreeCMBlobData(&(cInfo->certInfo));
328 CmFree(cInfo);
329 }
330
CompareCert(const struct CertAbstract * firstCert,const struct CertAbstract * secondCert)331 static bool CompareCert(const struct CertAbstract *firstCert, const struct CertAbstract *secondCert)
332 {
333 if (firstCert == nullptr || secondCert == nullptr) {
334 CM_TEST_LOG_E("cert invalid parameter");
335 return false;
336 }
337 return ((strcmp(firstCert->uri, secondCert->uri) == 0) &&
338 (strcmp(firstCert->certAlias, secondCert->certAlias) == 0) &&
339 (strcmp(firstCert->subjectName, secondCert->subjectName) == 0) &&
340 (firstCert->status == secondCert->status));
341 }
342
CompareCredentialList(const struct CredentialAbstract * firstCert,const struct CredentialAbstract * secondCert)343 bool CompareCredentialList(const struct CredentialAbstract *firstCert, const struct CredentialAbstract *secondCert)
344 {
345 if (firstCert == nullptr || secondCert == nullptr) {
346 CM_TEST_LOG_E("cert invalid parameter");
347 return false;
348 }
349 return ((strcmp(firstCert->type, secondCert->type) == 0) &&
350 (strcmp(firstCert->alias, secondCert->alias) == 0) &&
351 (strcmp(firstCert->keyUri, secondCert->keyUri) == 0));
352 }
353
DumpCertAbstractInfo(const struct CertAbstract * certAbstract)354 std::string DumpCertAbstractInfo(const struct CertAbstract *certAbstract)
355 {
356 if (certAbstract == nullptr) {
357 return " ";
358 }
359 std::string str = "";
360 str += ENDOF;
361 str += certAbstract->uri;
362 str += DELIMITER;
363 str += certAbstract->certAlias;
364 str += DELIMITER;
365 str += certAbstract->subjectName;
366 str += DELIMITER;
367 str += (certAbstract->status) ? "true" : "false";
368 str += ENDOF;
369 return str;
370 }
371
DumpCertList(struct CertList * certList)372 std::string DumpCertList(struct CertList *certList)
373 {
374 if (certList == nullptr) {
375 return " ";
376 }
377
378 std::string str = "";
379 if (certList->certsCount > 0 && certList->certAbstract != nullptr) {
380 for (uint32_t i = 0; i < certList->certsCount; i++) {
381 str += DumpCertAbstractInfo(&(certList->certAbstract[i]));
382 }
383 }
384 return str;
385 }
386
CompareCertInfo(const struct CertInfo * firstCert,const struct CertInfo * secondCert)387 bool CompareCertInfo(const struct CertInfo *firstCert, const struct CertInfo *secondCert)
388 {
389 if (firstCert == nullptr || secondCert == nullptr) {
390 return false;
391 }
392 return ((strcmp(firstCert->uri, secondCert->uri) == 0) &&
393 (strcmp(firstCert->certAlias, secondCert->certAlias) == 0) &&
394 (firstCert->status == secondCert->status) &&
395 (strcmp(firstCert->issuerName, secondCert->issuerName) == 0) &&
396 (strcmp(firstCert->subjectName, secondCert->subjectName) == 0) &&
397 (strcmp(firstCert->serial, secondCert->serial) == 0) &&
398 (strcmp(firstCert->notBefore, secondCert->notBefore) == 0) &&
399 (strcmp(firstCert->notAfter, secondCert->notAfter) == 0) &&
400 (strcmp(firstCert->fingerprintSha256, secondCert->fingerprintSha256) == 0));
401 }
402
CompareCertData(const struct CmBlob * firstData,const struct CmBlob * secondData)403 bool CompareCertData(const struct CmBlob *firstData, const struct CmBlob *secondData)
404 {
405 if (firstData == nullptr || secondData == nullptr) {
406 return false;
407 }
408 return ((firstData->size == secondData->size) &&
409 (memcmp(firstData->data, secondData->data, static_cast<int32_t>(firstData->size)) == 0));
410 }
411
DumpCertInfo(const struct CertInfo * certInfo)412 std::string DumpCertInfo(const struct CertInfo *certInfo)
413 {
414 if (certInfo == nullptr) {
415 return " ";
416 }
417 std::string str = "";
418 str += ENDOF;
419 str += certInfo->uri;
420 str += DELIMITER;
421 str += certInfo->certAlias;
422 str += DELIMITER;
423 str += certInfo->subjectName;
424 str += DELIMITER;
425 str += (certInfo->status) ? "true" : "false";
426 str += ENDOF;
427 return str;
428 }
429
CompareCredential(const struct Credential * firstCredential,const struct Credential * secondCredential)430 bool CompareCredential(const struct Credential *firstCredential, const struct Credential *secondCredential)
431 {
432 if (firstCredential == nullptr || secondCredential == nullptr) {
433 return false;
434 }
435 return ((strcmp(firstCredential->type, secondCredential->type) == 0) &&
436 (strcmp(firstCredential->alias, secondCredential->alias) == 0) &&
437 (strcmp(firstCredential->keyUri, secondCredential->keyUri) == 0) &&
438 (firstCredential->certNum == secondCredential->certNum) &&
439 (firstCredential->keyNum == secondCredential->keyNum) &&
440 (firstCredential->credData.size == secondCredential->credData.size));
441 }
442
ConstructAppCertData(uint32_t alg,struct CmBlob * appCert)443 static int32_t ConstructAppCertData(uint32_t alg, struct CmBlob *appCert)
444 {
445 auto iterSize = ALG_CODE_TO_CERT_SIZE.find(alg);
446 if (iterSize == ALG_CODE_TO_CERT_SIZE.end()) {
447 return CMR_ERROR_INVALID_ARGUMENT;
448 }
449 appCert->size = iterSize->second;
450
451 auto iterData = ALG_CODE_TO_CERT_DATA.find(alg);
452 if (iterData == ALG_CODE_TO_CERT_DATA.end()) {
453 return CMR_ERROR_INVALID_ARGUMENT;
454 }
455 appCert->data = const_cast<uint8_t *>(iterData->second);
456 return CM_SUCCESS;
457 }
458
TestGenerateAppCert(const struct CmBlob * alias,uint32_t alg,uint32_t store)459 int32_t TestGenerateAppCert(const struct CmBlob *alias, uint32_t alg, uint32_t store)
460 {
461 struct CmBlob appCert = { 0, NULL };
462 int32_t ret = ConstructAppCertData(alg, &appCert);
463 if (ret != CM_SUCCESS) {
464 return ret;
465 }
466
467 struct CmBlob appCertPwd = { sizeof(g_certPwd), const_cast<uint8_t *>(g_certPwd) };
468 if (alg == CERT_KEY_ALG_SM2_1 || alg == CERT_KEY_ALG_SM2_2) {
469 appCertPwd.size = sizeof(g_sm2certPwd);
470 appCertPwd.data = const_cast<uint8_t *>(g_sm2certPwd);
471 }
472 uint8_t uriData[MAX_LEN_URI] = {0};
473 struct CmBlob keyUri = { sizeof(uriData), uriData };
474
475 if (store == CM_SYS_CREDENTIAL_STORE) {
476 struct CmAppCertParam appCertParam = { &appCert, &appCertPwd,
477 (struct CmBlob *)alias, CM_SYS_CREDENTIAL_STORE, TEST_USERID };
478 return CmInstallSystemAppCert(&appCertParam, &keyUri);
479 }
480 return CmInstallAppCert(&appCert, &appCertPwd, alias, store, &keyUri);
481 }
482
FindCertAbstract(const struct CertAbstract * abstract,const struct CertList * cList)483 bool FindCertAbstract(const struct CertAbstract *abstract, const struct CertList *cList)
484 {
485 if (abstract == nullptr || cList == nullptr || cList->certsCount == 0) {
486 return false;
487 }
488 for (uint32_t i = 0; i < cList->certsCount; ++i) {
489 if (CompareCert(abstract, &(cList->certAbstract[i]))) {
490 return true;
491 }
492 }
493 return false;
494 }
495 }
496