• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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_sign_key.h"
17 
18 #include <cstring>
19 #include <cstdio>
20 #include <climits>
21 #include <securec.h>
22 #include <string>
23 
24 #include "byte_buffer.h"
25 #include "cert_utils.h"
26 #include "errcode.h"
27 #include "iservice_registry.h"
28 #include "log.h"
29 #include "system_ability_definition.h"
30 
31 namespace OHOS {
32 namespace Security {
33 namespace CodeSign {
34 static const std::string ALIAS_NAME = "LOCAL_SIGN_KEY";
35 static const struct HksBlob LOCAL_SIGN_KEY_ALIAS = { ALIAS_NAME.size(), (uint8_t *)ALIAS_NAME.c_str()};
36 static const uint32_t SIGNATURE_COMMON_SIZE = 512;
37 
38 static const std::string SUPPORTED_SIGN_ALGORITHM = "ECDSA256";
39 static constexpr uint32_t MAX_SIGN_SIZE = 65535;
40 
41 static const struct HksParam ECC_KEY_PRARAM[] = {
42     { .tag = HKS_TAG_KEY_STORAGE_FLAG, .uint32Param = HKS_STORAGE_PERSISTENT },
43     { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_ECC },
44     { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_ECC_KEY_SIZE_256 },
45     { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_SIGN | HKS_KEY_PURPOSE_VERIFY },
46     { .tag = HKS_TAG_DIGEST, .uint32Param = HKS_DIGEST_SHA256 },
47     { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }
48 };
49 
50 static const struct HksParam ECC_SIGN_PRARAM[] = {
51     { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_ECC },
52     { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_ECC_KEY_SIZE_256 },
53     { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_SIGN },
54     { .tag = HKS_TAG_DIGEST, .uint32Param = HKS_DIGEST_SHA256 },
55     { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }
56 };
57 
58 static const struct HksParam ECC_EXIST_PRARAM[] = {
59     { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }
60 };
61 
GetInstance()62 LocalSignKey &LocalSignKey::GetInstance()
63 {
64     static LocalSignKey singleLocalSignKey;
65     return singleLocalSignKey;
66 }
67 
LocalSignKey()68 LocalSignKey::LocalSignKey()
69 {
70 }
71 
~LocalSignKey()72 LocalSignKey::~LocalSignKey()
73 {
74     if (cert_ != nullptr) {
75         delete cert_;
76         cert_ = nullptr;
77     }
78     if (certChain_ != nullptr) {
79         FreeCertChain(&certChain_, certChain_->certsCount);
80         certChain_ = nullptr;
81     }
82 }
83 
SetChallenge(const ByteBuffer & challenge)84 void LocalSignKey::SetChallenge(const ByteBuffer &challenge)
85 {
86     std::lock_guard<std::mutex> lock(lock_);
87     if (challenge_) {
88         challenge_.reset(nullptr);
89     }
90     uint32_t len = challenge.GetSize();
91     challenge_ = std::make_unique<ByteBuffer>(len);
92     if (challenge_ == nullptr) {
93         return;
94     }
95     if (memcpy_s(challenge_->GetBuffer(), len, challenge.GetBuffer(), len) != EOK) {
96         LOG_ERROR("set challenge failed.");
97     }
98 }
Connect()99 sptr<AppExecFwk::IBundleMgr> LocalSignKey::Connect()
100 {
101     sptr<ISystemAbilityManager> systemAbilityManager =
102         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
103     if (systemAbilityManager == nullptr) {
104         LOG_ERROR("failed to get system ability manager");
105         return nullptr;
106     }
107     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
108     if (remoteObject == nullptr) {
109         LOG_ERROR("get remoteObject failed");
110         return nullptr;
111     }
112     return iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
113 }
114 
UpdateKey()115 bool LocalSignKey::UpdateKey()
116 {
117     HUKSParamSet paramSet;
118     bool bRet = paramSet.Init(ECC_EXIST_PRARAM, sizeof(ECC_EXIST_PRARAM) / sizeof(HksParam));
119     if (!bRet) {
120         return false;
121     }
122     int32_t ret = HksKeyExist(&LOCAL_SIGN_KEY_ALIAS, paramSet.GetParamSet());
123     if (ret == HKS_ERROR_NOT_EXIST) {
124         LOG_INFO("The key does not exist, update the key, ret is %{public}d!", ret);
125         sptr<AppExecFwk::IBundleMgr> bundleMgr = Connect();
126         if (bundleMgr == nullptr) {
127             LOG_ERROR("Get bundleMgr failed");
128             return false;
129         }
130         int32_t result = bundleMgr->ResetAllAOT();
131         if (result != ERR_OK) {
132             LOG_ERROR("bundleMgr reset aot fail.");
133             return false;
134         }
135         if (!GenerateKey()) {
136             LOG_ERROR("GenerateKey fail.");
137             return false;
138         }
139     } else if (ret != HKS_SUCCESS) {
140         LOG_ERROR("HksKeyExist fail, ret is %{public}d!", ret);
141         return false;
142     }
143     return true;
144 }
145 
InitKey()146 bool LocalSignKey::InitKey()
147 {
148     if (!UpdateKey()) {
149         return false;
150     }
151     certChain_ = QueryCertChain();
152     if (certChain_ == nullptr) {
153         return false;
154     }
155     return true;
156 }
157 
GetSignCert()158 const ByteBuffer *LocalSignKey::GetSignCert()
159 {
160     if (cert_ != nullptr) {
161         return cert_;
162     }
163     const HksCertChain *certChain = GetCertChain();
164     if (certChain == nullptr) {
165         return nullptr;
166     }
167     cert_ = new (std::nothrow) ByteBuffer();
168     if (cert_ == nullptr) {
169         LOG_ERROR("Alloc memory for cert blob failed.");
170         return nullptr;
171     }
172     // get cert chain with 4 certs. the first is sign cert
173     if (!cert_->CopyFrom(certChain->certs[0].data, certChain->certs[0].size)) {
174         delete cert_;
175         cert_ = nullptr;
176     }
177     return cert_;
178 }
179 
GetCertChain()180 const HksCertChain *LocalSignKey::GetCertChain()
181 {
182     if (certChain_ != nullptr) {
183         return certChain_;
184     }
185     certChain_ = QueryCertChain();
186     if (certChain_ == nullptr) {
187         LOG_ERROR("QueryCertChain failed.");
188         return nullptr;
189     }
190     return certChain_;
191 }
192 
QueryCertChain()193 HksCertChain *LocalSignKey::QueryCertChain()
194 {
195     // init attest param
196     HUKSParamSet paramSet;
197     if (!GetAttestParamSet(paramSet)) {
198         return nullptr;
199     }
200 
201     HksCertChain *certChain = nullptr;
202     // alloc memory for cert chain
203     if (!ConstructDataToCertChain(&certChain)) {
204         return nullptr;
205     }
206 
207     // get cert chain by huks attest
208     int32_t ret = HksAttestKey(&LOCAL_SIGN_KEY_ALIAS, paramSet.GetParamSet(), certChain);
209     if (ret != HKS_SUCCESS) {
210         FreeCertChain(&certChain, certChain->certsCount);
211         LOG_ERROR("HksAttestKey fail, ret is %{public}d!", ret);
212         return nullptr;
213     }
214     return certChain;
215 }
216 
GetFormattedCertChain(ByteBuffer & buffer)217 int32_t LocalSignKey::GetFormattedCertChain(ByteBuffer &buffer)
218 {
219     if (GetCertChain() == nullptr) {
220         return CS_ERR_HUKS_OBTAIN_CERT;
221     }
222     if (!FormattedCertChain(certChain_, buffer)) {
223         return CS_ERR_MEMORY;
224     }
225     return CS_SUCCESS;
226 }
227 
GetKeyParamSet(HUKSParamSet & paramSet)228 bool LocalSignKey::GetKeyParamSet(HUKSParamSet &paramSet)
229 {
230     if (algorithm_.compare(SUPPORTED_SIGN_ALGORITHM) == 0) {
231         return paramSet.Init(ECC_KEY_PRARAM, sizeof(ECC_KEY_PRARAM) / sizeof(HksParam));
232     }
233     return false;
234 }
235 
GetAttestParamSet(HUKSParamSet & paramSet)236 bool LocalSignKey::GetAttestParamSet(HUKSParamSet &paramSet)
237 {
238     std::lock_guard<std::mutex> lock(lock_);
239     // init challenge data by secure random function
240     if (challenge_ == nullptr) {
241         challenge_ = GetRandomChallenge();
242         if (challenge_ == nullptr) {
243             return false;
244         }
245     }
246 
247     LOG_INFO("challenge in attest param.");
248     struct HksBlob challengeBlob = {
249         .size = challenge_->GetSize(),
250         .data = challenge_->GetBuffer()
251     };
252     struct HksParam attestationParams[] = {
253         { .tag = HKS_TAG_ATTESTATION_CHALLENGE, .blob = challengeBlob },
254         { .tag = HKS_TAG_ATTESTATION_ID_ALIAS, .blob = LOCAL_SIGN_KEY_ALIAS },
255         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }
256     };
257     return paramSet.Init(attestationParams, sizeof(attestationParams) / sizeof(HksParam));
258 }
259 
GenerateKey()260 bool LocalSignKey::GenerateKey()
261 {
262     HUKSParamSet paramSet;
263     if (!GetKeyParamSet(paramSet)) {
264         return false;
265     }
266     int32_t ret = HksGenerateKey(&LOCAL_SIGN_KEY_ALIAS, paramSet.GetParamSet(), nullptr);
267     if (ret != HKS_SUCCESS) {
268         LOG_ERROR("HksGenerateKey failed, ret is %{public}d!", ret);
269         return false;
270     }
271     return true;
272 }
273 
GetSignParamSet(HUKSParamSet & paramSet)274 bool LocalSignKey::GetSignParamSet(HUKSParamSet &paramSet)
275 {
276     if (algorithm_.compare(SUPPORTED_SIGN_ALGORITHM) == 0) {
277         return paramSet.Init(ECC_SIGN_PRARAM, sizeof(ECC_SIGN_PRARAM) / sizeof(HksParam));
278     }
279     return false;
280 }
281 
Sign(const ByteBuffer & data,ByteBuffer & signature)282 bool LocalSignKey::Sign(const ByteBuffer &data, ByteBuffer &signature)
283 {
284     if (data.GetSize() > MAX_SIGN_SIZE) {
285         LOG_ERROR("Data to sign is too long");
286         return false;
287     }
288     struct HksBlob inData = {
289         .size = data.GetSize(),
290         .data = data.GetBuffer()
291     };
292 
293     uint8_t tmpOut[SIGNATURE_COMMON_SIZE] = {0};
294     struct HksBlob outData = {
295         .size = SIGNATURE_COMMON_SIZE,
296         .data = tmpOut
297     };
298     if (!SignByHUKS(&inData, &outData)) {
299         return false;
300     }
301     if (!signature.CopyFrom(outData.data, outData.size)) {
302         return false;
303     }
304     return true;
305 }
306 
SignByHUKS(const struct HksBlob * inData,struct HksBlob * outData)307 bool LocalSignKey::SignByHUKS(const struct HksBlob *inData, struct HksBlob *outData)
308 {
309     if (!UpdateKey()) {
310         return false;
311     }
312     HUKSParamSet paramSet;
313     if (!GetSignParamSet(paramSet)) {
314         return false;
315     }
316     // first stage: init, set key alias
317     uint8_t tmpHandle[sizeof(uint64_t)] = {0};
318     struct HksBlob handle = { sizeof(uint64_t), tmpHandle };
319     int32_t ret = HksInit(&LOCAL_SIGN_KEY_ALIAS, paramSet.GetParamSet(), &handle, nullptr);
320     if (ret != HKS_SUCCESS) {
321         LOG_ERROR("HksInit failed");
322         return false;
323     }
324     // second stage: update, send input data to HUKS
325     struct HksBlob tmpOutData = {
326         .size = MAX_SIGN_SIZE,
327         .data = nullptr
328     };
329     tmpOutData.data = static_cast<uint8_t *>(malloc(tmpOutData.size));
330     if (tmpOutData.data == nullptr) {
331         LOG_ERROR("Alloc memory for blob failed.");
332         return false;
333     }
334     ret = HksUpdate(&handle, paramSet.GetParamSet(), inData, &tmpOutData);
335     if (ret != HKS_SUCCESS) {
336         LOG_ERROR("HksUpdate Failed.");
337         free(tmpOutData.data);
338         return false;
339     }
340     // third stage: finish, get signature from HUKS
341     tmpOutData.size = 0;
342     ret = HksFinish(&handle, paramSet.GetParamSet(), &tmpOutData, outData);
343     free(tmpOutData.data);
344     if (ret != HKS_SUCCESS) {
345         LOG_ERROR("HksFinish Failed.");
346         return false;
347     }
348     return true;
349 }
350 }
351 }
352 }
353