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 <vector>
17 
18 #include "cert_mgr_adapter_impl.h"
19 #include "net_conn_client.h"
20 #include "nweb_log.h"
21 #include "securec.h"
22 
23 using namespace OHOS::NWeb;
24 
25 namespace OHOS::NWeb {
26 
InitCertList(struct CertList ** cList)27 int32_t CertManagerAdapterImpl::InitCertList(struct CertList **cList)
28 {
29     *cList = static_cast<struct CertList *>(malloc(sizeof(struct CertList)));
30     if (*cList == nullptr) {
31         return CMR_ERROR_MALLOC_FAIL;
32     }
33 
34     uint32_t buffSize = MAX_COUNT_CERTIFICATE * sizeof(struct CertAbstract);
35     (*cList)->certAbstract = static_cast<struct CertAbstract *>(malloc(buffSize));
36     if ((*cList)->certAbstract == nullptr) {
37         free(*cList);
38         *cList = nullptr;
39         return CMR_ERROR_MALLOC_FAIL;
40     }
41     (void)memset_s((*cList)->certAbstract, buffSize, 0, buffSize);
42     (*cList)->certsCount = MAX_COUNT_CERTIFICATE;
43 
44     return CM_SUCCESS;
45 }
46 
InitCertInfo(struct CertInfo * certInfo)47 int32_t CertManagerAdapterImpl::InitCertInfo(struct CertInfo *certInfo)
48 {
49     if (certInfo == nullptr) {
50         return CMR_ERROR_MALLOC_FAIL;
51     }
52 
53     certInfo->certInfo.data = static_cast<uint8_t *>(malloc(MAX_LEN_CERTIFICATE));
54     if (certInfo->certInfo.data == nullptr) {
55         return CMR_ERROR_MALLOC_FAIL;
56     }
57     certInfo->certInfo.size = MAX_LEN_CERTIFICATE;
58 
59     return CM_SUCCESS;
60 }
61 
FreeCMBlobData(struct CmBlob * blob)62 void CertManagerAdapterImpl::FreeCMBlobData(struct CmBlob *blob)
63 {
64     if (blob == nullptr) {
65         return;
66     }
67 
68     if (blob->data != nullptr) {
69         free(blob->data);
70         blob->data = nullptr;
71     }
72     blob->size = 0;
73 }
74 
FreeCertList(CertList * certList)75 void CertManagerAdapterImpl::FreeCertList(CertList *certList)
76 {
77     if (certList == nullptr) {
78         return;
79     }
80 
81     if (certList->certAbstract != nullptr) {
82         free(certList->certAbstract);
83         certList->certAbstract = nullptr;
84     }
85 
86     free(certList);
87     certList = nullptr;
88 }
89 
GetCertMaxSize()90 uint32_t CertManagerAdapterImpl::GetCertMaxSize()
91 {
92     return MAX_LEN_CERTIFICATE;
93 }
94 
GetAppCertMaxSize()95 uint32_t CertManagerAdapterImpl::GetAppCertMaxSize()
96 {
97     return MAX_LEN_CERTIFICATE_CHAIN;
98 }
99 
GetSytemRootCertSum()100 uint32_t CertManagerAdapterImpl::GetSytemRootCertSum()
101 {
102     uint32_t certSum = 0;
103     struct CertList *certList = nullptr;
104     int32_t ret = InitCertList(&certList);
105     if (ret != CM_SUCCESS) {
106         WVLOG_E("GetSytemRootCertSum, init cert list failed, ret = %{public}d ", ret);
107         FreeCertList(certList);
108         return certSum;
109     }
110 
111     ret = CmGetCertList(CM_SYSTEM_TRUSTED_STORE, certList);
112     if (ret != CM_SUCCESS) {
113         WVLOG_E("GetSytemRootCertSum, get cert list failed, ret = %{public}d ", ret);
114         FreeCertList(certList);
115         return certSum;
116     }
117 
118     if (certList != nullptr) {
119         certSum = certList->certsCount;
120     }
121 
122     FreeCertList(certList);
123     return certSum;
124 }
125 
GetCertInfo(char * uri,struct CertInfo * certInfo,int32_t certType)126 int32_t CertManagerAdapterImpl::GetCertInfo(char *uri, struct CertInfo *certInfo, int32_t certType)
127 {
128     unsigned int len = sizeof(struct CertInfo);
129     (void)memset_s(certInfo, len, 0, len);
130     int32_t ret = InitCertInfo(certInfo);
131     if (ret != CM_SUCCESS) {
132         WVLOG_E("GetCertInfo, init cert failed, ret = %{public}d", ret);
133         FreeCMBlobData(&(certInfo->certInfo));
134         return CM_FAILURE;
135     }
136 
137     struct CmBlob uriBlob = {strlen(uri) + 1, reinterpret_cast<uint8_t *>(uri)};
138 
139     if (certType == CM_USER_TRUSTED_STORE) {
140         ret = CmGetUserCertInfo(&uriBlob, certType, certInfo);
141     } else if (certType == CM_SYSTEM_TRUSTED_STORE) {
142         ret = CmGetCertInfo(&uriBlob, certType, certInfo);
143     } else {
144         WVLOG_E("GetCertInfo, unknow certType = %{public}d", certType);
145         FreeCMBlobData(&(certInfo->certInfo));
146         return CM_FAILURE;
147     }
148 
149     if (ret != CM_SUCCESS) {
150         WVLOG_E("GetCertInfo, get cert info failed, ret = %{public}d", ret);
151         FreeCMBlobData(&(certInfo->certInfo));
152         return ret;
153     }
154 
155     return CM_SUCCESS;
156 }
157 
GetCertDataBySubject(const char * subjectName,uint8_t * certData,int32_t certType)158 int32_t CertManagerAdapterImpl::GetCertDataBySubject(const char *subjectName, uint8_t* certData, int32_t certType)
159 {
160     struct CertList *certList = nullptr;
161     int32_t ret = InitCertList(&certList);
162     if (ret != CM_SUCCESS) {
163         WVLOG_E("GetCertDataBySubject, init cert list failed, ret = %{public}d", ret);
164         return CM_FAILURE;
165     }
166 
167     if (certType == CM_USER_TRUSTED_STORE) {
168         ret = CmGetUserCertList(certType, certList);
169     } else if (certType == CM_SYSTEM_TRUSTED_STORE) {
170         ret = CmGetCertList(certType, certList);
171     } else {
172         WVLOG_E("GetCertDataBySubject, unknow certType = %{public}d", certType);
173         FreeCertList(certList);
174         return CM_FAILURE;
175     }
176 
177     if (ret != CM_SUCCESS) {
178         WVLOG_E("GetCertDataBySubject, get cert list failed, ret = %{public}d", ret);
179         FreeCertList(certList);
180         return CM_FAILURE;
181     }
182 
183     char *uri = nullptr;
184     for (uint32_t i = 0; i < certList->certsCount; i++) {
185         if (0 == strcmp(subjectName, certList->certAbstract[i].subjectName)) {
186             uri = certList->certAbstract[i].uri;
187             break;
188         }
189     }
190 
191     if (!uri) {
192         WVLOG_D("GetCertDataBySubject, can not find cert");
193         FreeCertList(certList);
194         return CM_FAILURE;
195     }
196 
197     struct CertInfo certInfo;
198     ret = GetCertInfo(uri, &certInfo, certType);
199     if (ret != CM_SUCCESS) {
200         WVLOG_E("GetCertDataBySubject, get cert info failed, ret = %{public}d", ret);
201         FreeCertList(certList);
202         return CM_FAILURE;
203     }
204 
205     ret = CM_SUCCESS;
206     if (memcpy_s(certData, MAX_LEN_CERTIFICATE, certInfo.certInfo.data, certInfo.certInfo.size) != EOK) {
207         WVLOG_E("GetCertDataBySubject, memory copy failed");
208         ret = CM_FAILURE;
209     }
210 
211     FreeCMBlobData(&(certInfo.certInfo));
212     FreeCertList(certList);
213     return ret;
214 }
215 
GetSytemRootCertData(uint32_t certCount,uint8_t * certData)216 int32_t CertManagerAdapterImpl::GetSytemRootCertData(uint32_t certCount, uint8_t* certData)
217 {
218     struct CertList *certList = nullptr;
219     int32_t ret = InitCertList(&certList);
220     if (ret != CM_SUCCESS) {
221         WVLOG_E("GetSytemRootCertData, init cert list failed, ret = %{public}d ", ret);
222         FreeCertList(certList);
223         return CM_FAILURE;
224     }
225 
226     ret = CmGetCertList(CM_SYSTEM_TRUSTED_STORE, certList);
227     if (ret != CM_SUCCESS) {
228         WVLOG_E("GetSytemRootCertData, get cert list failed, ret = %{public}d ", ret);
229         FreeCertList(certList);
230         return CM_FAILURE;
231     }
232 
233     struct CertInfo certInfo;
234     unsigned int len = sizeof(struct CertInfo);
235     (void)memset_s(&certInfo, len, 0, len);
236     ret = InitCertInfo(&certInfo);
237     if (ret != CM_SUCCESS) {
238         WVLOG_E("GetSytemRootCertData, init cert failed, ret = %{public}d ", ret);
239         FreeCMBlobData(&(certInfo.certInfo));
240         FreeCertList(certList);
241         return CM_FAILURE;
242     }
243 
244     if (certCount > certList->certsCount) {
245         WVLOG_E("GetSytemRootCertData, cert count invailed, cert count = %{public}d ", certCount);
246         FreeCMBlobData(&(certInfo.certInfo));
247         FreeCertList(certList);
248         return CM_FAILURE;
249     }
250 
251     char *uri = certList->certAbstract[certCount].uri;
252     struct CmBlob uriBlob = {strlen(uri) + 1, (uint8_t *)(uri)};
253 
254     ret = CmGetCertInfo(&uriBlob, CM_SYSTEM_TRUSTED_STORE, &certInfo);
255     if (ret != CM_SUCCESS) {
256         WVLOG_E("GetSytemRootCertData, get cert info failed, ret = %{public}d ", ret);
257         FreeCMBlobData(&(certInfo.certInfo));
258         FreeCertList(certList);
259         return CM_FAILURE;
260     }
261 
262     if (memcpy_s(certData, MAX_LEN_CERTIFICATE, certInfo.certInfo.data, certInfo.certInfo.size) != EOK) {
263         WVLOG_E("GetSytemRootCertData, memory copy failed");
264         FreeCMBlobData(&(certInfo.certInfo));
265         FreeCertList(certList);
266         return CM_FAILURE;
267     }
268 
269     FreeCMBlobData(&(certInfo.certInfo));
270     FreeCertList(certList);
271     return CM_SUCCESS;
272 }
273 
GetUserRootCertSum()274 uint32_t CertManagerAdapterImpl::GetUserRootCertSum()
275 {
276     uint32_t certSum = 0;
277     struct CertList *certList = nullptr;
278     int32_t ret = InitCertList(&certList);
279     if (ret != CM_SUCCESS) {
280         WVLOG_E("GetUserRootCertSum, init cert list failed, ret = %{public}d ", ret);
281         FreeCertList(certList);
282         return certSum;
283     }
284 
285     ret = CmGetUserCertList(CM_USER_TRUSTED_STORE, certList);
286     if (ret != CM_SUCCESS) {
287         WVLOG_E("GetUserRootCertSum, get user cert list failed, ret = %{public}d ", ret);
288         FreeCertList(certList);
289         return certSum;
290     }
291 
292     if (certList != nullptr) {
293         certSum = certList->certsCount;
294     }
295 
296     FreeCertList(certList);
297     return certSum;
298 }
299 
GetUserRootCertData(uint32_t certCount,uint8_t * certData)300 int32_t CertManagerAdapterImpl::GetUserRootCertData(uint32_t certCount, uint8_t* certData)
301 {
302     struct CertList *certList = nullptr;
303     int32_t ret = InitCertList(&certList);
304     if (ret != CM_SUCCESS) {
305         WVLOG_E("GetUserRootCertData, init cert list, ret = %{public}d ", ret);
306         FreeCertList(certList);
307         return CM_FAILURE;
308     }
309 
310     ret = CmGetUserCertList(CM_USER_TRUSTED_STORE, certList);
311     if (ret != CM_SUCCESS) {
312         WVLOG_E("GetUserRootCertData, get user cert list failed, ret = %{public}d ", ret);
313         FreeCertList(certList);
314         return CM_FAILURE;
315     }
316 
317     struct CertInfo certInfo;
318     unsigned int len = sizeof(struct CertInfo);
319     (void)memset_s(&certInfo, len, 0, len);
320     ret = InitCertInfo(&certInfo);
321     if (ret != CM_SUCCESS) {
322         WVLOG_E("GetUserRootCertData, init cert info failed, ret = %{public}d ", ret);
323         FreeCMBlobData(&(certInfo.certInfo));
324         FreeCertList(certList);
325         return CM_FAILURE;
326     }
327 
328     if (certCount > certList->certsCount) {
329         WVLOG_E("GetUserRootCertData, cert count invailed, cert count = %{public}d ", certCount);
330         FreeCMBlobData(&(certInfo.certInfo));
331         FreeCertList(certList);
332         return CM_FAILURE;
333     }
334 
335     char *uri = certList->certAbstract[certCount].uri;
336     struct CmBlob uriBlob = {strlen(uri) + 1, (uint8_t *)(uri)};
337 
338     ret = CmGetUserCertInfo(&uriBlob, CM_USER_TRUSTED_STORE, &certInfo);
339     if (ret != CM_SUCCESS) {
340         WVLOG_E("GetUserRootCertData, get user cert info failed, ret = %{public}d ", ret);
341         FreeCMBlobData(&(certInfo.certInfo));
342         FreeCertList(certList);
343         return CM_FAILURE;
344     }
345 
346     if (memcpy_s(certData, MAX_LEN_CERTIFICATE, certInfo.certInfo.data, certInfo.certInfo.size) != EOK) {
347         WVLOG_E("GetUserRootCertData, memory copy failed");
348         FreeCMBlobData(&(certInfo.certInfo));
349         FreeCertList(certList);
350         return CM_FAILURE;
351     }
352 
353     FreeCMBlobData(&(certInfo.certInfo));
354     FreeCertList(certList);
355     return CM_SUCCESS;
356 }
357 
GetAppCert(uint8_t * uriData,uint8_t * certData,uint32_t * len)358 int32_t CertManagerAdapterImpl::GetAppCert(uint8_t* uriData, uint8_t* certData, uint32_t* len)
359 {
360     struct Credential cred;
361     (void)memset_s(&cred, sizeof(struct Credential), 0, sizeof(struct Credential));
362     cred.credData.size = MAX_LEN_CERTIFICATE_CHAIN;
363     cred.credData.data = static_cast<uint8_t *>(malloc(MAX_LEN_CERTIFICATE_CHAIN));
364     if (cred.credData.data == nullptr) {
365         WVLOG_E("GetAppCert, malloc failed");
366         return CM_FAILURE;
367     }
368 
369     struct CmBlob uri = { strlen((char*)uriData) + 1, uriData };
370     int32_t ret = CmGetAppCert(&uri, CM_CREDENTIAL_STORE, &cred);
371     if (ret != CM_SUCCESS) {
372         WVLOG_E("GetAppCert, get app cert failed, ret = %{public}d ", ret);
373         free(cred.credData.data);
374         cred.credData.data = nullptr;
375         return CM_FAILURE;
376     }
377 
378     *len = cred.credData.size;
379     if (memcpy_s(certData, MAX_LEN_CERTIFICATE_CHAIN, cred.credData.data, cred.credData.size) != EOK) {
380         WVLOG_E("GetAppCert, memory copy failed");
381         free(cred.credData.data);
382         cred.credData.data = nullptr;
383         return CM_FAILURE;
384     }
385 
386     free(cred.credData.data);
387     cred.credData.data = nullptr;
388     return CM_SUCCESS;
389 }
390 
Sign(const uint8_t * uri,const uint8_t * certData,uint32_t certDataLen,uint8_t * signData,uint32_t signDataLen)391 int32_t CertManagerAdapterImpl::Sign(const uint8_t* uri, const uint8_t* certData, uint32_t certDataLen,
392     uint8_t* signData, uint32_t signDataLen)
393 {
394     uint64_t handleValue = 0;
395     struct CmBlob handle = { sizeof(uint64_t), (uint8_t *)&handleValue };
396     const struct CmBlob keyUri = { strlen((char*)uri) + 1, (uint8_t*)uri };
397     struct CmSignatureSpec spec = { CM_KEY_PURPOSE_SIGN, CM_PADDING_PSS, CM_DIGEST_SHA256 };
398 
399     if (signData == nullptr) {
400         WVLOG_E("Sign, sign data is nullptr");
401         return CM_FAILURE;
402     }
403 
404     int32_t ret = CmInit(&keyUri, &spec, &handle);
405     if (ret != CM_SUCCESS) {
406         WVLOG_E("Sign, init failed, ret = %{public}d ", ret);
407         return CM_FAILURE;
408     }
409 
410     const struct CmBlob message = {certDataLen, const_cast<uint8_t *>(certData)};
411     ret = CmUpdate(&handle, &message);
412     if (ret != CM_SUCCESS) {
413         WVLOG_E("Sign, update failed, ret = %{public}d ", ret);
414         return CM_FAILURE;
415     }
416 
417     struct CmBlob signature = { signDataLen, signData };
418     struct CmBlob inDataFinish = { 0, nullptr };
419     ret = CmFinish(&handle, &inDataFinish, &signature);
420     if (ret != CM_SUCCESS) {
421         WVLOG_E("Sign, finish failed, ret = %{public}d ", ret);
422         return CM_FAILURE;
423     }
424 
425     ret = CmAbort(&handle);
426     if (ret != CM_SUCCESS) {
427         WVLOG_E("Sign, abort failed, ret = %{public}d ", ret);
428         return CM_FAILURE;
429     }
430 
431     return CM_SUCCESS;
432 }
433 
GetTrustAnchorsForHostName(const std::string & hostname,std::vector<std::string> & certs)434 bool CertManagerAdapterImpl::GetTrustAnchorsForHostName(
435     const std::string& hostname, std::vector<std::string>& certs)
436 {
437     int32_t ret = OHOS::NetManagerStandard::NetConnClient::GetInstance().
438         GetTrustAnchorsForHostName(hostname, certs);
439     if (ret != OHOS::NetManagerStandard::NETMANAGER_SUCCESS) {
440         WVLOG_E("GetTrustAnchorsForHostName for hostname:%{public}s failed",
441             hostname.c_str());
442         return false;
443     }
444     return true;
445 }
446 
GetPinSetForHostName(const std::string & hostname,std::vector<std::string> & pins)447 bool CertManagerAdapterImpl::GetPinSetForHostName(
448     const std::string& hostname, std::vector<std::string>& pins)
449 {
450     std::string pinsString;
451     int32_t ret = OHOS::NetManagerStandard::NetConnClient::GetInstance().
452         GetPinSetForHostName(hostname, pinsString);
453     if (ret != OHOS::NetManagerStandard::NETMANAGER_SUCCESS) {
454         WVLOG_E("GetPinSetForHostName for hostname:%{public}s failed, ret:%{public}d",
455             hostname.c_str(), ret);
456         return false;
457     }
458 
459     if (pinsString.empty()) {
460         WVLOG_D("GetPinSetForHostName for hostname:%{public}s is empty", hostname.c_str());
461         return true;
462     }
463     size_t start = 0;
464     size_t pos = pinsString.find(";", start);
465     while (pos != std::string::npos) {
466         pins.emplace_back(pinsString.substr(start, pos - start));
467         start = pos + 1;
468         pos = pinsString.find(";", start);
469     }
470     pins.emplace_back(pinsString.substr(start));
471     return true;
472 }
473 }
474