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 <string>
16#include <cstring>
17
18#include "localization_adapter.h"
19#include "constant.h"
20
21namespace OHOS {
22namespace SignatureTools {
23
24LocalizationAdapter::LocalizationAdapter(Options* options)
25{
26    this->options = options;
27    this->keyStoreHelper = std::make_unique<KeyStoreHelper>();
28    this->isIssuerKeyStoreFile = false;
29}
30
31int LocalizationAdapter::IsAliasExist(const std::string& alias)
32{
33    std::string keyStoreFile = options->GetString(Options::KEY_STORE_FILE);
34    if (!keyStoreHelper->IsKeyStoreFileExist(keyStoreFile)) {
35        return RET_FAILED;
36    }
37
38    EVP_PKEY* keyPair = nullptr;
39    char* keyStorePwd = options->GetChars(Options::KEY_STORE_RIGHTS);
40    char* keyPwd = options->GetChars(Options::KEY_RIGHTS);
41    keyStoreHelper->SetIsRegen(true);
42    int status = keyStoreHelper->ReadKeyStore(keyStoreFile, keyStorePwd, alias, keyPwd, &keyPair);
43    EVP_PKEY_free(keyPair);
44    if (status == RET_OK) {
45        return RET_OK;
46    }
47
48    return RET_FAILED;
49}
50
51void LocalizationAdapter::ResetPwd()
52{
53    char* keyRights = options->GetChars(Options::KEY_RIGHTS);
54    if (keyRights != nullptr) {
55        ResetChars(keyRights);
56    }
57    char* keyStoreRights = options->GetChars(Options::KEY_STORE_RIGHTS);
58    if (keyStoreRights != nullptr) {
59        ResetChars(keyStoreRights);
60    }
61    char* issuerKeyRights = options->GetChars(Options::ISSUER_KEY_RIGHTS);
62    if (issuerKeyRights != nullptr) {
63        ResetChars(issuerKeyRights);
64    }
65    char* issuerKeyStoreRights = options->GetChars(Options::ISSUER_KEY_STORE_RIGHTS);
66    if (issuerKeyStoreRights != nullptr) {
67        ResetChars(issuerKeyStoreRights);
68    }
69}
70
71void LocalizationAdapter::ResetChars(char* chars)
72{
73    if (chars == NULL) {
74        return;
75    }
76    for (size_t i = 0; i < strlen(chars); i++) {
77        chars[i] = 0;
78    }
79}
80
81EVP_PKEY* LocalizationAdapter::GetAliasKey(bool autoCreate)
82{
83    EVP_PKEY* keyPair = nullptr;
84    if (keyStoreHelper == nullptr) {
85        keyStoreHelper = std::make_unique<KeyStoreHelper>();
86    }
87
88    int status = GetKeyPair(autoCreate, &keyPair);
89    if (status == RET_FAILED) {
90        EVP_PKEY_free(keyPair);
91        return nullptr;
92    }
93
94    return keyPair;
95}
96
97int LocalizationAdapter::GetKeyPair(bool autoCreate, EVP_PKEY** keyPair)
98{
99    keyStoreHelper->SetPassWordStatus(true);
100    keyStoreHelper->SetIsRegen(autoCreate);
101
102    int status = RET_FAILED;
103    if (isIssuerKeyStoreFile) {
104        status = IssuerKeyStoreFile(keyPair, autoCreate);
105    } else {
106        status = KeyStoreFile(keyPair, autoCreate);
107    }
108    isIssuerKeyStoreFile = false;
109    return status;
110}
111
112int LocalizationAdapter::KeyStoreFile(EVP_PKEY** keyPair, bool autoCreate)
113{
114    std::string keyStorePath = "";
115    keyStorePath = options->GetString(Options::KEY_STORE_FILE);
116    char* keyStorePwd = options->GetChars(Options::KEY_STORE_RIGHTS);
117    char* keyPwd = options->GetChars(Options::KEY_RIGHTS);
118    std::string keyAlias = options->GetString(Options::KEY_ALIAS);
119    bool fileStatus = keyStoreHelper->IsKeyStoreFileExist(keyStorePath);
120    if (fileStatus) {
121        int status = keyStoreHelper->ReadKeyStore(keyStorePath, keyStorePwd, keyAlias, keyPwd, keyPair);
122        if (status == RET_OK) {
123            return RET_OK;
124        }
125
126        if (!keyStoreHelper->GetPassWordStatus()) {
127                autoCreate = false;
128        }
129    }
130    if (autoCreate) {
131        std::string keyAlg = options->GetString(Options::KEY_ALG);
132        int keySize = options->GetInt(Options::KEY_SIZE);
133        *keyPair = keyStoreHelper->GenerateKeyPair(keyAlg, keySize);
134        int status = keyStoreHelper->WriteKeyStore(*keyPair, keyStorePath, keyStorePwd, keyAlias, keyPwd);
135        if (status == RET_OK) {
136            PrintMsg("Remind: generate new keypair ,the keyalias is " + keyAlias + " !");
137            return RET_OK;
138        }
139    }
140
141    return RET_FAILED;
142}
143
144int LocalizationAdapter::IssuerKeyStoreFile(EVP_PKEY** keyPair, bool autoCreate)
145{
146    std::string keyStore = options->GetString(Options::ISSUER_KEY_STORE_FILE);
147    char* keyStorePwd = options->GetChars(Options::ISSUER_KEY_STORE_RIGHTS);
148    std::string keyAlias = options->GetString(Options::ISSUER_KEY_ALIAS);
149    char* keyPwd = options->GetChars(Options::ISSUER_KEY_RIGHTS);
150
151    if (keyStore.empty()) {
152        keyStore = options->GetString(Options::KEY_STORE_FILE);
153        keyStorePwd = options->GetChars(Options::KEY_STORE_RIGHTS);
154    }
155
156    bool fileStatus = keyStoreHelper->IsKeyStoreFileExist(keyStore);
157    if (fileStatus) {
158        int status = keyStoreHelper->ReadKeyStore(keyStore, keyStorePwd, keyAlias, keyPwd, keyPair);
159        if (status == RET_OK) {
160            return RET_OK;
161        }
162
163        if (!keyStoreHelper->GetPassWordStatus()) {
164                autoCreate = false;
165        }
166    }
167
168    if (!fileStatus && !keyStore.empty() && !autoCreate) {
169        PrintErrorNumberMsg("KEY_ALIAS_ERROR", KEY_ALIAS_ERROR, "keyAlias: '"
170                            + keyAlias + "' is not exist in" + keyStore);
171    }
172
173    if (autoCreate) {
174        std::string keyAlg = options->GetString(Options::KEY_ALG);
175        int keySize = options->GetInt(Options::KEY_SIZE);
176        *keyPair = keyStoreHelper->GenerateKeyPair(keyAlg, keySize);
177        if (keyStore.empty()) {
178            return keyStoreHelper->WriteKeyStore(*keyPair, keyStore, keyStorePwd, keyAlias, keyPwd);
179        }
180    }
181
182    return RET_FAILED;
183}
184
185void LocalizationAdapter::SetIssuerKeyStoreFile(bool issuerKeyStoreFile)
186{
187    this->isIssuerKeyStoreFile = issuerKeyStoreFile;
188}
189
190STACK_OF(X509)* LocalizationAdapter::GetSignCertChain()
191{
192    STACK_OF(X509)* certificates = NULL;
193    std::string certPath = options->GetString(Options::PROFILE_CERT_FILE);
194    if (certPath.empty()) {
195        certPath = options->GetString(Options::APP_CERT_FILE);
196    }
197    certificates = sk_X509_new(NULL);
198    if (certificates == NULL) {
199        SIGNATURE_TOOLS_LOGE("sk_X509_new failed");
200        return  NULL;
201    }
202    std::vector<X509*> certs = GetCertsFromFile(certPath, Options::PROFILE_CERT_FILE);
203    for (int i = 0; i < static_cast<int>(certs.size()); i++) {
204        sk_X509_push(certificates, certs[i]);
205    }
206    if (sk_X509_num(certificates) < MIN_CERT_CHAIN_SIZE || sk_X509_num(certificates) > MAX_CERT_CHAIN_SIZE) {
207        SIGNATURE_TOOLS_LOGE("Profile cert '%s' must a cert chain", certPath.c_str());
208        goto err;
209    }
210    return certificates;
211err:
212    sk_X509_pop_free(certificates, X509_free);
213    return NULL;
214}
215
216EVP_PKEY* LocalizationAdapter::GetIssuerKeyByAlias()
217{
218    return GetAliasKey(false);
219}
220
221bool LocalizationAdapter::IsOutFormChain()
222{
223    std::string checkStr = OUT_FORM_CERT_CHAIN;
224    std::string outForm = options->GetString(Options::OUT_FORM, checkStr);
225    if (outForm.compare(OUT_FORM_CERT_CHAIN) == 0) {
226        return true;
227    }
228    return false;
229}
230
231X509* LocalizationAdapter::GetSubCaCertFile()
232{
233    std::string certPath = options->GetString(Options::SUB_CA_CERT_FILE);
234    return GetCertsFromFile(certPath, Options::SUB_CA_CERT_FILE).at(0);
235}
236
237const std::string LocalizationAdapter::GetSignAlg() const
238{
239    return options->GetString(Options::SIGN_ALG);
240}
241
242X509* LocalizationAdapter::GetCaCertFile()
243{
244    std::string certPath = options->GetString(Options::CA_CERT_FILE);
245    return GetCertsFromFile(certPath, Options::CA_CERT_FILE).at(0);
246}
247
248const std::string LocalizationAdapter::GetOutFile()
249{
250    return options->GetString(Options::OUT_FILE);
251}
252
253std::vector<X509*> LocalizationAdapter::GetCertsFromFile(std::string& certPath, const std::string& logTitle)
254{
255    SIGNATURE_TOOLS_LOGD("outPutPath = %s , logTitle = %s", certPath.c_str(), logTitle.c_str());
256    std::vector<X509*> certs;
257    if (certPath.empty()) {
258        SIGNATURE_TOOLS_LOGE("cert path not exist!");
259        return certs;
260    }
261    // Read And Get Cert
262    BIO* bio = BIO_new_file(certPath.c_str(), "rb");
263    if (!bio) {
264        PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open file:" + certPath + "failed");
265        DigestCommon::GetOpensslErrorMessage();
266        BIO_free(bio);
267        return certs;
268    }
269    X509* cert = nullptr;
270    while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != nullptr) {
271        certs.emplace_back(cert);
272    }
273    BIO_free(bio);
274    return certs;
275}
276
277const std::string LocalizationAdapter::GetInFile()
278{
279    return options->GetString(Options::IN_FILE);
280}
281
282bool LocalizationAdapter::IsRemoteSigner()
283{
284    std::string mode = options->GetString(Options::MODE, LOCAL_SIGN);
285    return mode == REMOTE_SIGN;
286}
287
288Options* LocalizationAdapter::GetOptions()
289{
290    return options;
291}
292
293void LocalizationAdapter::AppAndProfileAssetsRealse(std::initializer_list<EVP_PKEY*> keys,
294                                                    std::initializer_list<X509_REQ*> reqs,
295                                                    std::initializer_list<X509*> certs)
296{
297    for (auto cert : certs) {
298        if (cert) {
299            X509_free(cert);
300            cert = nullptr;
301        }
302    }
303    for (auto req : reqs) {
304        if (req) {
305            X509_REQ_free(req);
306            req = nullptr;
307        }
308    }
309    for (auto key : keys) {
310        if (key) {
311            EVP_PKEY_free(key);
312            key = nullptr;
313        }
314    }
315}
316
317} // namespace SignatureTools
318} // namespace OHOS
319
320