1 /*
2 * Copyright (c) 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
16 #include "local_code_sign_utils.h"
17
18 #include <unistd.h>
19
20 #include "byte_buffer.h"
21 #include "local_code_sign_kit.h"
22 #include "log.h"
23 #include "securec.h"
24 #include "thread_ex.h"
25
26 using namespace OHOS::Security::CodeSign;
27
28 namespace OHOS {
29 namespace Security {
30 namespace CodeSign {
31 constexpr uint32_t INIT_LOCAL_CERT_TIMEOUT_MS = 300 * 1000;
32 constexpr uint32_t INIT_LOCAL_CERT_SLEEP_US = 1000 * 1000;
33 const std::string INIT_LOCAL_CERT_THREAD_NAME = "init_local_cert";
34
35 static std::condition_variable g_condition;
36
37 class InitLocalCertThread : public OHOS::Thread {
38 public:
InitLocalCertThread()39 InitLocalCertThread() {}
~InitLocalCertThread()40 ~InitLocalCertThread() {}
41
GetRet()42 int GetRet()
43 {
44 return initResult_;
45 }
46
GetCert()47 ByteBuffer& GetCert()
48 {
49 return cert_;
50 }
51
52 protected:
Run()53 bool Run()
54 {
55 initResult_ = LocalCodeSignKit::InitLocalCertificate(cert_);
56 if (initResult_ == CS_ERR_SA_GET_PROXY) {
57 usleep(INIT_LOCAL_CERT_SLEEP_US);
58 return true;
59 } else {
60 g_condition.notify_one();
61 return false;
62 }
63 }
64
65 private:
66 int32_t initResult_ = -1;
67 ByteBuffer cert_;
68 };
69 }
70 }
71 }
72
InitLocalCertificate(uint8_t * certData,uint32_t * certSize)73 int32_t InitLocalCertificate(uint8_t *certData, uint32_t *certSize)
74 {
75 std::unique_ptr<InitLocalCertThread> thread = std::make_unique<InitLocalCertThread>();
76 OHOS::ThreadStatus status = thread->Start(INIT_LOCAL_CERT_THREAD_NAME);
77 if (status != OHOS::ThreadStatus::OK) {
78 LOG_ERROR(LABEL, "initing local cert thread not start.");
79 return CS_ERR_INIT_LOCAL_CERT;
80 }
81
82 std::mutex mtx;
83 std::unique_lock<std::mutex> lock(mtx);
84 g_condition.wait_for(lock, std::chrono::milliseconds(INIT_LOCAL_CERT_TIMEOUT_MS));
85 thread->NotifyExitSync();
86
87 int ret = thread->GetRet();
88 if (ret != CS_SUCCESS) {
89 LOG_ERROR(LABEL, "init local cert timeout or error, ret = %{public}d", ret);
90 return ret;
91 }
92
93 ByteBuffer &cert = thread->GetCert();
94 if (memcpy_s(certData, *certSize, cert.GetBuffer(), cert.GetSize()) != EOK) {
95 return CS_ERR_MEMORY;
96 }
97 *certSize = cert.GetSize();
98 return ret;
99 }