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 "hks_template.h"
33 #include "huks_service_ipc_interface_code.h"
34
35 namespace OHOS {
36 namespace Security {
37 namespace Hks {
38
SendAsyncReply(uint32_t errCode,std::unique_ptr<uint8_t[]> & certChain,uint32_t sz)39 void HksStub::SendAsyncReply(uint32_t errCode, std::unique_ptr<uint8_t[]> &certChain, uint32_t sz)
40 {
41 std::unique_lock<std::mutex> lck(mMutex);
42 mErrCode = errCode;
43 mAsyncReply = std::move(certChain);
44 mSize = sz;
45 mCv.notify_all();
46 }
47
ProcessAttestKeyAsyncReply(MessageParcel & data)48 int HksStub::ProcessAttestKeyAsyncReply(MessageParcel& data)
49 {
50 std::unique_ptr<uint8_t[]> certChain{};
51 uint32_t errCode = 1;
52 if (!data.ReadUint32(errCode) || errCode != DCM_SUCCESS) {
53 HKS_LOG_E("ipc client read errCode %" LOG_PUBLIC "u", errCode);
54 SendAsyncReply(errCode, certChain, 0);
55 return ERR_INVALID_DATA;
56 }
57 uint32_t certChainLen = 0;
58 int err = ERR_INVALID_DATA;
59 do {
60 uint32_t sz = 0;
61 HKS_IF_TRUE_LOGE_BREAK(!data.ReadUint32(sz) || sz == 0 || sz > MAX_OUT_BLOB_SIZE,
62 "invalid sz %" LOG_PUBLIC "u", sz)
63 const uint8_t *ptr = data.ReadBuffer(sz);
64 HKS_IF_NULL_LOGE_BREAK(ptr, "ReadBuffer %" LOG_PUBLIC "u size ptr is nullptr", sz)
65 std::unique_ptr<uint8_t[]> receivedPtr(new (std::nothrow) uint8_t[sz]());
66 if (receivedPtr == nullptr) {
67 HKS_LOG_E("new receivedPtr failed");
68 err = ERR_NO_MEMORY;
69 break;
70 }
71 HKS_IF_NOT_EOK_LOGE_BREAK(memcpy_s(receivedPtr.get(), sz, ptr, sz), "memcpy_s receivedPtr failed");
72 err = ERR_OK;
73 certChain = std::move(receivedPtr);
74 certChainLen = sz;
75 } while (false);
76 SendAsyncReply(errCode, certChain, certChainLen);
77 return err;
78 }
79
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)80 int HksStub::OnRemoteRequest(uint32_t code,
81 MessageParcel& data, MessageParcel& reply, MessageOption& option)
82 {
83 HKS_IF_TRUE_LOGE_RETURN(data.ReadInterfaceToken() != GetDescriptor(), ERR_INVALID_DATA,
84 "failed to check interface token! code %" LOG_PUBLIC "d", code)
85 HKS_IF_TRUE_LOGE_RETURN(code != HKS_MSG_ATTEST_KEY_ASYNC_REPLY, ERR_TRANSACTION_FAILED,
86 "unknown remote request code %" LOG_PUBLIC "u", code)
87 return ProcessAttestKeyAsyncReply(data);
88 }
89
WaitForAsyncReply(int timeout)90 std::tuple<uint32_t, std::unique_ptr<uint8_t[]>, uint32_t> HksStub::WaitForAsyncReply(int timeout)
91 {
92 std::unique_lock<std::mutex> lck(mMutex);
93 mAsyncReply = nullptr;
94 mSize = 0;
95 mErrCode = DCM_SUCCESS;
96 HKS_LOG_I("begin wait for async reply");
97 mCv.wait_for(lck, std::chrono::seconds(timeout));
98 return {mErrCode, std::move(mAsyncReply), mSize};
99 }
100
101 BrokerDelegator<HksProxy> HksProxy::delegator_;
HksProxy(const sptr<IRemoteObject> & impl)102 HksProxy::HksProxy(const sptr<IRemoteObject> &impl)
103 : IRemoteProxy<IHksService>(impl)
104 {
105 }
106
SendAsyncReply(uint32_t errCode,std::unique_ptr<uint8_t[]> & certChain,uint32_t sz)107 void HksProxy::SendAsyncReply(uint32_t errCode, std::unique_ptr<uint8_t[]> &certChain, uint32_t sz)
108 {
109 HKS_IF_NULL_LOGE_RETURN_VOID(Remote(), "Remote() is nullptr! Would not SendRequest!")
110 MessageParcel data, reply;
111 MessageOption option = MessageOption::TF_ASYNC;
112 bool writeResult = data.WriteInterfaceToken(GetDescriptor());
113 HKS_IF_NOT_TRUE_LOGE_RETURN_VOID(writeResult,
114 "WriteInterfaceToken errCode %" LOG_PUBLIC "u failed %" LOG_PUBLIC "d", errCode, writeResult)
115 writeResult = data.WriteUint32(errCode);
116 HKS_IF_NOT_TRUE_LOGE_RETURN_VOID(writeResult, "WriteUint32 errCode %" LOG_PUBLIC "u failed %" LOG_PUBLIC "d",
117 errCode, writeResult)
118 if (errCode != DCM_SUCCESS) {
119 HKS_LOG_E("dcm callback fail errCode %" LOG_PUBLIC "u", errCode);
120 int res = Remote()->SendRequest(HKS_MSG_ATTEST_KEY_ASYNC_REPLY, data, reply, option);
121 HKS_IF_TRUE_LOGE(res != ERR_OK, "send fail reply errCode failed %" LOG_PUBLIC "d", res)
122 return;
123 }
124 writeResult = data.WriteUint32(sz);
125 HKS_IF_NOT_TRUE_LOGE_RETURN_VOID(writeResult, "WriteUint32 sz %" LOG_PUBLIC "u failed %" LOG_PUBLIC "d",
126 sz, writeResult)
127 if (sz == 0 || certChain == nullptr) {
128 HKS_LOG_E("dcm reply success but empty certChain %" LOG_PUBLIC "u", sz);
129 int res = Remote()->SendRequest(HKS_MSG_ATTEST_KEY_ASYNC_REPLY, data, reply, option);
130 HKS_IF_TRUE_LOGE(res != ERR_OK,
131 "Remote()->SendRequest HKS_MSG_ATTEST_KEY_ASYNC_REPLY failed %" LOG_PUBLIC "d", res)
132 return;
133 }
134 writeResult = data.WriteBuffer(certChain.get(), sz);
135 HKS_IF_NOT_TRUE_LOGE_RETURN_VOID(writeResult, "WriteBuffer size %" LOG_PUBLIC "u failed %" LOG_PUBLIC "d",
136 sz, writeResult)
137 int res = Remote()->SendRequest(HKS_MSG_ATTEST_KEY_ASYNC_REPLY, data, reply, option);
138 HKS_IF_TRUE_LOGE(res != ERR_OK,
139 "Remote()->SendRequest HKS_MSG_ATTEST_KEY_ASYNC_REPLY failed %" LOG_PUBLIC "d", res)
140 }
141
142 } // namespace Hks
143 } // namespace Security
144 } // namespace OHOS
145