• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "hks_request.h"
17 
18 #include <iservice_registry.h>
19 #include <message_option.h>
20 #include <securec.h>
21 
22 #include "hks_base_check.h" // for HksAttestIsAnonymous
23 #include "hks_log.h"
24 #include "hks_param.h"
25 #include "hks_sa_interface.h"
26 #include "hks_template.h"
27 #include "hks_type.h"
28 #include "huks_service_ipc_interface_code.h"
29 
30 using namespace OHOS;
31 
32 namespace {
33 constexpr int SA_ID_KEYSTORE_SERVICE = 3510;
34 const std::u16string SA_KEYSTORE_SERVICE_DESCRIPTOR = u"ohos.security.hks.service";
35 static volatile std::atomic_bool g_isInitBundleDead = false;
36 sptr<Security::Hks::HksStub> g_hks_callback;
37 }
38 
GetHksProxy()39 static sptr<IRemoteObject> GetHksProxy()
40 {
41     auto registry = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
42     HKS_IF_NULL_LOGE_RETURN(registry, nullptr, "GetHksProxy registry is null")
43 
44     sptr<IRemoteObject> hksProxy = registry->GetSystemAbility(SA_ID_KEYSTORE_SERVICE);
45     HKS_IF_NULL_LOGE_RETURN(hksProxy, nullptr,
46         "GetHksProxy GetSystemAbility %" LOG_PUBLIC "d is null", SA_ID_KEYSTORE_SERVICE)
47 
48     return hksProxy;
49 }
50 
HksReadRequestReply(MessageParcel & reply,struct HksBlob * outBlob)51 static int32_t HksReadRequestReply(MessageParcel &reply, struct HksBlob *outBlob)
52 {
53     int32_t ret = reply.ReadInt32();
54 
55     uint32_t outLen = reply.ReadUint32();
56     if (ret == HKS_SUCCESS && outLen == 0) {
57         if (outBlob != nullptr) {
58             outBlob->size = 0;
59         }
60     }
61     if (outLen != 0) {
62         HKS_IF_NOT_SUCC_LOGE_RETURN(CheckBlob(outBlob), (ret == HKS_SUCCESS ? HKS_ERROR_INVALID_ARGUMENT : ret),
63             "Check blob failed in HksReadRequestReply")
64         const uint8_t *outData = reply.ReadBuffer(outLen);
65         HKS_IF_NULL_RETURN(outData, ret == HKS_SUCCESS ? HKS_ERROR_IPC_MSG_FAIL : ret)
66 
67         if (ret == HKS_SUCCESS) {
68             if (outBlob->size < outLen) {
69                 HKS_LOG_E("outBlob size[%" LOG_PUBLIC "u] smaller than outLen[%" LOG_PUBLIC "u]",
70                     outBlob->size, outLen);
71                 return (ret == HKS_SUCCESS) ? HKS_ERROR_BUFFER_TOO_SMALL : ret;
72             }
73             HKS_IF_NOT_EOK_LOGE_RETURN(memcpy_s(outBlob->data, outBlob->size, outData, outLen),
74                 ret == HKS_SUCCESS ? HKS_ERROR_INSUFFICIENT_MEMORY : ret, "copy outBlob data failed!")
75             outBlob->size = outLen;
76         }
77     }
78 #ifdef L2_STANDARD
79     uint32_t errMsgLen = 0;
80     if (reply.ReadUint32(errMsgLen) && errMsgLen != 0 && errMsgLen < MAX_ERROR_MESSAGE_LEN) {
81         HKS_LOG_D("reply get errMsgLen = %{public}u", errMsgLen);
82         const uint8_t *errMsg = reply.ReadUnpadBuffer(errMsgLen);
83         HKS_IF_NULL_LOGE_RETURN(errMsg, ret, "[ipc error] read errorMsg")
84         HksAppendThreadErrMsg(errMsg, errMsgLen);
85     }
86 #endif
87 
88     return ret;
89 }
90 
HksSendAnonAttestRequestAndWaitAsyncReply(MessageParcel & data,const struct HksParamSet * paramSet,sptr<IRemoteObject> hksProxy,sptr<Security::Hks::HksStub> hksCallback,struct HksBlob * outBlob)91 static int32_t HksSendAnonAttestRequestAndWaitAsyncReply(MessageParcel &data, const struct HksParamSet *paramSet,
92     sptr<IRemoteObject> hksProxy, sptr<Security::Hks::HksStub> hksCallback, struct HksBlob *outBlob)
93 {
94     HKS_IF_NOT_SUCC_LOGE_RETURN(CheckBlob(outBlob), HKS_ERROR_INVALID_ARGUMENT, "invalid outBlob");
95     MessageParcel reply{};
96     // We send the request in sync mode, and we send a stub instance in the request.
97     // We wait for the instance callback later.
98     MessageOption option = MessageOption::TF_SYNC;
99     int error = hksProxy->SendRequest(HKS_MSG_ATTEST_KEY_ASYNC_REPLY, data, reply, option);
100     HKS_IF_NOT_SUCC_LOGE_RETURN(error, HKS_ERROR_IPC_MSG_FAIL, "hksProxy->SendRequest failed %" LOG_PUBLIC "d", error);
101 
102     int ret = HksReadRequestReply(reply, outBlob);
103     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
104         "HksSendAnonAttestRequestAndWaitAsyncReply HksReadRequestReply failed %" LOG_PUBLIC "d", ret)
105 
106 #ifndef HKS_UNTRUSTED_RUNNING_ENV
107     int timeout = 10; // seconds
108     auto [errCode, packedCerts, packedSize] = hksCallback->WaitForAsyncReply(timeout);
109     if (errCode != HKS_SUCCESS || packedCerts == nullptr || packedSize == 0) {
110         HKS_LOG_E("errCode %" LOG_PUBLIC "u fail or packedCerts empty or size %" LOG_PUBLIC "u 0", errCode, packedSize);
111         return HUKS_ERR_CODE_EXTERNAL_ERROR;
112     }
113 
114     if (outBlob->size < packedSize) {
115         HKS_LOG_E("out blob empty or too small %" LOG_PUBLIC "u %" LOG_PUBLIC "u", outBlob->size, packedSize);
116         return HKS_ERROR_INVALID_ARGUMENT;
117     }
118 
119     HKS_IF_NOT_EOK_LOGE_RETURN(memcpy_s(outBlob->data, outBlob->size, packedCerts.get(), packedSize),
120         HKS_ERROR_INVALID_ARGUMENT, "memcpy_s failed destMax %" LOG_PUBLIC "u count %" LOG_PUBLIC "u",
121         outBlob->size, packedSize)
122     outBlob->size = packedSize;
123     return HKS_SUCCESS;
124 #else
125     (void)(paramSet);
126     (void)(hksCallback);
127     return ret;
128 #endif
129 }
130 
HksSendRequest(enum HksIpcInterfaceCode type,const struct HksBlob * inBlob,struct HksBlob * outBlob,const struct HksParamSet * paramSet)131 int32_t HksSendRequest(enum HksIpcInterfaceCode type, const struct HksBlob *inBlob,
132     struct HksBlob *outBlob, const struct HksParamSet *paramSet)
133 {
134 #ifdef L2_STANDARD
135     HksClearThreadErrorMsg();
136 #endif
137     enum HksSendType sendType = HKS_SEND_TYPE_SYNC;
138     struct HksParam *sendTypeParam = nullptr;
139     int32_t ret = HksGetParam(paramSet, HKS_TAG_IS_ASYNCHRONIZED, &sendTypeParam);
140     if (ret == HKS_SUCCESS) {
141         sendType = static_cast<enum HksSendType>(sendTypeParam->uint32Param);
142     }
143 
144     MessageParcel data;
145     MessageParcel reply;
146     MessageOption option;
147     if (sendType == HKS_SEND_TYPE_SYNC) {
148         option = MessageOption::TF_SYNC;
149     } else {
150         option = MessageOption::TF_ASYNC;
151     }
152     HKS_IF_NOT_TRUE_RETURN(data.WriteInterfaceToken(SA_KEYSTORE_SERVICE_DESCRIPTOR), HKS_ERROR_BAD_STATE);
153 
154     if (outBlob == nullptr) {
155         HKS_IF_NOT_TRUE_RETURN(data.WriteUint32(0), HKS_ERROR_BAD_STATE);
156     } else {
157         HKS_IF_NOT_TRUE_LOGE_RETURN(data.WriteUint32(outBlob->size), HKS_ERROR_BAD_STATE, "WriteUint32 fail")
158     }
159     HKS_IF_NOT_TRUE_RETURN(data.WriteUint32(inBlob->size), HKS_ERROR_BAD_STATE);
160     HKS_IF_NOT_TRUE_RETURN(data.WriteBuffer(inBlob->data, static_cast<size_t>(inBlob->size)), HKS_ERROR_BAD_STATE);
161 
162     sptr<IRemoteObject> hksProxy = GetHksProxy();
163     HKS_IF_NULL_LOGE_RETURN(hksProxy, HKS_ERROR_BAD_STATE, "GetHksProxy registry is null")
164 
165     bool flag = false;
166     if (type == HKS_MSG_INIT && std::atomic_compare_exchange_strong(&g_isInitBundleDead, &flag, true)) {
167         g_hks_callback = new (std::nothrow) Security::Hks::HksStub();
168         HKS_IF_NULL_LOGE_RETURN(g_hks_callback, HKS_ERROR_INSUFFICIENT_MEMORY, "new HksStub failed")
169 
170         bool result = data.WriteRemoteObject(g_hks_callback);
171         HKS_IF_NOT_TRUE_LOGE_RETURN(result, HKS_ERROR_IPC_MSG_FAIL,
172             "WriteRemoteObject hksCallback failed %" LOG_PUBLIC "d", result)
173     }
174     if (type == HKS_MSG_ATTEST_KEY_ASYNC_REPLY) {
175         sptr<Security::Hks::HksStub> hksCallback = new (std::nothrow) Security::Hks::HksStub();
176         HKS_IF_NULL_LOGE_RETURN(hksCallback, HKS_ERROR_INSUFFICIENT_MEMORY, "new HksStub failed")
177         // We write a HksStub instance if type == HKS_MSG_ATTEST_KEY_ASYNC_REPLY,
178         // then we can read it in the server side if type == HKS_MSG_ATTEST_KEY_ASYNC_REPLY.
179         bool result = data.WriteRemoteObject(hksCallback);
180         HKS_IF_NOT_TRUE_LOGE_RETURN(result, HKS_ERROR_IPC_MSG_FAIL,
181             "WriteRemoteObject hksCallback failed %" LOG_PUBLIC "d", result)
182         return HksSendAnonAttestRequestAndWaitAsyncReply(data, paramSet, hksProxy, hksCallback, outBlob);
183         // If the mode is non-anonymous attest, we write a HksStub instance here, then go back and process as normal.
184     }
185 
186     int error = hksProxy->SendRequest(type, data, reply, option);
187     HKS_IF_TRUE_LOGE_RETURN(error != 0, HKS_ERROR_IPC_MSG_FAIL, "hksProxy->SendRequest failed %" LOG_PUBLIC "d", error)
188 
189     return HksReadRequestReply(reply, outBlob);
190 }
191