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 "util/hap_verify_openssl_utils.h"
17 
18 #include "common/hap_verify_log.h"
19 #include "openssl/asn1.h"
20 #include "openssl/bio.h"
21 #include "openssl/crypto.h"
22 #include "openssl/err.h"
23 #include "openssl/obj_mac.h"
24 #include "openssl/objects.h"
25 #include "openssl/rsa.h"
26 #include "openssl/x509.h"
27 
28 namespace OHOS {
29 namespace Security {
30 namespace Verify {
31 using Pkcs7SignerInfoStack = STACK_OF(PKCS7_SIGNER_INFO);
32 using X509AttributeStack = STACK_OF(X509_ATTRIBUTE);
33 
34 const int32_t HapVerifyOpensslUtils::OPENSSL_PKCS7_VERIFY_SUCCESS = 1;
35 const int32_t HapVerifyOpensslUtils::OPENSSL_ERR_MESSAGE_MAX_LEN = 1024;
36 
37 /*
38  * OPENSSL_READ_DATA_MAX_TIME * OPENSSL_READ_DATA_LEN_EACH_TIME < 2GBytes.
39  * make the maximum size of data that can be read each time be 1 KBytes,
40  * so the maximum times of read data is 1024 * 1024 * 2 = 2097152;
41  */
42 const int32_t HapVerifyOpensslUtils::OPENSSL_READ_DATA_MAX_TIME = 2097152;
43 const int32_t HapVerifyOpensslUtils::OPENSSL_READ_DATA_LEN_EACH_TIME = 1024;
44 
45 /* Signature algorithm OID for extended PKCS7 */
46 const std::string HapVerifyOpensslUtils::PKCS7_EXT_SHAWITHRSA_PSS = "1.2.840.113549.1.1.10";
47 const int32_t HapVerifyOpensslUtils::MAX_OID_LENGTH = 128;
48 
ParsePkcs7Package(const unsigned char packageData[],uint32_t packageLen,Pkcs7Context & pkcs7Context)49 bool HapVerifyOpensslUtils::ParsePkcs7Package(const unsigned char packageData[],
50     uint32_t packageLen, Pkcs7Context& pkcs7Context)
51 {
52     if (packageData == nullptr || packageLen == 0) {
53         HAPVERIFY_LOG_ERROR("invalid input");
54         return false;
55     }
56 
57     pkcs7Context.p7 = d2i_PKCS7(nullptr, &packageData, packageLen);
58     if (!CheckPkcs7SignedDataIsValid(pkcs7Context.p7)) {
59         GetOpensslErrorMessage();
60         HAPVERIFY_LOG_ERROR("p7 is invalid");
61         return false;
62     }
63     if (!GetContentInfo(pkcs7Context.p7->d.sign->contents, pkcs7Context.content)) {
64         HAPVERIFY_LOG_ERROR("Get content from pkcs7 failed");
65         return false;
66     }
67     return true;
68 }
69 
GetCertChains(PKCS7 * p7,Pkcs7Context & pkcs7Context)70 bool HapVerifyOpensslUtils::GetCertChains(PKCS7* p7, Pkcs7Context& pkcs7Context)
71 {
72     if (!CheckPkcs7SignedDataIsValid(p7)) {
73         HAPVERIFY_LOG_ERROR("p7 is invalid");
74         return false;
75     }
76 
77     CertSign certVisitSign;
78     HapCertVerifyOpensslUtils::GenerateCertSignFromCertStack(p7->d.sign->cert, certVisitSign);
79 
80     Pkcs7SignerInfoStack* signerInfoStack = PKCS7_get_signer_info(p7);
81     if (signerInfoStack == nullptr) {
82         HAPVERIFY_LOG_ERROR("get signerInfoStack error");
83         GetOpensslErrorMessage();
84         return false;
85     }
86     int32_t signCount = sk_PKCS7_SIGNER_INFO_num(signerInfoStack);
87     if (signCount <= 0) {
88         HAPVERIFY_LOG_ERROR("can not find signinfo");
89         return false;
90     }
91 
92     for (int32_t i = 0; i < signCount; i++) {
93         /* get ith signInfo */
94         PKCS7_SIGNER_INFO* signInfo = sk_PKCS7_SIGNER_INFO_value(signerInfoStack, i);
95         if (signInfo == nullptr) {
96             HAPVERIFY_LOG_ERROR("signInfo %{public}dst is nullptr", i);
97             return false;
98         }
99         /* GET X509 certificate */
100         X509* cert = PKCS7_cert_from_signer_info(p7, signInfo);
101         if (cert == nullptr) {
102             HAPVERIFY_LOG_ERROR("get cert for %{public}dst signInfo failed", i);
103             return false;
104         }
105         CertChain certChain;
106         pkcs7Context.certChains.push_back(certChain);
107         pkcs7Context.certChains[i].push_back(X509_dup(cert));
108         HapCertVerifyOpensslUtils::ClearCertVisitSign(certVisitSign);
109         certVisitSign[cert] = true;
110         if (!VerifyCertChain(pkcs7Context.certChains[i], p7, signInfo, pkcs7Context, certVisitSign)) {
111             HAPVERIFY_LOG_ERROR("verify %{public}dst certchain failed", i);
112             return false;
113         }
114     }
115     return true;
116 }
117 
VerifyCertChain(CertChain & certsChain,PKCS7 * p7,PKCS7_SIGNER_INFO * signInfo,Pkcs7Context & pkcs7Context,CertSign & certVisitSign)118 bool HapVerifyOpensslUtils::VerifyCertChain(CertChain& certsChain, PKCS7* p7,
119     PKCS7_SIGNER_INFO* signInfo, Pkcs7Context& pkcs7Context, CertSign& certVisitSign)
120 {
121     if (!HapCertVerifyOpensslUtils::GetCertsChain(certsChain, certVisitSign, pkcs7Context)) {
122         HAPVERIFY_LOG_ERROR("get cert chain for signInfo failed");
123         return false;
124     }
125     ASN1_TYPE* signTime = PKCS7_get_signed_attribute(signInfo, NID_pkcs9_signingTime);
126     if (!HapCertVerifyOpensslUtils::VerifyCertChainPeriodOfValidity(certsChain, signTime)) {
127         HAPVERIFY_LOG_ERROR("VerifyCertChainPeriodOfValidity for signInfo failed");
128         return false;
129     }
130     if (!HapCertVerifyOpensslUtils::VerifyCrl(certsChain, p7->d.sign->crl, pkcs7Context)) {
131         HAPVERIFY_LOG_ERROR("VerifyCrl for signInfo failed");
132         return false;
133     }
134     return true;
135 }
136 
CheckPkcs7SignedDataIsValid(const PKCS7 * p7)137 bool HapVerifyOpensslUtils::CheckPkcs7SignedDataIsValid(const PKCS7* p7)
138 {
139     if (p7 == nullptr || !PKCS7_type_is_signed(p7) || p7->d.sign == nullptr) {
140         return false;
141     }
142     return true;
143 }
144 
VerifyPkcs7(Pkcs7Context & pkcs7Context)145 bool HapVerifyOpensslUtils::VerifyPkcs7(Pkcs7Context& pkcs7Context)
146 {
147     if (!CheckPkcs7SignedDataIsValid(pkcs7Context.p7)) {
148         HAPVERIFY_LOG_ERROR("p7 type is invalid signed_data_pkcs7");
149         return false;
150     }
151 
152     if (!VerifyPkcs7SignedData(pkcs7Context)) {
153         HAPVERIFY_LOG_ERROR("verify p7 error");
154         return false;
155     }
156     return true;
157 }
158 
VerifyPkcs7SignedData(Pkcs7Context & pkcs7Context)159 bool HapVerifyOpensslUtils::VerifyPkcs7SignedData(Pkcs7Context& pkcs7Context)
160 {
161     /* get signed data which was used to be signed */
162     BIO* p7Bio = PKCS7_dataDecode(pkcs7Context.p7, nullptr, nullptr, nullptr);
163     if (p7Bio == nullptr) {
164         HAPVERIFY_LOG_ERROR("get p7bio error");
165         GetOpensslErrorMessage();
166         return false;
167     }
168     char buf[OPENSSL_READ_DATA_LEN_EACH_TIME] = {0};
169     int32_t readLen = BIO_read(p7Bio, buf, sizeof(buf));
170     int32_t readTime = 0;
171     while ((readLen > 0) && (++readTime < OPENSSL_READ_DATA_MAX_TIME)) {
172         readLen = BIO_read(p7Bio, buf, sizeof(buf));
173     }
174     Pkcs7SignerInfoStack* signerInfoStack = PKCS7_get_signer_info(pkcs7Context.p7);
175     if (signerInfoStack == nullptr) {
176         HAPVERIFY_LOG_ERROR("get signerInfoStack error");
177         BIO_free_all(p7Bio);
178         GetOpensslErrorMessage();
179         return false;
180     }
181     /* get the num of signInfo */
182     int32_t signCount = sk_PKCS7_SIGNER_INFO_num(signerInfoStack);
183     if (signCount <= 0) {
184         HAPVERIFY_LOG_ERROR("can not find signinfo");
185         BIO_free_all(p7Bio);
186         return false;
187     }
188     for (int32_t i = 0; i < signCount; i++) {
189         if (!VerifySignInfo(signerInfoStack, p7Bio, i, pkcs7Context)) {
190             HAPVERIFY_LOG_ERROR("Verify %{public}dst signInfo failed", i);
191             BIO_free_all(p7Bio);
192             return false;
193         }
194     }
195     BIO_free_all(p7Bio);
196     return true;
197 }
198 
VerifySignInfo(STACK_OF (PKCS7_SIGNER_INFO)* signerInfoStack,BIO * p7Bio,int32_t signInfoNum,Pkcs7Context & pkcs7Context)199 bool HapVerifyOpensslUtils::VerifySignInfo(STACK_OF(PKCS7_SIGNER_INFO)* signerInfoStack,
200     BIO* p7Bio, int32_t signInfoNum, Pkcs7Context& pkcs7Context) {
201     if (signerInfoStack == nullptr || p7Bio == nullptr) {
202         HAPVERIFY_LOG_ERROR("invalid input");
203         return false;
204     }
205     /* get signInfo */
206     PKCS7_SIGNER_INFO* signInfo = sk_PKCS7_SIGNER_INFO_value(signerInfoStack, signInfoNum);
207     if (signInfo == nullptr) {
208         HAPVERIFY_LOG_ERROR("signInfo %{public}dst is nullptr", signInfoNum);
209         return false;
210     }
211     /* GET X509 certificate */
212     X509* cert = pkcs7Context.certChains[signInfoNum][0];
213     bool isShaWithRsaPss = IsEnablePss(signInfo);
214     if (isShaWithRsaPss) {
215         EVP_PKEY* pkey = X509_get0_pubkey(cert);
216         if (pkey == nullptr) {
217             HAPVERIFY_LOG_ERROR("signInfo %{public}dst X509_get_pubkey failed", signInfoNum);
218             return false;
219         }
220         HAPVERIFY_LOG_DEBUG("use RSA/pss");
221         if (!VerifyShaWithRsaPss(signInfo, p7Bio, pkey, isShaWithRsaPss)) {
222             HAPVERIFY_LOG_ERROR("VerifyShaWithRsaPss %{public}dst signInfo failed", signInfoNum);
223             return false;
224         }
225     } else {
226         if (PKCS7_signatureVerify(p7Bio, pkcs7Context.p7, signInfo, cert) <= 0) {
227             HAPVERIFY_LOG_ERROR("PKCS7_signatureVerify %{public}dst signInfo failed", signInfoNum);
228             GetOpensslErrorMessage();
229             return false;
230         }
231     }
232     return true;
233 }
234 
IsEnablePss(const PKCS7_SIGNER_INFO * signInfo)235 bool HapVerifyOpensslUtils::IsEnablePss(const PKCS7_SIGNER_INFO* signInfo)
236 {
237     char oId[MAX_OID_LENGTH];
238     if (signInfo->digest_enc_alg == nullptr) {
239         HAPVERIFY_LOG_ERROR("signInfo->digest_enc_alg is nullptr");
240         return false;
241     }
242     int32_t len = OBJ_obj2txt(oId, sizeof(oId), signInfo->digest_enc_alg->algorithm, 1);
243     if (len < 0 || len >= MAX_OID_LENGTH) {
244         HAPVERIFY_LOG_ERROR("Get length of oId failed");
245         return false;
246     }
247     return PKCS7_EXT_SHAWITHRSA_PSS.compare(0, PKCS7_EXT_SHAWITHRSA_PSS.size(), oId, len) == 0;
248 }
249 
VerifyShaWithRsaPss(const PKCS7_SIGNER_INFO * signInfo,BIO * p7Bio,EVP_PKEY * pkey,bool isPss)250 bool HapVerifyOpensslUtils::VerifyShaWithRsaPss(const PKCS7_SIGNER_INFO* signInfo,
251     BIO* p7Bio, EVP_PKEY* pkey, bool isPss)
252 {
253     if (signInfo->digest_alg == nullptr) {
254         HAPVERIFY_LOG_ERROR("signInfo->digest_alg is nullptr");
255         return false;
256     }
257     int32_t mdType = OBJ_obj2nid(signInfo->digest_alg->algorithm);
258     const EVP_MD_CTX* mdCtx = FindMdCtxInBio(p7Bio, mdType);
259     EVP_MD_CTX* mdCtxTmp = EVP_MD_CTX_new();
260     if (mdCtxTmp == nullptr) {
261         HAPVERIFY_LOG_ERROR("EVP_MD_CTX_new failed");
262         return false;
263     }
264     if (!EVP_MD_CTX_copy_ex(mdCtxTmp, mdCtx)) {
265         HAPVERIFY_LOG_ERROR("EVP_MD_CTX_copy_ex failed");
266         EVP_MD_CTX_free(mdCtxTmp);
267         return false;
268     }
269     if (!VerifyPkcs7AuthAttributes(signInfo, mdCtxTmp, mdType)) {
270         HAPVERIFY_LOG_ERROR("VerifyPkcs7AuthAttributes failed");
271         EVP_MD_CTX_free(mdCtxTmp);
272         return false;
273     }
274 
275     unsigned char digest[EVP_MAX_MD_SIZE];
276     uint32_t digestLen;
277     if (EVP_DigestFinal_ex(mdCtxTmp, digest, &digestLen) <= 0) {
278         HAPVERIFY_LOG_ERROR("Digest content failed");
279         GetOpensslErrorMessage();
280         EVP_MD_CTX_free(mdCtxTmp);
281         return false;
282     }
283     EVP_MD_CTX_free(mdCtxTmp);
284 
285     if (!VerifyShaWithRsaPss(signInfo, pkey, isPss, digest, digestLen)) {
286         HAPVERIFY_LOG_ERROR("VerifyShaWithRsaPss failed");
287         GetOpensslErrorMessage();
288         return false;
289     }
290     return true;
291 }
292 
FindMdCtxInBio(BIO * p7Bio,int32_t mdType)293 const EVP_MD_CTX* HapVerifyOpensslUtils::FindMdCtxInBio(BIO* p7Bio, int32_t mdType)
294 {
295     EVP_MD_CTX* mdCtx = nullptr;
296     while (p7Bio) {
297         BIO_get_md_ctx(p7Bio, &mdCtx);
298         if (mdCtx == nullptr) {
299             HAPVERIFY_LOG_ERROR("Get null from bio");
300             return nullptr;
301         }
302         if ((EVP_MD_CTX_type(mdCtx) == mdType) || (EVP_MD_pkey_type(EVP_MD_CTX_md(mdCtx)) == mdType)) {
303             break;
304         }
305         p7Bio = BIO_next(p7Bio);
306     }
307     return mdCtx;
308 }
309 
VerifyPkcs7AuthAttributes(const PKCS7_SIGNER_INFO * signInfo,EVP_MD_CTX * mdCtx,int32_t mdType)310 bool HapVerifyOpensslUtils::VerifyPkcs7AuthAttributes(
311     const PKCS7_SIGNER_INFO* signInfo, EVP_MD_CTX* mdCtx, int32_t mdType)
312 {
313     X509AttributeStack* authAttributes = signInfo->auth_attr;
314     if ((authAttributes != nullptr) && (sk_X509_ATTRIBUTE_num(authAttributes) != 0)) {
315         unsigned char digest[EVP_MAX_MD_SIZE];
316         uint32_t digestLen;
317         if (EVP_DigestFinal_ex(mdCtx, digest, &digestLen) <= 0) {
318             HAPVERIFY_LOG_ERROR("Digest content failed");
319             GetOpensslErrorMessage();
320             return false;
321         }
322         ASN1_OCTET_STRING* digestInAttribute = PKCS7_digest_from_attributes(authAttributes);
323         if (!AsnStringCmp(digestInAttribute, digest, static_cast<int>(digestLen))) {
324             HAPVERIFY_LOG_ERROR("AsnStringCmp failed");
325             return false;
326         }
327 
328         if (!EVP_VerifyInit_ex(mdCtx, EVP_get_digestbynid(mdType), nullptr)) {
329             HAPVERIFY_LOG_ERROR("EVP_VerifyInit_ex failed");
330             GetOpensslErrorMessage();
331             return false;
332         }
333 
334         unsigned char* attributesData = nullptr;
335         int32_t attributesLen = ASN1_item_i2d(reinterpret_cast<ASN1_VALUE*>(authAttributes), &attributesData,
336             ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
337         if (attributesLen <= 0 || attributesData == nullptr) {
338             HAPVERIFY_LOG_ERROR("ASN1_item_i2d failed");
339             GetOpensslErrorMessage();
340             return false;
341         }
342         if (!EVP_VerifyUpdate(mdCtx, attributesData, attributesLen)) {
343             HAPVERIFY_LOG_ERROR("EVP_VerifyUpdate failed");
344             GetOpensslErrorMessage();
345             OPENSSL_free(attributesData);
346             return false;
347         }
348         OPENSSL_free(attributesData);
349     }
350     return true;
351 }
352 
AsnStringCmp(const ASN1_OCTET_STRING * asnStr,const unsigned char data[],int32_t len)353 bool HapVerifyOpensslUtils::AsnStringCmp(const ASN1_OCTET_STRING* asnStr, const unsigned char data[], int32_t len)
354 {
355     if (asnStr == nullptr) {
356         HAPVERIFY_LOG_ERROR("asnStr is nullptr");
357         return false;
358     }
359     if (asnStr->data == nullptr) {
360         HAPVERIFY_LOG_ERROR("asnStr->data is nullptr");
361         return false;
362     }
363     if (data == nullptr) {
364         HAPVERIFY_LOG_ERROR("data is nullptr");
365         return false;
366     }
367     if (asnStr->length != len) {
368         HAPVERIFY_LOG_ERROR("asnStr->length: %{public}d is not equal to len: %{public}d", asnStr->length, len);
369         return false;
370     }
371     for (int32_t i = 0; i < len; i++) {
372         if (asnStr->data[i] != data[i]) {
373             HAPVERIFY_LOG_ERROR("%{public}dst data is not equal", i);
374             return false;
375         }
376     }
377     return true;
378 }
379 
VerifyShaWithRsaPss(const PKCS7_SIGNER_INFO * signInfo,EVP_PKEY * pkey,bool isPss,const unsigned char digest[],uint32_t digestLen)380 bool HapVerifyOpensslUtils::VerifyShaWithRsaPss(const PKCS7_SIGNER_INFO* signInfo, EVP_PKEY* pkey, bool isPss,
381     const unsigned char digest[], uint32_t digestLen)
382 {
383     EVP_PKEY_CTX* pkeyCtx = EVP_PKEY_CTX_new(pkey, nullptr);
384     if (pkeyCtx == nullptr) {
385         HAPVERIFY_LOG_ERROR("EVP_PKEY_CTX_new failed");
386         GetOpensslErrorMessage();
387         return false;
388     }
389     if (EVP_PKEY_verify_init(pkeyCtx) <= 0) {
390         HAPVERIFY_LOG_ERROR("EVP_PKEY_verify_init failed");
391         GetOpensslErrorMessage();
392         EVP_PKEY_CTX_free(pkeyCtx);
393         return false;
394     }
395     if (signInfo->digest_alg == nullptr || signInfo->enc_digest == nullptr) {
396         HAPVERIFY_LOG_ERROR("no digest_alg or enc_digest in signInfo");
397         EVP_PKEY_CTX_free(pkeyCtx);
398         return false;
399     }
400     int32_t mdType = OBJ_obj2nid(signInfo->digest_alg->algorithm);
401     if ((isPss && EVP_PKEY_CTX_set_rsa_padding(pkeyCtx, RSA_PKCS1_PSS_PADDING) <= 0) ||
402         (EVP_PKEY_CTX_set_signature_md(pkeyCtx, EVP_get_digestbynid(mdType)) <= 0)) {
403         HAPVERIFY_LOG_ERROR("set rsa_padding or signature_md failed");
404         GetOpensslErrorMessage();
405         EVP_PKEY_CTX_free(pkeyCtx);
406         return false;
407     }
408     if (EVP_PKEY_verify(pkeyCtx, signInfo->enc_digest->data, signInfo->enc_digest->length, digest, digestLen) <= 0) {
409         HAPVERIFY_LOG_ERROR("EVP_PKEY_verify failed");
410         GetOpensslErrorMessage();
411         EVP_PKEY_CTX_free(pkeyCtx);
412         return false;
413     }
414     EVP_PKEY_CTX_free(pkeyCtx);
415     return true;
416 }
417 
GetPublickeys(const CertChain & signCertChain,std::vector<std::string> & SignatureVec)418 bool HapVerifyOpensslUtils::GetPublickeys(const CertChain& signCertChain,
419     std::vector<std::string>& SignatureVec)
420 {
421     for (uint32_t i = 0; i < signCertChain.size(); i++) {
422         if (!GetPublickeyFromCertificate(signCertChain[i], SignatureVec)) {
423             HAPVERIFY_LOG_ERROR("%{public}ust Get Publickey failed", i);
424             return false;
425         }
426     }
427     return !SignatureVec.empty();
428 }
429 
GetSignatures(const CertChain & signCertChain,std::vector<std::string> & SignatureVec)430 bool HapVerifyOpensslUtils::GetSignatures(const CertChain& signCertChain,
431     std::vector<std::string>& SignatureVec)
432 {
433     for (uint32_t i = 0; i < signCertChain.size(); i++) {
434         if (!GetDerCert(signCertChain[i], SignatureVec)) {
435             HAPVERIFY_LOG_ERROR("%{public}ust GetDerCert failed", i);
436             return false;
437         }
438     }
439     return !SignatureVec.empty();
440 }
441 
GetDerCert(X509 * ptrX509,std::vector<std::string> & SignatureVec)442 bool HapVerifyOpensslUtils::GetDerCert(X509* ptrX509, std::vector<std::string>& SignatureVec)
443 {
444     if (ptrX509 == nullptr) {
445         return false;
446     }
447 
448     int32_t certLen = i2d_X509(ptrX509, nullptr);
449     if (certLen <= 0) {
450         HAPVERIFY_LOG_ERROR("certLen %{public}d, i2d_X509 failed", certLen);
451         GetOpensslErrorMessage();
452         return false;
453     }
454     std::unique_ptr<unsigned char[]> derCertificate = std::make_unique<unsigned char[]>(certLen);
455     int32_t base64CertLen = HapCertVerifyOpensslUtils::CalculateLenAfterBase64Encode(certLen);
456     std::unique_ptr<unsigned char[]> base64Certificate = std::make_unique<unsigned char[]>(base64CertLen);
457     unsigned char* derCertificateBackup = derCertificate.get();
458     if (i2d_X509(ptrX509, &derCertificateBackup) <= 0) {
459         HAPVERIFY_LOG_ERROR("i2d_X509 failed");
460         GetOpensslErrorMessage();
461         return false;
462     }
463 
464     /* base64 encode */
465     int32_t len = EVP_EncodeBlock(base64Certificate.get(), derCertificate.get(), certLen);
466     SignatureVec.emplace_back(std::string(reinterpret_cast<char*>(base64Certificate.get()), len));
467     return true;
468 }
469 
GetPublickeyFromCertificate(const X509 * ptrX509,std::vector<std::string> & publicKeyVec)470 bool HapVerifyOpensslUtils::GetPublickeyFromCertificate(const X509* ptrX509, std::vector<std::string>& publicKeyVec)
471 {
472     if (ptrX509 == nullptr) {
473         return false;
474     }
475 
476     std::string publicKey;
477     if (!HapCertVerifyOpensslUtils::GetPublickeyBase64(ptrX509, publicKey)) {
478         HAPVERIFY_LOG_ERROR("GetPublickeyBase64 Failed");
479         return false;
480     }
481     publicKeyVec.emplace_back(publicKey);
482     return true;
483 }
484 
GetContentInfo(const PKCS7 * p7ContentInfo,HapByteBuffer & content)485 bool HapVerifyOpensslUtils::GetContentInfo(const PKCS7* p7ContentInfo, HapByteBuffer& content)
486 {
487     if ((p7ContentInfo == nullptr) || !PKCS7_type_is_data(p7ContentInfo)) {
488         HAPVERIFY_LOG_ERROR("p7ContentInfo is invalid");
489         return false;
490     }
491 
492     ASN1_OCTET_STRING* strContentInfo = p7ContentInfo->d.data;
493     if (strContentInfo == nullptr) {
494         HAPVERIFY_LOG_ERROR("strContentInfo is invalid");
495         return false;
496     }
497 
498     int32_t strContentInfoLen = strContentInfo->length;
499     unsigned char* strContentInfoData = strContentInfo->data;
500     if (strContentInfoData == nullptr || strContentInfoLen <= 0) {
501         HAPVERIFY_LOG_ERROR("ASN1_OCTET_STRING is invalid");
502         return false;
503     }
504 
505     content.SetCapacity(strContentInfoLen);
506     content.PutData(0, reinterpret_cast<char*>(strContentInfoData), strContentInfoLen);
507     HAPVERIFY_LOG_DEBUG("strContentInfoLen: %{public}d", strContentInfoLen);
508     return true;
509 }
510 
GetDigestAlgorithmOutputSizeBytes(int32_t nId)511 int32_t HapVerifyOpensslUtils::GetDigestAlgorithmOutputSizeBytes(int32_t nId)
512 {
513     return EVP_MD_size(EVP_get_digestbynid(nId));
514 }
515 
CheckDigestParameter(const DigestParameter & digestParameter)516 bool HapVerifyOpensslUtils::CheckDigestParameter(const DigestParameter& digestParameter)
517 {
518     if (digestParameter.md == nullptr) {
519         HAPVERIFY_LOG_ERROR("md is nullptr");
520         return false;
521     }
522     if (digestParameter.ptrCtx == nullptr) {
523         HAPVERIFY_LOG_ERROR("ptrCtx is nullptr");
524         return false;
525     }
526     return true;
527 }
528 
DigestInit(const DigestParameter & digestParameter)529 bool HapVerifyOpensslUtils::DigestInit(const DigestParameter& digestParameter)
530 {
531     if (!CheckDigestParameter(digestParameter)) {
532         return false;
533     }
534     if (EVP_DigestInit(digestParameter.ptrCtx, digestParameter.md) <= 0) {
535         GetOpensslErrorMessage();
536         HAPVERIFY_LOG_ERROR("EVP_DigestInit failed");
537         return false;
538     }
539     return true;
540 }
541 
542 /* the caller must ensure that EVP_DigestInit was called before calling this function */
DigestUpdate(const DigestParameter & digestParameter,const unsigned char content[],int32_t len)543 bool HapVerifyOpensslUtils::DigestUpdate(const DigestParameter& digestParameter,
544     const unsigned char content[], int32_t len)
545 {
546     if (content == nullptr) {
547         HAPVERIFY_LOG_ERROR("content is nullptr");
548         return false;
549     }
550     if (!CheckDigestParameter(digestParameter)) {
551         return false;
552     }
553     if (EVP_DigestUpdate(digestParameter.ptrCtx, content, len) <= 0) {
554         GetOpensslErrorMessage();
555         HAPVERIFY_LOG_ERROR("EVP_DigestUpdate chunk failed");
556         return false;
557     }
558     return true;
559 }
560 
GetDigest(const DigestParameter & digestParameter,unsigned char (& out)[EVP_MAX_MD_SIZE])561 int32_t HapVerifyOpensslUtils::GetDigest(const DigestParameter& digestParameter, unsigned char (&out)[EVP_MAX_MD_SIZE])
562 {
563     uint32_t outLen = 0;
564     if (!CheckDigestParameter(digestParameter)) {
565         return outLen;
566     }
567     if (EVP_DigestFinal(digestParameter.ptrCtx, out, &outLen) <= 0) {
568         GetOpensslErrorMessage();
569         HAPVERIFY_LOG_ERROR("EVP_DigestFinal failed");
570         outLen = 0;
571     }
572     return outLen;
573 }
574 
GetDigest(const HapByteBuffer & chunk,const std::vector<OptionalBlock> & optionalBlocks,const DigestParameter & digestParameter,unsigned char (& out)[EVP_MAX_MD_SIZE])575 int32_t HapVerifyOpensslUtils::GetDigest(const HapByteBuffer& chunk, const std::vector<OptionalBlock>& optionalBlocks,
576     const DigestParameter& digestParameter, unsigned char (&out)[EVP_MAX_MD_SIZE])
577 {
578     int32_t chunkLen = chunk.Remaining();
579     uint32_t outLen = 0;
580     if (digestParameter.md == nullptr) {
581         HAPVERIFY_LOG_ERROR("md is nullprt");
582         return outLen;
583     }
584     if (digestParameter.ptrCtx == nullptr) {
585         HAPVERIFY_LOG_ERROR("ptrCtx is nullprt");
586         return outLen;
587     }
588 
589     if (EVP_DigestInit(digestParameter.ptrCtx, digestParameter.md) <= 0) {
590         GetOpensslErrorMessage();
591         HAPVERIFY_LOG_ERROR("EVP_DigestInit failed");
592         return outLen;
593     }
594 
595     if (EVP_DigestUpdate(digestParameter.ptrCtx, chunk.GetBufferPtr(), chunkLen) <= 0) {
596         GetOpensslErrorMessage();
597         HAPVERIFY_LOG_ERROR("EVP_DigestUpdate chunk failed");
598         return outLen;
599     }
600     for (int32_t i = 0; i < static_cast<int>(optionalBlocks.size()); i++) {
601         chunkLen = optionalBlocks[i].optionalBlockValue.GetCapacity();
602         if (EVP_DigestUpdate(digestParameter.ptrCtx, optionalBlocks[i].optionalBlockValue.GetBufferPtr(),
603             chunkLen) <= 0) {
604             GetOpensslErrorMessage();
605             HAPVERIFY_LOG_ERROR("EVP_DigestUpdate %{public}dst optional block failed", i);
606             return outLen;
607         }
608     }
609 
610     if (EVP_DigestFinal(digestParameter.ptrCtx, out, &outLen) <= 0) {
611         GetOpensslErrorMessage();
612         HAPVERIFY_LOG_ERROR("EVP_DigestFinal failed");
613         outLen = 0;
614     }
615     return outLen;
616 }
617 
GetOpensslErrorMessage()618 void HapVerifyOpensslUtils::GetOpensslErrorMessage()
619 {
620     unsigned long retOpenssl;
621     char errOpenssl[OPENSSL_ERR_MESSAGE_MAX_LEN];
622     while ((retOpenssl = ERR_get_error()) != 0) {
623         ERR_error_string(retOpenssl, errOpenssl);
624         HAPVERIFY_LOG_ERROR("openssl err: %{public}lu, message: %{public}s", retOpenssl, errOpenssl);
625     }
626 }
627 
GetDigestAlgorithmId(int32_t signAlgorithm)628 int32_t HapVerifyOpensslUtils::GetDigestAlgorithmId(int32_t signAlgorithm)
629 {
630     switch (signAlgorithm) {
631         case ALGORITHM_SHA256_WITH_RSA_PSS:
632         case ALGORITHM_SHA256_WITH_RSA_PKCS1_V1_5:
633         case ALGORITHM_SHA256_WITH_ECDSA:
634         case ALGORITHM_SHA256_WITH_DSA:
635             return NID_sha256;
636         case ALGORITHM_SHA384_WITH_RSA_PSS:
637         case ALGORITHM_SHA384_WITH_RSA_PKCS1_V1_5:
638         case ALGORITHM_SHA384_WITH_ECDSA:
639         case ALGORITHM_SHA384_WITH_DSA:
640             return NID_sha384;
641         case ALGORITHM_SHA512_WITH_RSA_PSS:
642         case ALGORITHM_SHA512_WITH_RSA_PKCS1_V1_5:
643         case ALGORITHM_SHA512_WITH_ECDSA:
644         case ALGORITHM_SHA512_WITH_DSA:
645             return NID_sha512;
646         default:
647             HAPVERIFY_LOG_ERROR("signAlgorithm: %{public}d error", signAlgorithm);
648             return NID_undef;
649     }
650 }
651 } // namespace Verify
652 } // namespace Security
653 } // namespace OHOS
654