1 /*
2 * Copyright (c) 2023-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 #ifdef HKS_CONFIG_FILE
17 #include HKS_CONFIG_FILE
18 #else
19 #include "hks_config.h"
20 #endif
21
22 #include "hks_sa_interface.h"
23
24 #include <errors.h>
25 #include <ipc_types.h>
26 #include <memory>
27 #include <mutex>
28 #include <securec.h>
29
30 #include "hks_dcm_callback_handler.h"
31 #include "hks_log.h"
32 #include "huks_service_ipc_interface_code.h"
33
34 namespace OHOS {
35 namespace Security {
36 namespace Hks {
37
SendAsyncReply(uint32_t errCode,std::unique_ptr<uint8_t[]> & certChain,uint32_t sz)38 void HksStub::SendAsyncReply(uint32_t errCode, std::unique_ptr<uint8_t[]> &certChain, uint32_t sz)
39 {
40 std::unique_lock<std::mutex> lck(mMutex);
41 mErrCode = errCode;
42 mAsyncReply = std::move(certChain);
43 mSize = sz;
44 mCv.notify_all();
45 }
46
ProcessAttestKeyAsyncReply(MessageParcel & data)47 int HksStub::ProcessAttestKeyAsyncReply(MessageParcel& data)
48 {
49 std::unique_ptr<uint8_t[]> certChain{};
50 uint32_t errCode = data.ReadUint32();
51 if (errCode != DCM_SUCCESS) {
52 HKS_LOG_E("ipc client read errCode %" LOG_PUBLIC "u", errCode);
53 SendAsyncReply(errCode, certChain, 0);
54 return ERR_INVALID_DATA;
55 }
56 uint32_t certChainLen = 0;
57 int err = ERR_INVALID_DATA;
58 do {
59 uint32_t sz = data.ReadUint32();
60 if (sz == 0 || sz > MAX_OUT_BLOB_SIZE) {
61 HKS_LOG_E("invalid sz %" LOG_PUBLIC "u", sz);
62 break;
63 }
64 const uint8_t *ptr = data.ReadBuffer(sz);
65 if (ptr == nullptr) {
66 HKS_LOG_E("ReadBuffer %" LOG_PUBLIC "u size ptr is nullptr", sz);
67 break;
68 }
69 std::unique_ptr<uint8_t[]> receivedPtr(new (std::nothrow) uint8_t[sz]());
70 if (receivedPtr == nullptr) {
71 HKS_LOG_E("new receivedPtr failed");
72 err = ERR_NO_MEMORY;
73 break;
74 }
75 errno_t err = memcpy_s(receivedPtr.get(), sz, ptr, sz);
76 if (err != EOK) {
77 HKS_LOG_E("memcpy_s receivedPtr failed");
78 break;
79 }
80 err = ERR_OK;
81 certChain = std::move(receivedPtr);
82 certChainLen = sz;
83 } while (false);
84 SendAsyncReply(errCode, certChain, certChainLen);
85 return err;
86 }
87
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)88 int HksStub::OnRemoteRequest(uint32_t code,
89 MessageParcel& data, MessageParcel& reply, MessageOption& option)
90 {
91 if (data.ReadInterfaceToken() != GetDescriptor()) {
92 HKS_LOG_E("failed to check interface token! code %" LOG_PUBLIC "d", code);
93 return ERR_INVALID_DATA;
94 }
95 int result = ERR_NONE;
96
97 switch (code) {
98 case HKS_MSG_ATTEST_KEY_ASYNC_REPLY:
99 result = ProcessAttestKeyAsyncReply(data);
100 break;
101 default:
102 HKS_LOG_E("unknown remote request code %" LOG_PUBLIC "u", code);
103 result = ERR_TRANSACTION_FAILED;
104 break;
105 }
106
107 return result;
108 }
109
WaitForAsyncReply(int timeout)110 std::tuple<uint32_t, std::unique_ptr<uint8_t[]>, uint32_t> HksStub::WaitForAsyncReply(int timeout)
111 {
112 std::unique_lock<std::mutex> lck(mMutex);
113 mAsyncReply = nullptr;
114 mSize = 0;
115 mErrCode = DCM_SUCCESS;
116 HKS_LOG_I("begin wait for async reply");
117 mCv.wait_for(lck, std::chrono::seconds(timeout));
118 return {mErrCode, std::move(mAsyncReply), mSize};
119 }
120
121 BrokerDelegator<HksProxy> HksProxy::delegator_;
HksProxy(const sptr<IRemoteObject> & impl)122 HksProxy::HksProxy(const sptr<IRemoteObject> &impl)
123 : IRemoteProxy<IHksService>(impl)
124 {
125 }
126
SendAsyncReply(uint32_t errCode,std::unique_ptr<uint8_t[]> & certChain,uint32_t sz)127 void HksProxy::SendAsyncReply(uint32_t errCode, std::unique_ptr<uint8_t[]> &certChain, uint32_t sz)
128 {
129 if (Remote() == nullptr) {
130 HKS_LOG_E("Remote() is nullptr! Would not SendRequest!");
131 return;
132 }
133 MessageParcel data, reply;
134 MessageOption option = MessageOption::TF_ASYNC;
135 bool writeResult = data.WriteInterfaceToken(GetDescriptor());
136 if (!writeResult) {
137 HKS_LOG_E("WriteInterfaceToken errCode %" LOG_PUBLIC "u failed %" LOG_PUBLIC "d", errCode, writeResult);
138 return;
139 }
140 writeResult = data.WriteUint32(errCode);
141 if (!writeResult) {
142 HKS_LOG_E("WriteUint32 errCode %" LOG_PUBLIC "u failed %" LOG_PUBLIC "d", errCode, writeResult);
143 return;
144 }
145 if (errCode != DCM_SUCCESS) {
146 HKS_LOG_E("dcm callback fail errCode %" LOG_PUBLIC "u", errCode);
147 int res = Remote()->SendRequest(HKS_MSG_ATTEST_KEY_ASYNC_REPLY, data, reply, option);
148 if (res != ERR_OK) {
149 HKS_LOG_E("send fail reply errCode failed %" LOG_PUBLIC "d", res);
150 }
151 return;
152 }
153 writeResult = data.WriteUint32(sz);
154 if (!writeResult) {
155 HKS_LOG_E("WriteUint32 sz %" LOG_PUBLIC "u failed %" LOG_PUBLIC "d", sz, writeResult);
156 return;
157 }
158 if (sz == 0 || certChain == nullptr) {
159 HKS_LOG_E("dcm reply success but empty certChain %" LOG_PUBLIC "u", sz);
160 int res = Remote()->SendRequest(HKS_MSG_ATTEST_KEY_ASYNC_REPLY, data, reply, option);
161 if (res != ERR_OK) {
162 HKS_LOG_E("Remote()->SendRequest HKS_MSG_ATTEST_KEY_ASYNC_REPLY failed %" LOG_PUBLIC "d", res);
163 }
164 return;
165 }
166 writeResult = data.WriteBuffer(certChain.get(), sz);
167 if (!writeResult) {
168 HKS_LOG_E("WriteBuffer size %" LOG_PUBLIC "u failed %" LOG_PUBLIC "d", sz, writeResult);
169 return;
170 }
171 int res = Remote()->SendRequest(HKS_MSG_ATTEST_KEY_ASYNC_REPLY, data, reply, option);
172 if (res != ERR_OK) {
173 HKS_LOG_E("Remote()->SendRequest HKS_MSG_ATTEST_KEY_ASYNC_REPLY failed %" LOG_PUBLIC "d", res);
174 }
175 }
176
177 } // namespace Hks
178 } // namespace Security
179 } // namespace OHOS
180