1/*
2 * Copyright (c) 2024-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#include <cassert>
16#include <string>
17#include <unordered_map>
18#include <openssl/x509.h>
19#include <openssl/x509v3.h>
20#include <openssl/conf.h>
21
22#include "cert_tools.h"
23#include "openssl/ec.h"
24#include "openssl/obj_mac.h"
25#include "openssl/asn1.h"
26#include "signature_tools_log.h"
27#include "constant.h"
28
29namespace OHOS {
30namespace SignatureTools {
31
32static std::unordered_map<std::string, long> externDic{
33    {"digitalSignature", X509v3_KU_DIGITAL_SIGNATURE},
34    {"nonRepudiation", X509v3_KU_NON_REPUDIATION},
35    {"keyEncipherment", X509v3_KU_KEY_ENCIPHERMENT},
36    {"dataEncipherment", X509v3_KU_DATA_ENCIPHERMENT},
37    {"keyAgreement", X509v3_KU_KEY_AGREEMENT},
38    {"certificateSignature", X509v3_KU_KEY_CERT_SIGN},
39    {"crlSignature", X509v3_KU_CRL_SIGN},
40    {"encipherOnly", X509v3_KU_ENCIPHER_ONLY},
41    {"decipherOnly", X509v3_KU_DECIPHER_ONLY},
42
43};
44
45static std::unordered_map<std::string, std::string> externKey{
46    {"serverAuthentication", "1.3.6.1.5.5.7.3.1"},
47    {"clientAuthentication",  "1.3.6.1.5.5.7.3.2"},
48    {"codeSignature",  "1.3.6.1.5.5.7.3.3"},
49    {"emailProtection",  "1.3.6.1.5.5.7.3.4"},
50    {"smartCardLogin",  "1.3.6.1.5.5.7.3.5"},
51    {"timestamp",  "1.3.6.1.5.5.7.3.8"},
52    {"ocspSignature",  "1.3.6.1.5.5.7.3.9"},
53
54};
55
56bool CertTools::SaveCertTofile(const std::string& filename, X509* cert)
57{
58    BIO* certBio = BIO_new_file(filename.data(), "w");
59    if (!certBio) {
60        VerifyHapOpensslUtils::GetOpensslErrorMessage();
61        SIGNATURE_TOOLS_LOGE("BIO_new failed");
62        return false;
63    }
64
65    if (PEM_write_bio_X509(certBio, cert) < 0) {
66        VerifyHapOpensslUtils::GetOpensslErrorMessage();
67        SIGNATURE_TOOLS_LOGE("PEM_write_bio_X509 failed");
68        BIO_free(certBio);
69        return false;
70    }
71    BIO_free(certBio);
72    return true;
73}
74
75static bool UpdateConstraint(Options* options)
76{
77    if (options->count(Options::BASIC_CONSTRAINTS)) {
78        if (!CertTools::String2Bool(options, Options::BASIC_CONSTRAINTS)) {
79            return false;
80        }
81    } else {
82        (*options)[Options::BASIC_CONSTRAINTS] = DEFAULT_BASIC_CONSTRAINTS;
83    }
84
85    if (options->count(Options::BASIC_CONSTRAINTS_CRITICAL)) {
86        if (!CertTools::String2Bool(options, Options::BASIC_CONSTRAINTS_CRITICAL)) {
87            return false;
88        }
89    } else {
90        (*options)[Options::BASIC_CONSTRAINTS_CRITICAL] = DEFAULT_BASIC_CONSTRAINTS_CRITICAL;
91    }
92
93    if (options->count(Options::BASIC_CONSTRAINTS_CA)) {
94        if (!CertTools::String2Bool(options, Options::BASIC_CONSTRAINTS_CA)) {
95            return false;
96        }
97    } else {
98        (*options)[Options::BASIC_CONSTRAINTS_CA] = DEFAULT_BASIC_CONSTRAINTS_CA;
99    }
100    return true;
101}
102
103bool CertTools::SetBisicConstraints(Options* options, X509* cert)
104{
105    if (!UpdateConstraint(options)) {
106        return false;
107    }
108
109    bool basicCon = options->GetBool(Options::BASIC_CONSTRAINTS);
110    if (basicCon) {
111        bool basicConstraintsCritical = options->GetBool(Options::BASIC_CONSTRAINTS_CRITICAL);
112        int critial = basicConstraintsCritical ? 1 : 0;
113        bool basicConstraintsCa = options->GetBool(Options::BASIC_CONSTRAINTS_CA);
114        std::string  ContainCa = basicConstraintsCa ? "CA:TRUE" : "CA:FALSE";
115        std::string constraints = ContainCa + "," + "pathlen:" +
116            std::to_string(options->GetInt(Options::BASIC_CONSTRAINTS_PATH_LEN));
117        X509V3_CTX ctx;
118        X509V3_set_ctx_nodb(&ctx);
119
120        X509_EXTENSION* ext = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, constraints.c_str());
121        if (!X509_EXTENSION_set_critical(ext, critial)) {
122            SIGNATURE_TOOLS_LOGE("failed to set  critical for extKeyUsage ");
123            X509_EXTENSION_free(ext);
124            VerifyHapOpensslUtils::GetOpensslErrorMessage();
125            return false;
126        }
127        if (!X509_add_ext(cert, ext, -1)) {
128            SIGNATURE_TOOLS_LOGE("X509_add_ext failed");
129            X509_EXTENSION_free(ext);
130            VerifyHapOpensslUtils::GetOpensslErrorMessage();
131            return false;
132        }
133        X509_EXTENSION_free(ext);
134    }
135
136    return true;
137}
138
139bool CertTools::SetBisicConstraintsPathLen(Options* options, X509* cert)
140{
141    std::string setOptions = "CA:TRUE, pathlen:" +
142        std::to_string(options->GetInt(Options::BASIC_CONSTRAINTS_PATH_LEN));
143    X509V3_CTX ctx;
144    X509V3_set_ctx_nodb(&ctx);
145    X509_EXTENSION* ext = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, setOptions.c_str());
146    if (!X509_EXTENSION_set_critical(ext, 1)) {
147        SIGNATURE_TOOLS_LOGE("failed to set  critical for extKeyUsage ");
148        X509_EXTENSION_free(ext);
149        VerifyHapOpensslUtils::GetOpensslErrorMessage();
150        return false;
151    }
152    if (!X509_add_ext(cert, ext, -1)) {
153        SIGNATURE_TOOLS_LOGE("X509_add_ext failed\n");
154        X509_EXTENSION_free(ext);
155        VerifyHapOpensslUtils::GetOpensslErrorMessage();
156        return false;
157    }
158    X509_EXTENSION_free(ext);
159    return true;
160}
161
162bool CertTools::SignForSubCert(X509* cert, X509_REQ* subcsr, X509_REQ* rootcsr, EVP_PKEY* caPrikey, Options* options)
163{
164    bool result = false;
165    std::string signAlg = options->GetString(Options::SIGN_ALG);
166    EVP_PKEY* pubKey = X509_REQ_get_pubkey(subcsr);
167    X509_NAME* issuerName = X509_REQ_get_subject_name(rootcsr);
168    X509_NAME* subjectName = X509_REQ_get_subject_name(subcsr);
169    if (pubKey == NULL) {
170        SIGNATURE_TOOLS_LOGE("X509_REQ_get_pubkey failed");
171        goto err;
172    }
173    if (caPrikey == nullptr || rootcsr == nullptr || subcsr == nullptr) {
174        SIGNATURE_TOOLS_LOGE("Sign failed because of caPrikey, roocsr or subcsr is nullptr");
175        goto err;
176    }
177    result = (!X509_set_pubkey(cert, pubKey));
178    if (result) {
179        SIGNATURE_TOOLS_LOGE("X509_set_pubkey failed");
180        goto err;
181    }
182    result = (!X509_set_issuer_name(cert, issuerName));
183    if (result) {
184        SIGNATURE_TOOLS_LOGE("X509_set_issuer_name failed");
185        goto err;
186    }
187    result = (!X509_set_subject_name(cert, subjectName));
188    if (result) {
189        SIGNATURE_TOOLS_LOGE("X509_set_subject_name failed");
190        goto err;
191    }
192    result = (!SignCert(cert, caPrikey, signAlg));
193    if (result) {
194        goto err;
195    }
196    EVP_PKEY_free(pubKey);
197    return true;
198err:
199    EVP_PKEY_free(pubKey);
200    X509_NAME_free(issuerName);
201    X509_NAME_free(subjectName);
202    VerifyHapOpensslUtils::GetOpensslErrorMessage();
203    return false;
204}
205
206X509* CertTools::SignCsrGenerateCert(X509_REQ* rootcsr, X509_REQ* subcsr,
207                                     EVP_PKEY* keyPair, Options* options)
208{
209    bool result = false;
210    X509* cert = X509_new();
211    int validity = options->GetInt(Options::VALIDITY);
212    result = (!SetCertVersion(cert, DEFAULT_CERT_VERSION) ||
213              !SetCertSerialNum(cert));
214    if (result) {
215        goto err;
216    }
217    result = SetCertValidity(cert, validity);
218    if (!result) {
219        goto err;
220    }
221    result = (!SetBisicConstraintsPathLen(options, cert) ||
222              !SetKeyIdentifierExt(cert) ||
223              !SetAuthorizeKeyIdentifierExt(cert)||
224              !SetKeyUsage(cert, options) ||
225              !SignForSubCert(cert, subcsr, rootcsr, keyPair, options));
226    if (result) {
227        goto err;
228    }
229    return  cert;
230err:
231    X509_free(cert);
232    return nullptr;
233}
234
235bool CertTools::SetSubjectForCert(X509_REQ* certReq, X509* cert)
236{
237    if (certReq == nullptr) {
238        SIGNATURE_TOOLS_LOGE("set subjcet failed because of certReq is nullptr");
239        goto err;
240    }
241
242    if (X509_set_subject_name(cert, X509_REQ_get_subject_name(certReq)) != 1) {
243        SIGNATURE_TOOLS_LOGE("X509_set_issuer_name failed");
244        goto err;
245    }
246
247    if (X509_set_issuer_name(cert, X509_REQ_get_subject_name(certReq)) != 1) {
248        SIGNATURE_TOOLS_LOGE("X509_set_issuer_name failed");
249        goto err;
250    }
251    return true;
252err:
253    VerifyHapOpensslUtils::GetOpensslErrorMessage();
254    return false;
255}
256
257X509* CertTools::GenerateRootCertificate(EVP_PKEY* keyPair, X509_REQ* certReq, Options* options)
258{
259    bool result = false;
260    X509* cert = X509_new();
261    int validity = options->GetInt(Options::VALIDITY);
262    std::string signAlg = options->GetString(Options::SIGN_ALG);
263    result = (!SetCertVersion(cert, DEFAULT_CERT_VERSION) ||
264              !SetCertSerialNum(cert));
265    if (result) {
266        goto err;
267    }
268    if (!SetCertValidityStartAndEnd(cert, DEFAULT_START_VALIDITY, validity)) {
269        goto err;
270    }
271    result = (!SetBisicConstraintsPathLen(options, cert) ||
272              !SetSubjectForCert(certReq, cert) ||
273              !SetCertPublickKey(cert, certReq) ||
274              !SetKeyIdentifierExt(cert) ||
275              !SetKeyUsage(cert, options));
276    if (result) {
277        goto err;
278    }
279    result = (!SignCert(cert, keyPair, signAlg));
280    if (result) {
281        goto err;
282    }
283    return cert;
284err:
285    X509_free(cert);
286    return nullptr;
287}
288
289X509* CertTools::GenerateSubCert(EVP_PKEY* keyPair, X509_REQ* rootcsr, Options* options)
290{
291    std::unique_ptr<LocalizationAdapter> adapter = std::make_unique< LocalizationAdapter>(options);
292    EVP_PKEY* subKey = nullptr;
293    X509_REQ* subcsr = nullptr;
294    X509* subCert = nullptr;
295    subKey = adapter->GetAliasKey(false);
296    if (subKey == nullptr) {
297        SIGNATURE_TOOLS_LOGE("failed to get the keypair");
298        goto err;
299    }
300    subcsr = CertTools::GenerateCsr(subKey, options->GetString(Options::SIGN_ALG),
301                                    options->GetString(Options::SUBJECT));
302    if (subcsr == nullptr) {
303        SIGNATURE_TOOLS_LOGE("failed to generate csr");
304        goto err;
305    }
306    subCert = SignCsrGenerateCert(rootcsr, subcsr, keyPair, options);
307    if (subCert == nullptr) {
308        SIGNATURE_TOOLS_LOGE("failed to generate the subCert");
309        goto err;
310    }
311    EVP_PKEY_free(subKey);
312    X509_REQ_free(subcsr);
313    return subCert;
314err:
315    EVP_PKEY_free(subKey);
316    X509_REQ_free(subcsr);
317    return nullptr;
318}
319
320bool CertTools::SetKeyUsage(X509* cert, Options* options)
321{
322    std::string keyUsage = options->GetString(Options::KEY_USAGE);
323    ASN1_INTEGER* keyUsageInt = ASN1_INTEGER_new();
324    long key = 0;
325    if (keyUsage.empty()) {
326        key = X509v3_KU_KEY_CERT_SIGN | X509v3_KU_CRL_SIGN;
327        if (keyUsageInt == NULL || !ASN1_INTEGER_set(keyUsageInt, key)) {
328            SIGNATURE_TOOLS_LOGE("failed to set asn1_integer");
329            ASN1_INTEGER_free(keyUsageInt);
330            return false;
331        }
332        if (!X509_add1_ext_i2d(cert, NID_key_usage, keyUsageInt, 0, X509V3_ADD_DEFAULT)) {
333            SIGNATURE_TOOLS_LOGE("failed to add ext");
334            ASN1_INTEGER_free(keyUsageInt);
335            return false;
336        }
337    } else {
338        bool keyUsageCritical = options->GetBool(Options::KEY_USAGE_CRITICAL);
339        int crit = keyUsageCritical > 0 ? 1 : 0;
340        std::vector<std::string> vecs = StringUtils::SplitString(keyUsage.c_str(), ',');
341        for (auto &vec : vecs) {
342            key |= externDic[vec];
343        }
344        if (keyUsageInt == NULL || !ASN1_INTEGER_set(keyUsageInt, key)) {
345            SIGNATURE_TOOLS_LOGE("failed to set asn1_integer");
346            ASN1_INTEGER_free(keyUsageInt);
347            return false;
348        }
349        if (!X509_add1_ext_i2d(cert, NID_key_usage, keyUsageInt, crit, X509V3_ADD_DEFAULT)) {
350            SIGNATURE_TOOLS_LOGE("failed to add ext");
351            ASN1_INTEGER_free(keyUsageInt);
352            return false;
353        }
354    }
355    ASN1_INTEGER_free(keyUsageInt);
356    return true;
357}
358
359bool CertTools::SetkeyUsageExt(X509* cert, Options* options)
360{
361    X509_EXTENSION* ext = nullptr;
362    bool keyUsageCritical = options->GetBool(Options::KEY_USAGE_CRITICAL);
363    int crit = keyUsageCritical  ? 1 : 0;
364    if (!options->GetString(Options::EXT_KEY_USAGE).empty()) {
365        ext = X509V3_EXT_conf(NULL, NULL, NID_EXT_KEYUSAGE_CONST.c_str(),
366                              externKey[options->GetString(Options::EXT_KEY_USAGE)].c_str());
367        if (!X509_EXTENSION_set_critical(ext, crit)) {
368            SIGNATURE_TOOLS_LOGE("failed to set  critical for extKeyUsage ");
369            X509_EXTENSION_free(ext);
370            return false;
371        }
372        if (!X509_add_ext(cert, ext, -1)) {
373            SIGNATURE_TOOLS_LOGE("failed to add extension");
374            X509_EXTENSION_free(ext);
375            return false;
376        }
377    }
378    X509_EXTENSION_free(ext);
379    return true;
380}
381
382bool CertTools::SetExpandedInformation(X509* cert, Options* options)
383{
384    bool result = false;
385    result = (!SetKeyUsage(cert, options) ||
386              !SetkeyUsageExt(cert, options));
387    if (result) {
388        SIGNATURE_TOOLS_LOGE("Failed to set expanded information ");
389        return false;
390    }
391    return true;
392}
393
394bool CertTools::SetPubkeyAndSignCert(X509* cert, X509_REQ* issuercsr,
395                                     X509_REQ* certReq, EVP_PKEY* keyPair, Options* options)
396{
397    if (!X509_set_issuer_name(cert, X509_REQ_get_subject_name(issuercsr))) {
398        SIGNATURE_TOOLS_LOGE("X509_set_issuer_name failed");
399        goto err;
400    }
401
402    if (!X509_set_subject_name(cert, X509_REQ_get_subject_name(certReq))) {
403        SIGNATURE_TOOLS_LOGE("X509_set_subject_name failed");
404        goto err;
405    }
406    if ((options->GetString(Options::SIGN_ALG)) == SIGN_ALG_SHA256) {
407        if (!X509_sign(cert, keyPair, EVP_sha256())) {
408            SIGNATURE_TOOLS_LOGE("X509_sign failed");
409            goto err;
410        }
411    } else {
412        if (!X509_sign(cert, keyPair, EVP_sha384())) {
413            SIGNATURE_TOOLS_LOGE("X509_sign failed");
414            goto err;
415        }
416    }
417    return true;
418err:
419    VerifyHapOpensslUtils::GetOpensslErrorMessage();
420    return false;
421}
422
423X509* CertTools::GenerateCert(EVP_PKEY* keyPair, X509_REQ* certReq, Options* options)
424{
425    int validity = 0;
426    bool result = false;
427    X509_REQ* issuercsr = CertTools::GenerateCsr(keyPair, options->GetString(Options::SIGN_ALG),
428                                                 options->GetString(Options::ISSUER));
429    if (issuercsr == nullptr) {
430        SIGNATURE_TOOLS_LOGE("failed to generate the issuercsr");
431        return nullptr;
432    }
433
434    X509* cert = X509_new();
435    result = (!SetCertVersion(cert, DEFAULT_CERT_VERSION) ||
436              !SetCertSerialNum(cert) ||
437              !SetKeyIdentifierExt(cert));
438    if (result) {
439        goto err;
440    }
441    validity = options->GetInt(Options::VALIDITY);
442    if (!SetCertValidityStartAndEnd(cert, DEFAULT_START_VALIDITY, validity)) {
443        goto err;
444    }
445
446    result = (!SetBisicConstraints(options, cert) ||
447              !SetCertPublickKey(cert, certReq) ||
448              !SetExpandedInformation(cert, options) ||
449              !SetPubkeyAndSignCert(cert, issuercsr, certReq, keyPair, options));
450    if (result) {
451        goto err;
452    }
453    X509_REQ_free(issuercsr);
454    return cert;
455err:
456    X509_free(cert);
457    X509_REQ_free(issuercsr);
458    return nullptr;
459}
460
461X509_REQ* CertTools::GenerateCsr(EVP_PKEY* evpPkey, std::string signAlgorithm, std::string subject)
462{
463    X509_NAME* name = nullptr;
464    X509_REQ* req = X509_REQ_new();
465
466    if (!X509_REQ_set_pubkey(req, evpPkey)) {
467        SIGNATURE_TOOLS_LOGE("X509_REQ_set_pubkey failed");
468        goto err;
469    }
470
471    name = BuildDN(subject, req);
472    if (!name) {
473        SIGNATURE_TOOLS_LOGE("failed to add subject into cert");
474        goto err;
475    }
476
477    if (signAlgorithm == SIGN_ALG_SHA256) {
478        if (!X509_REQ_sign(req, evpPkey, EVP_sha256())) {
479            SIGNATURE_TOOLS_LOGE("X509_REQ_sign failed");
480            goto err;
481        }
482    } else if (signAlgorithm == SIGN_ALG_SHA384) {
483        if (!X509_REQ_sign(req, evpPkey, EVP_sha384())) {
484            SIGNATURE_TOOLS_LOGE("X509_REQ_sign failed");
485            goto err;
486        }
487    } else {
488        PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR,
489                            "Sign algorithm format error! Please check again.");
490        goto err;
491    }
492    return req;
493err:
494    VerifyHapOpensslUtils::GetOpensslErrorMessage();
495    X509_REQ_free(req);
496    return nullptr;
497}
498
499std::string CertTools::CsrToString(X509_REQ* csr)
500{
501    BIO* csrBio = BIO_new(BIO_s_mem());
502    if (!csrBio) {
503        return "";
504    }
505    if (!PEM_write_bio_X509_REQ(csrBio, csr)) {
506        VerifyHapOpensslUtils::GetOpensslErrorMessage();
507        SIGNATURE_TOOLS_LOGE("PEM_write_bio_X509_REQ error");
508        BIO_free(csrBio);
509        return "";
510    }
511    BUF_MEM* data = nullptr;
512    BIO_get_mem_ptr(csrBio, &data);
513    if (!data) {
514        BIO_free(csrBio);
515        return "";
516    }
517    if (!data->data) {
518        BIO_free(csrBio);
519        return "";
520    }
521    std::string csrStr(data->data, data->length);
522    BIO_free(csrBio);
523    return csrStr;
524}
525
526X509* CertTools::ReadfileToX509(const std::string& filename)
527{
528    BIO* certBio = BIO_new_file(filename.c_str(), "rb");
529    if (!certBio) {
530        VerifyHapOpensslUtils::GetOpensslErrorMessage();
531        SIGNATURE_TOOLS_LOGE("BIO_new_file failed");
532        BIO_free(certBio);
533        return nullptr;
534    }
535
536    X509* cert = X509_new();
537    if (!PEM_read_bio_X509(certBio, &cert, NULL, NULL)) {
538        VerifyHapOpensslUtils::GetOpensslErrorMessage();
539        SIGNATURE_TOOLS_LOGE("PEM_read_bio_X509 failed");
540        X509_free(cert);
541        BIO_free(certBio);
542        return nullptr;
543    }
544    BIO_free(certBio);
545
546    return cert;
547}
548
549bool CertTools::SetCertVersion(X509* cert, int versionNum)
550{
551    if (!X509_set_version(cert, versionNum)) {
552        VerifyHapOpensslUtils::GetOpensslErrorMessage();
553        SIGNATURE_TOOLS_LOGE("set x509 cert version failed");
554        return false;
555    }
556    return true;
557}
558
559bool CertTools::SetCertSerialNum(X509* cert)
560{
561    BN_CTX* ctx = BN_CTX_new();
562    BIGNUM* bignum = BN_new();
563    uint8_t serialNumberValue[RANDOM_SERIAL_NUMBER_LENGTH] = {0};
564    if (!SerialNumberBuilder(serialNumberValue, sizeof(serialNumberValue))) {
565        goto err;
566    }
567    if (!BN_bin2bn(serialNumberValue, sizeof(serialNumberValue), bignum)) {
568        VerifyHapOpensslUtils::GetOpensslErrorMessage();
569        goto err;
570    }
571    if (BN_is_negative(bignum)) {
572        BN_set_negative(bignum, 0); // Replace negative numbers with positive ones
573    }
574    if (!BN_to_ASN1_INTEGER(bignum, X509_get_serialNumber(cert))) {
575        VerifyHapOpensslUtils::GetOpensslErrorMessage();
576        goto err;
577    }
578    BN_CTX_free(ctx);
579    BN_free(bignum);
580    return true;
581err:
582    SIGNATURE_TOOLS_LOGE("set x509 cert serial number failed");
583    BN_CTX_free(ctx);
584    BN_free(bignum);
585    return false;
586}
587
588bool CertTools::SetCertIssuerName(X509* cert, X509_NAME* issuer)
589{
590    if (!X509_set_issuer_name(cert, issuer)) {
591        VerifyHapOpensslUtils::GetOpensslErrorMessage();
592        SIGNATURE_TOOLS_LOGE("set x509 cert issuer name failed");
593        return false;
594    }
595    return true;
596}
597
598bool CertTools::SetCertSubjectName(X509* cert, X509_REQ* subjectCsr)
599{
600    X509_NAME* subject = nullptr;
601    if (!(subject = X509_REQ_get_subject_name(subjectCsr))) {
602        VerifyHapOpensslUtils::GetOpensslErrorMessage();
603        SIGNATURE_TOOLS_LOGE("get X509 cert subject name failed");
604        return false;
605    }
606    if (!X509_set_subject_name(cert, subject)) {
607        VerifyHapOpensslUtils::GetOpensslErrorMessage();
608        SIGNATURE_TOOLS_LOGE("set X509 cert subject name failed");
609        return false;
610    }
611    return true;
612}
613
614bool CertTools::SetCertValidityStartAndEnd(X509* cert, long vilidityStart, long vilidityEnd)
615{
616    if (!X509_gmtime_adj(X509_getm_notBefore(cert), vilidityStart)) {
617        VerifyHapOpensslUtils::GetOpensslErrorMessage();
618        SIGNATURE_TOOLS_LOGE("set cert vilidity start time failed");
619        return false;
620    }
621    if (!X509_gmtime_adj(X509_getm_notAfter(cert), vilidityEnd)) {
622        VerifyHapOpensslUtils::GetOpensslErrorMessage();
623        SIGNATURE_TOOLS_LOGE("set cert vilidity end time failed");
624        return false;
625    }
626    return true;
627}
628
629bool CertTools::SetCertPublickKey(X509* cert, X509_REQ* subjectCsr)
630{
631    EVP_PKEY* publicKey = X509_REQ_get_pubkey(subjectCsr);
632    if (!publicKey) {
633        VerifyHapOpensslUtils::GetOpensslErrorMessage();
634        SIGNATURE_TOOLS_LOGE("get the pubkey from csr failed");
635        return false;
636    }
637    if (!X509_set_pubkey(cert, publicKey)) {
638        VerifyHapOpensslUtils::GetOpensslErrorMessage();
639        EVP_PKEY_free(publicKey);
640        SIGNATURE_TOOLS_LOGE("set public key to cert failed");
641        return false;
642    }
643    EVP_PKEY_free(publicKey);
644    return true;
645}
646
647bool CertTools::SetBasicExt(X509* cert)
648{
649    X509_EXTENSION* basicExtension = X509V3_EXT_conf(NULL, NULL, NID_BASIC_CONST.c_str(),
650                                                     DEFAULT_BASIC_EXTENSION.c_str());
651    if (!X509_add_ext(cert, basicExtension, -1)) {
652        VerifyHapOpensslUtils::GetOpensslErrorMessage();
653        SIGNATURE_TOOLS_LOGE("set basicExtension information failed");
654        X509_EXTENSION_free(basicExtension);
655        return false;
656    }
657    X509_EXTENSION_free(basicExtension);
658    return true;
659}
660
661bool CertTools::SetkeyUsageExt(X509* cert)
662{
663    X509_EXTENSION* keyUsageExtension = X509V3_EXT_conf(NULL, NULL, NID_KEYUSAGE_CONST.c_str(),
664                                                        DEFAULT_KEYUSAGE_EXTENSION.c_str());
665    if (!X509_add_ext(cert, keyUsageExtension, -1)) {
666        VerifyHapOpensslUtils::GetOpensslErrorMessage();
667        SIGNATURE_TOOLS_LOGE("set keyUsageExtension information failed");
668        X509_EXTENSION_free(keyUsageExtension);
669        return false;
670    }
671    X509_EXTENSION_free(keyUsageExtension);
672    return true;
673}
674
675bool CertTools::SetKeyUsageEndExt(X509* cert)
676{
677    X509_EXTENSION* keyUsageEndExtension = X509V3_EXT_conf(NULL, NULL, NID_EXT_KEYUSAGE_CONST.c_str(),
678                                                           DEFAULT_EXTEND_KEYUSAGE.c_str());
679    if (!X509_add_ext(cert, keyUsageEndExtension, -1)) {
680        VerifyHapOpensslUtils::GetOpensslErrorMessage();
681        SIGNATURE_TOOLS_LOGE("set keyUsageEndExtension information failed");
682        X509_EXTENSION_free(keyUsageEndExtension);
683        return false;
684    }
685    X509_EXTENSION_free(keyUsageEndExtension);
686    return true;
687}
688
689bool CertTools::SetKeyIdentifierExt(X509* cert)
690{
691    unsigned char digest[SHA256_DIGEST_LENGTH] = {0};
692    unsigned int digestLen = 0;
693    if (X509_pubkey_digest(cert, EVP_sha256(), digest, &digestLen) != 1) {
694        VerifyHapOpensslUtils::GetOpensslErrorMessage();
695        SIGNATURE_TOOLS_LOGE("digest x509 cert public key failed");
696        return false;
697    }
698    ASN1_OCTET_STRING* pubKeyDigestData = ASN1_OCTET_STRING_new();
699    if (!ASN1_OCTET_STRING_set(pubKeyDigestData, digest, digestLen)) {
700        VerifyHapOpensslUtils::GetOpensslErrorMessage();
701        SIGNATURE_TOOLS_LOGE("set ANS1 pubKeyDigestData failed");
702        ASN1_OCTET_STRING_free(pubKeyDigestData);
703        return false;
704    }
705
706    X509_EXTENSION* subKeyIdentifierExtension = nullptr;
707    /* function OBJ_nid2obj(NID_subject_key_identifier) return value is a global variable, so should not free it */
708    subKeyIdentifierExtension = X509_EXTENSION_create_by_OBJ(NULL, OBJ_nid2obj(NID_subject_key_identifier),
709                                                             0, pubKeyDigestData);
710    if (!X509_add_ext(cert, subKeyIdentifierExtension, -1)) {
711        VerifyHapOpensslUtils::GetOpensslErrorMessage();
712        SIGNATURE_TOOLS_LOGE("set subKeyIdentifierExtension information failed");
713        ASN1_OCTET_STRING_free(pubKeyDigestData);
714        X509_EXTENSION_free(subKeyIdentifierExtension);
715        return false;
716    }
717    ASN1_OCTET_STRING_free(pubKeyDigestData);
718    X509_EXTENSION_free(subKeyIdentifierExtension);
719    return true;
720}
721
722bool CertTools::SetAuthorizeKeyIdentifierExt(X509* cert)
723{
724    unsigned char key_id[] = { 0x73, 0x3a, 0x81, 0x87, 0x8f, 0x95, 0xc1, 0x94,
725                               0xcf, 0xef, 0xab, 0x6f, 0x7f, 0x01, 0x52, 0x86,
726                               0xa3, 0xc2, 0x01, 0xc2 };
727    unsigned int key_id_len = sizeof(key_id);
728    X509_EXTENSION* ext = nullptr;
729    AUTHORITY_KEYID* akid = AUTHORITY_KEYID_new();
730    akid->keyid = ASN1_OCTET_STRING_new();
731    if (!ASN1_OCTET_STRING_set(akid->keyid, key_id, key_id_len)) {
732        VerifyHapOpensslUtils::GetOpensslErrorMessage();
733        SIGNATURE_TOOLS_LOGE("set ANS1 pubKeyDigestData failed");
734        AUTHORITY_KEYID_free(akid);
735        return false;
736    }
737    ext = X509V3_EXT_i2d(NID_authority_key_identifier, 1, akid);
738    if (!X509_add_ext(cert, ext, -1)) {
739        SIGNATURE_TOOLS_LOGE("Failed to add AKI extension to certificate");
740        X509_EXTENSION_free(ext);
741        AUTHORITY_KEYID_free(akid);
742        return false;
743    }
744
745    X509_EXTENSION_free(ext);
746    AUTHORITY_KEYID_free(akid);
747    return true;
748}
749
750bool CertTools::SetSignCapacityExt(X509* cert, const char signCapacity[], int capacityLen)
751{
752    ASN1_OCTET_STRING* certSignCapacityData = ASN1_OCTET_STRING_new();
753    if (!ASN1_OCTET_STRING_set(certSignCapacityData, (const unsigned char*)signCapacity, capacityLen)) {
754        VerifyHapOpensslUtils::GetOpensslErrorMessage();
755        SIGNATURE_TOOLS_LOGE("failed to set pubkey digst into ASN1 object");
756        ASN1_OCTET_STRING_free(certSignCapacityData);
757        return false;
758    }
759    // generate user-define Nid
760    ASN1_OBJECT* nid = OBJ_txt2obj(X509_EXT_OID.c_str(), 1);
761    X509_EXTENSION* certSignCapacityExt = X509_EXTENSION_create_by_OBJ(NULL, nid, 0, certSignCapacityData);
762
763    if (!X509_add_ext(cert, certSignCapacityExt, -1)) {
764        VerifyHapOpensslUtils::GetOpensslErrorMessage();
765        SIGNATURE_TOOLS_LOGE("set certSignCapacityExt information failed");
766        ASN1_OBJECT_free(nid);
767        X509_EXTENSION_free(certSignCapacityExt);
768        ASN1_OCTET_STRING_free(certSignCapacityData);
769        return false;
770    }
771    ASN1_OBJECT_free(nid);
772    X509_EXTENSION_free(certSignCapacityExt);
773    ASN1_OCTET_STRING_free(certSignCapacityData);
774    return true;
775}
776
777bool CertTools::SignCert(X509* cert, EVP_PKEY* privateKey, std::string signAlg)
778{
779    const EVP_MD* alg = nullptr;
780    if (signAlg == SIGN_ALG_SHA256) {
781        /* in openssl this func return value is stack variable, so we not need to release it */
782        alg = EVP_sha256();
783    }
784    if (signAlg == SIGN_ALG_SHA384) {
785        alg = EVP_sha384();
786    }
787    if (!X509_sign(cert, privateKey, alg)) {
788        VerifyHapOpensslUtils::GetOpensslErrorMessage();
789        SIGNATURE_TOOLS_LOGE("sign X509 cert failed");
790        return false;
791    }
792    return true;
793}
794
795bool CertTools::SetCertValidity(X509* cert, int validity)
796{
797    if (!SetCertValidityStartAndEnd(cert, DEFAULT_START_VALIDITY, validity)) {
798        return false;
799    }
800    return true;
801}
802
803bool CertTools::SerialNumberBuilder(uint8_t* serialNum, int length)
804{
805    if (RAND_bytes(serialNum, length) != 1) { // this function is thread safity
806        SIGNATURE_TOOLS_LOGE("serial number build failed");
807        return false;
808    }
809    return true;
810}
811
812X509* CertTools::GenerateEndCert(X509_REQ* csr, EVP_PKEY* issuerKeyPair,
813                                 LocalizationAdapter& adapter,
814                                 const char signCapacity[], int capacityLen)
815{
816    X509* cert = X509_new(); // in this function, should not release X509cert memory
817    X509_REQ* issuerReq = nullptr;
818    bool result = false;
819    issuerReq = X509_REQ_new();
820    std::string issuerStr = adapter.options->GetString(adapter.options->ISSUER);
821    int validity = adapter.options->GetInt(adapter.options->VALIDITY);
822    std::string signAlg = adapter.options->GetString(adapter.options->SIGN_ALG);
823
824    result = (!SetCertVersion(cert, DEFAULT_CERT_VERSION) || !SetCertSerialNum(cert));
825    if (result) {
826        goto err;
827    }
828    result = (!SetCertIssuerName(cert, BuildDN(issuerStr, issuerReq)) || !SetCertSubjectName(cert, csr));
829    if (result) {
830        goto err;
831    }
832    result = (!SetCertValidity(cert, validity) || !SetCertPublickKey(cert, csr));
833    if (result) {
834        goto err;
835    }
836    result = (!SetBasicExt(cert) || !SetkeyUsageExt(cert) || !SetKeyUsageEndExt(cert));
837    if (result) {
838        goto err;
839    }
840    result = (!SetKeyIdentifierExt(cert) || !SetSignCapacityExt(cert, signCapacity, capacityLen));
841    if (result) {
842        goto err;
843    }
844    if (!SignCert(cert, issuerKeyPair, signAlg)) {
845        goto err;
846    }
847
848    adapter.AppAndProfileAssetsRealse({}, {issuerReq}, {});
849    return cert; // return x509 assets
850err:
851    adapter.AppAndProfileAssetsRealse({}, {issuerReq}, {cert});
852    return nullptr;
853}
854
855bool CertTools::String2Bool(Options* options, const std::string& option)
856{
857    std::string val = options->GetString(option);
858    if (val == "1" || val == "true" || val == "TRUE") {
859        (*options)[option] = true;
860    } else if (val == "0" || val == "false" || val == "FALSE") {
861        (*options)[option] = false;
862    } else {
863        PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR,
864                            val + "is not valid value for " + "-" + option);
865        return false;
866    }
867    return true;
868}
869} // namespace SignatureTools
870} // namespace OHOS
871
872