xref: /developtools/hdc/src/common/auth.cpp (revision cc290419)
1cc290419Sopenharmony_ci/*
2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License.
5cc290419Sopenharmony_ci * You may obtain a copy of the License at
6cc290419Sopenharmony_ci *
7cc290419Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cc290419Sopenharmony_ci *
9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and
13cc290419Sopenharmony_ci * limitations under the License.
14cc290419Sopenharmony_ci */
15cc290419Sopenharmony_ci#include "auth.h"
16cc290419Sopenharmony_ci#include <openssl/evp.h>
17cc290419Sopenharmony_ci#include <openssl/objects.h>
18cc290419Sopenharmony_ci#include <openssl/pem.h>
19cc290419Sopenharmony_ci#include <openssl/rsa.h>
20cc290419Sopenharmony_ci#include <openssl/sha.h>
21cc290419Sopenharmony_ci#include <openssl/err.h>
22cc290419Sopenharmony_ci
23cc290419Sopenharmony_ciusing namespace Hdc;
24cc290419Sopenharmony_ci#define BIGNUMTOBIT 32
25cc290419Sopenharmony_ci
26cc290419Sopenharmony_cinamespace HdcAuth {
27cc290419Sopenharmony_ci// ---------------------------------------Cheat compiler---------------------------------------------------------
28cc290419Sopenharmony_ci#ifdef HDC_HOST
29cc290419Sopenharmony_ci
30cc290419Sopenharmony_cibool AuthVerify(uint8_t *token, uint8_t *sig, int siglen)
31cc290419Sopenharmony_ci{
32cc290419Sopenharmony_ci    return false;
33cc290419Sopenharmony_ci};
34cc290419Sopenharmony_cibool PostUIConfirm(string publicKey)
35cc290419Sopenharmony_ci{
36cc290419Sopenharmony_ci    return false;
37cc290419Sopenharmony_ci}
38cc290419Sopenharmony_ci
39cc290419Sopenharmony_ci#else  // daemon
40cc290419Sopenharmony_ci
41cc290419Sopenharmony_cibool GenerateKey(const char *file)
42cc290419Sopenharmony_ci{
43cc290419Sopenharmony_ci    return false;
44cc290419Sopenharmony_ci};
45cc290419Sopenharmony_ciint AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig)
46cc290419Sopenharmony_ci{
47cc290419Sopenharmony_ci    return 0;
48cc290419Sopenharmony_ci};
49cc290419Sopenharmony_ciint GetPublicKeyFileBuf(unsigned char *data, size_t len)
50cc290419Sopenharmony_ci{
51cc290419Sopenharmony_ci    return 0;
52cc290419Sopenharmony_ci}
53cc290419Sopenharmony_ci
54cc290419Sopenharmony_ci#endif
55cc290419Sopenharmony_ci// ------------------------------------------------------------------------------------------------
56cc290419Sopenharmony_ci
57cc290419Sopenharmony_ciconst uint32_t RSANUMBYTES = 512;  // 4096 bit key length
58cc290419Sopenharmony_ciconst uint32_t RSANUMWORDS = (RSANUMBYTES / sizeof(uint32_t));
59cc290419Sopenharmony_cistruct RSAPublicKey {
60cc290419Sopenharmony_ci    int wordModulusSize;            // Length of n[] in number of uint32_t */
61cc290419Sopenharmony_ci    uint32_t rsaN0inv;              // -1 / n[0] mod 2^32
62cc290419Sopenharmony_ci    uint32_t modulus[RSANUMWORDS];  // modulus as little endian array
63cc290419Sopenharmony_ci    uint32_t rr[RSANUMWORDS];       // R^2 as little endian array
64cc290419Sopenharmony_ci    BN_ULONG exponent;                   // 3 or 65537
65cc290419Sopenharmony_ci};
66cc290419Sopenharmony_ci
67cc290419Sopenharmony_ci#ifdef HDC_HOST
68cc290419Sopenharmony_ci// Convert OpenSSL RSA private key to pre-computed RSAPublicKey format
69cc290419Sopenharmony_ciint RSA2RSAPublicKey(RSA *rsa, RSAPublicKey *publicKey)
70cc290419Sopenharmony_ci{
71cc290419Sopenharmony_ci    int result = 1;
72cc290419Sopenharmony_ci    unsigned int i;
73cc290419Sopenharmony_ci    BN_CTX *ctx = BN_CTX_new();
74cc290419Sopenharmony_ci    BIGNUM *r32 = BN_new();
75cc290419Sopenharmony_ci    BIGNUM *rsaRR = BN_new();
76cc290419Sopenharmony_ci    BIGNUM *rsaR = BN_new();
77cc290419Sopenharmony_ci    BIGNUM *rsaRem = BN_new();
78cc290419Sopenharmony_ci    BIGNUM *rsaN0inv = BN_new();
79cc290419Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
80cc290419Sopenharmony_ci    // boringssl
81cc290419Sopenharmony_ci    BIGNUM *n = BN_new();
82cc290419Sopenharmony_ci    BN_copy(n, rsa->n);
83cc290419Sopenharmony_ci    publicKey->exponent = BN_get_word(rsa->e);
84cc290419Sopenharmony_ci#else
85cc290419Sopenharmony_ci    // openssl
86cc290419Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10100005L
87cc290419Sopenharmony_ci    BIGNUM *n = (BIGNUM *)RSA_get0_n(rsa);
88cc290419Sopenharmony_ci    publicKey->exponent = BN_get_word(RSA_get0_e(rsa));
89cc290419Sopenharmony_ci#else
90cc290419Sopenharmony_ci    BIGNUM *n = BN_new();
91cc290419Sopenharmony_ci    BN_copy(n, rsa->n);
92cc290419Sopenharmony_ci    publicKey->exponent = BN_get_word(rsa->e);
93cc290419Sopenharmony_ci#endif
94cc290419Sopenharmony_ci
95cc290419Sopenharmony_ci#endif  // OPENSSL_IS_BORINGSSL
96cc290419Sopenharmony_ci    while (true) {
97cc290419Sopenharmony_ci        if (RSA_size(rsa) != RSANUMBYTES) {
98cc290419Sopenharmony_ci            result = 0;
99cc290419Sopenharmony_ci            break;
100cc290419Sopenharmony_ci        }
101cc290419Sopenharmony_ci
102cc290419Sopenharmony_ci        BN_set_bit(r32, BIGNUMTOBIT);
103cc290419Sopenharmony_ci        BN_set_bit(rsaR, RSANUMWORDS * BIGNUMTOBIT);
104cc290419Sopenharmony_ci        BN_mod_sqr(rsaRR, rsaR, n, ctx);
105cc290419Sopenharmony_ci        BN_div(nullptr, rsaRem, n, r32, ctx);
106cc290419Sopenharmony_ci        BN_mod_inverse(rsaN0inv, rsaRem, r32, ctx);
107cc290419Sopenharmony_ci        publicKey->wordModulusSize = RSANUMWORDS;
108cc290419Sopenharmony_ci        publicKey->rsaN0inv = 0 - BN_get_word(rsaN0inv);
109cc290419Sopenharmony_ci        for (i = 0; i < RSANUMWORDS; ++i) {
110cc290419Sopenharmony_ci            BN_div(rsaRR, rsaRem, rsaRR, r32, ctx);
111cc290419Sopenharmony_ci            publicKey->rr[i] = BN_get_word(rsaRem);
112cc290419Sopenharmony_ci            BN_div(n, rsaRem, n, r32, ctx);
113cc290419Sopenharmony_ci            publicKey->modulus[i] = BN_get_word(rsaRem);
114cc290419Sopenharmony_ci        }
115cc290419Sopenharmony_ci        break;
116cc290419Sopenharmony_ci    }
117cc290419Sopenharmony_ci
118cc290419Sopenharmony_ci    BN_free(rsaR);
119cc290419Sopenharmony_ci    BN_free(rsaRR);
120cc290419Sopenharmony_ci    BN_free(n);
121cc290419Sopenharmony_ci    BN_free(r32);
122cc290419Sopenharmony_ci    BN_free(rsaN0inv);
123cc290419Sopenharmony_ci    BN_free(rsaRem);
124cc290419Sopenharmony_ci    BN_CTX_free(ctx);
125cc290419Sopenharmony_ci    return result;
126cc290419Sopenharmony_ci}
127cc290419Sopenharmony_ci
128cc290419Sopenharmony_ciint GetUserInfo(char *buf, size_t len)
129cc290419Sopenharmony_ci{
130cc290419Sopenharmony_ci    char hostname[BUF_SIZE_DEFAULT];
131cc290419Sopenharmony_ci    char username[BUF_SIZE_DEFAULT];
132cc290419Sopenharmony_ci    uv_passwd_t pwd;
133cc290419Sopenharmony_ci    int ret = -1;
134cc290419Sopenharmony_ci    size_t bufSize = sizeof(hostname);
135cc290419Sopenharmony_ci    if (uv_os_gethostname(hostname, &bufSize) < 0 && EOK != strcpy_s(hostname, sizeof(hostname), "unknown")) {
136cc290419Sopenharmony_ci        return ERR_API_FAIL;
137cc290419Sopenharmony_ci    }
138cc290419Sopenharmony_ci    if (!uv_os_get_passwd(&pwd) && !strcpy_s(username, sizeof(username), pwd.username)) {
139cc290419Sopenharmony_ci        ret = 0;
140cc290419Sopenharmony_ci    }
141cc290419Sopenharmony_ci    uv_os_free_passwd(&pwd);
142cc290419Sopenharmony_ci    if (ret < 0 && EOK != strcpy_s(username, sizeof(username), "unknown")) {
143cc290419Sopenharmony_ci        return ERR_API_FAIL;
144cc290419Sopenharmony_ci    }
145cc290419Sopenharmony_ci    if (snprintf_s(buf, len, len - 1, " %s@%s", username, hostname) < 0) {
146cc290419Sopenharmony_ci        return ERR_BUF_OVERFLOW;
147cc290419Sopenharmony_ci    }
148cc290419Sopenharmony_ci    return RET_SUCCESS;
149cc290419Sopenharmony_ci}
150cc290419Sopenharmony_ci
151cc290419Sopenharmony_ciint WritePublicKeyfile(RSA *private_key, const char *private_key_path)
152cc290419Sopenharmony_ci{
153cc290419Sopenharmony_ci    RSAPublicKey publicKey;
154cc290419Sopenharmony_ci    char info[BUF_SIZE_DEFAULT];
155cc290419Sopenharmony_ci    int ret = 0;
156cc290419Sopenharmony_ci    string path = private_key_path + string(".pub");
157cc290419Sopenharmony_ci
158cc290419Sopenharmony_ci    ret = RSA2RSAPublicKey(private_key, &publicKey);
159cc290419Sopenharmony_ci    if (!ret) {
160cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "Failed to convert to publickey\n");
161cc290419Sopenharmony_ci        return 0;
162cc290419Sopenharmony_ci    }
163cc290419Sopenharmony_ci    vector<uint8_t> vec = Base::Base64Encode((const uint8_t *)&publicKey, sizeof(RSAPublicKey));
164cc290419Sopenharmony_ci    if (!vec.size()) {
165cc290419Sopenharmony_ci        return 0;
166cc290419Sopenharmony_ci    }
167cc290419Sopenharmony_ci    GetUserInfo(info, sizeof(info));
168cc290419Sopenharmony_ci    vec.insert(vec.end(), (uint8_t *)info, (uint8_t *)info + strlen(info));
169cc290419Sopenharmony_ci    ret = Base::WriteBinFile(path.c_str(), vec.data(), vec.size(), true);
170cc290419Sopenharmony_ci    return ret >= 0 ? 1 : 0;
171cc290419Sopenharmony_ci}
172cc290419Sopenharmony_ci
173cc290419Sopenharmony_cibool GenerateKey(const char *file)
174cc290419Sopenharmony_ci{
175cc290419Sopenharmony_ci    EVP_PKEY *publicKey = EVP_PKEY_new();
176cc290419Sopenharmony_ci    BIGNUM *exponent = BN_new();
177cc290419Sopenharmony_ci    RSA *rsa = RSA_new();
178cc290419Sopenharmony_ci    int bits = 4096;
179cc290419Sopenharmony_ci    mode_t old_mask;
180cc290419Sopenharmony_ci    FILE *fKey = nullptr;
181cc290419Sopenharmony_ci    bool ret = false;
182cc290419Sopenharmony_ci
183cc290419Sopenharmony_ci    while (true) {
184cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "generate_key '%s'\n", file);
185cc290419Sopenharmony_ci        if (!publicKey || !exponent || !rsa) {
186cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "Failed to allocate key");
187cc290419Sopenharmony_ci            break;
188cc290419Sopenharmony_ci        }
189cc290419Sopenharmony_ci
190cc290419Sopenharmony_ci        BN_set_word(exponent, RSA_F4);
191cc290419Sopenharmony_ci        RSA_generate_key_ex(rsa, bits, exponent, nullptr);
192cc290419Sopenharmony_ci        EVP_PKEY_set1_RSA(publicKey, rsa);
193cc290419Sopenharmony_ci        old_mask = umask(077);  // 077:permission
194cc290419Sopenharmony_ci
195cc290419Sopenharmony_ci        fKey = Base::Fopen(file, "w");
196cc290419Sopenharmony_ci        if (!fKey) {
197cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "Failed to open '%s'\n", file);
198cc290419Sopenharmony_ci            umask(old_mask);
199cc290419Sopenharmony_ci            break;
200cc290419Sopenharmony_ci        }
201cc290419Sopenharmony_ci        umask(old_mask);
202cc290419Sopenharmony_ci        if (!PEM_write_PrivateKey(fKey, publicKey, nullptr, nullptr, 0, nullptr, nullptr)) {
203cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "Failed to write key");
204cc290419Sopenharmony_ci            break;
205cc290419Sopenharmony_ci        }
206cc290419Sopenharmony_ci        if (!WritePublicKeyfile(rsa, file)) {
207cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "Failed to write public key");
208cc290419Sopenharmony_ci            break;
209cc290419Sopenharmony_ci        }
210cc290419Sopenharmony_ci        ret = true;
211cc290419Sopenharmony_ci        break;
212cc290419Sopenharmony_ci    }
213cc290419Sopenharmony_ci
214cc290419Sopenharmony_ci    EVP_PKEY_free(publicKey);
215cc290419Sopenharmony_ci    BN_free(exponent);
216cc290419Sopenharmony_ci    if (fKey)
217cc290419Sopenharmony_ci        fclose(fKey);
218cc290419Sopenharmony_ci    return ret;
219cc290419Sopenharmony_ci}
220cc290419Sopenharmony_ci
221cc290419Sopenharmony_cibool ReadKey(const char *file, list<void *> *listPrivateKey)
222cc290419Sopenharmony_ci{
223cc290419Sopenharmony_ci    FILE *f = nullptr;
224cc290419Sopenharmony_ci    bool ret = false;
225cc290419Sopenharmony_ci
226cc290419Sopenharmony_ci    if (file == nullptr || listPrivateKey == nullptr) {
227cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "file or listPrivateKey is null");
228cc290419Sopenharmony_ci        return ret;
229cc290419Sopenharmony_ci    }
230cc290419Sopenharmony_ci    while (true) {
231cc290419Sopenharmony_ci        if (!(f = fopen(file, "r"))) {
232cc290419Sopenharmony_ci            break;
233cc290419Sopenharmony_ci        }
234cc290419Sopenharmony_ci        RSA *rsa = RSA_new();
235cc290419Sopenharmony_ci        if (!PEM_read_RSAPrivateKey(f, &rsa, nullptr, nullptr)) {
236cc290419Sopenharmony_ci            RSA_free(rsa);
237cc290419Sopenharmony_ci            break;
238cc290419Sopenharmony_ci        }
239cc290419Sopenharmony_ci        listPrivateKey->push_back((void *)rsa);
240cc290419Sopenharmony_ci        ret = true;
241cc290419Sopenharmony_ci        break;
242cc290419Sopenharmony_ci    }
243cc290419Sopenharmony_ci    if (f) {
244cc290419Sopenharmony_ci        fclose(f);
245cc290419Sopenharmony_ci    }
246cc290419Sopenharmony_ci    return ret;
247cc290419Sopenharmony_ci}
248cc290419Sopenharmony_ci
249cc290419Sopenharmony_ciint GetUserKeyPath(string &path)
250cc290419Sopenharmony_ci{
251cc290419Sopenharmony_ci    struct stat status;
252cc290419Sopenharmony_ci    const char harmoneyPath[] = ".harmony";
253cc290419Sopenharmony_ci    const char hdcKeyFile[] = "hdckey";
254cc290419Sopenharmony_ci    char buf[BUF_SIZE_DEFAULT];
255cc290419Sopenharmony_ci    size_t len = BUF_SIZE_DEFAULT;
256cc290419Sopenharmony_ci    // $home
257cc290419Sopenharmony_ci    if (uv_os_homedir(buf, &len) < 0)
258cc290419Sopenharmony_ci        return false;
259cc290419Sopenharmony_ci    string dir = string(buf) + Base::GetPathSep() + string(harmoneyPath) + Base::GetPathSep();
260cc290419Sopenharmony_ci    path = Base::CanonicalizeSpecPath(dir);
261cc290419Sopenharmony_ci    if (path.empty()) {
262cc290419Sopenharmony_ci        path = dir;
263cc290419Sopenharmony_ci    } else {
264cc290419Sopenharmony_ci        path += Base::GetPathSep(); // bugfix for unix platform create key file not in dir.
265cc290419Sopenharmony_ci    }
266cc290419Sopenharmony_ci    if (stat(path.c_str(), &status)) {
267cc290419Sopenharmony_ci        uv_fs_t req;
268cc290419Sopenharmony_ci        uv_fs_mkdir(nullptr, &req, path.c_str(), 0750, nullptr);  // 0750:permission
269cc290419Sopenharmony_ci        uv_fs_req_cleanup(&req);
270cc290419Sopenharmony_ci        uv_fs_stat(nullptr, &req, path.c_str(), nullptr);
271cc290419Sopenharmony_ci        uv_fs_req_cleanup(&req);
272cc290419Sopenharmony_ci        if (req.result < 0) {
273cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "Cannot mkdir '%s'", path.c_str());
274cc290419Sopenharmony_ci            return false;
275cc290419Sopenharmony_ci        }
276cc290419Sopenharmony_ci    }
277cc290419Sopenharmony_ci    path += hdcKeyFile;
278cc290419Sopenharmony_ci    return true;
279cc290419Sopenharmony_ci}
280cc290419Sopenharmony_ci
281cc290419Sopenharmony_cibool LoadHostUserKey(list<void *> *listPrivateKey)
282cc290419Sopenharmony_ci{
283cc290419Sopenharmony_ci    struct stat status;
284cc290419Sopenharmony_ci    string path;
285cc290419Sopenharmony_ci    if (!GetUserKeyPath(path)) {
286cc290419Sopenharmony_ci        return false;
287cc290419Sopenharmony_ci    }
288cc290419Sopenharmony_ci    if (stat(path.c_str(), &status) == -1) {
289cc290419Sopenharmony_ci        if (!GenerateKey(path.c_str())) {
290cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "Failed to generate new key");
291cc290419Sopenharmony_ci            return false;
292cc290419Sopenharmony_ci        }
293cc290419Sopenharmony_ci    }
294cc290419Sopenharmony_ci    if (!ReadKey(path.c_str(), listPrivateKey)) {
295cc290419Sopenharmony_ci        return false;
296cc290419Sopenharmony_ci    }
297cc290419Sopenharmony_ci    return true;
298cc290419Sopenharmony_ci}
299cc290419Sopenharmony_ci
300cc290419Sopenharmony_ciint AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig)
301cc290419Sopenharmony_ci{
302cc290419Sopenharmony_ci    unsigned int len;
303cc290419Sopenharmony_ci    if (!RSA_sign(NID_sha256, token, tokenSize, (unsigned char *)sig, &len, (RSA *)rsa)) {
304cc290419Sopenharmony_ci        return 0;
305cc290419Sopenharmony_ci    }
306cc290419Sopenharmony_ci    return static_cast<int>(len);
307cc290419Sopenharmony_ci}
308cc290419Sopenharmony_ci
309cc290419Sopenharmony_ciint GetPublicKeyFileBuf(unsigned char *data, size_t len)
310cc290419Sopenharmony_ci{
311cc290419Sopenharmony_ci    string path;
312cc290419Sopenharmony_ci    int ret;
313cc290419Sopenharmony_ci
314cc290419Sopenharmony_ci    if (!GetUserKeyPath(path)) {
315cc290419Sopenharmony_ci        return 0;
316cc290419Sopenharmony_ci    }
317cc290419Sopenharmony_ci    path += ".pub";
318cc290419Sopenharmony_ci    ret = Base::ReadBinFile(path.c_str(), (void **)data, len);
319cc290419Sopenharmony_ci    if (ret <= 0) {
320cc290419Sopenharmony_ci        return 0;
321cc290419Sopenharmony_ci    }
322cc290419Sopenharmony_ci    data[ret] = '\0';
323cc290419Sopenharmony_ci    return ret + 1;
324cc290419Sopenharmony_ci}
325cc290419Sopenharmony_ci
326cc290419Sopenharmony_ci#else  // daemon
327cc290419Sopenharmony_ci
328cc290419Sopenharmony_cibool RSAPublicKey2RSA(const uint8_t *keyBuf, RSA **key)
329cc290419Sopenharmony_ci{
330cc290419Sopenharmony_ci    const int pubKeyModulusSize = 256;
331cc290419Sopenharmony_ci    const int pubKeyModulusSizeWords = pubKeyModulusSize / 4;
332cc290419Sopenharmony_ci
333cc290419Sopenharmony_ci    const RSAPublicKey *keyStruct = reinterpret_cast<const RSAPublicKey *>(keyBuf);
334cc290419Sopenharmony_ci    bool ret = false;
335cc290419Sopenharmony_ci    uint8_t modulusBuffer[pubKeyModulusSize];
336cc290419Sopenharmony_ci    RSA *newKey = RSA_new();
337cc290419Sopenharmony_ci    if (!newKey) {
338cc290419Sopenharmony_ci        goto cleanup;
339cc290419Sopenharmony_ci    }
340cc290419Sopenharmony_ci    if (keyStruct->wordModulusSize != pubKeyModulusSizeWords) {
341cc290419Sopenharmony_ci        goto cleanup;
342cc290419Sopenharmony_ci    }
343cc290419Sopenharmony_ci    if (memcpy_s(modulusBuffer, sizeof(modulusBuffer), keyStruct->modulus, sizeof(modulusBuffer)) != EOK) {
344cc290419Sopenharmony_ci        goto cleanup;
345cc290419Sopenharmony_ci    }
346cc290419Sopenharmony_ci    Base::ReverseBytes(modulusBuffer, sizeof(modulusBuffer));
347cc290419Sopenharmony_ci
348cc290419Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
349cc290419Sopenharmony_ci    // boringssl
350cc290419Sopenharmony_ci    newKey->n = BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr);
351cc290419Sopenharmony_ci    newKey->e = BN_new();
352cc290419Sopenharmony_ci    if (!newKey->e || !BN_set_word(newKey->e, keyStruct->exponent) || !newKey->n) {
353cc290419Sopenharmony_ci        goto cleanup;
354cc290419Sopenharmony_ci    }
355cc290419Sopenharmony_ci#else
356cc290419Sopenharmony_ci    // openssl
357cc290419Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10100005L
358cc290419Sopenharmony_ci    RSA_set0_key(newKey, BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr), BN_new(), BN_new());
359cc290419Sopenharmony_ci#else
360cc290419Sopenharmony_ci    newKey->n = BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr);
361cc290419Sopenharmony_ci    newKey->e = BN_new();
362cc290419Sopenharmony_ci    if (!newKey->e || !BN_set_word(newKey->e, keyStruct->exponent) || !newKey->n) {
363cc290419Sopenharmony_ci        goto cleanup;
364cc290419Sopenharmony_ci    }
365cc290419Sopenharmony_ci#endif
366cc290419Sopenharmony_ci#endif
367cc290419Sopenharmony_ci
368cc290419Sopenharmony_ci    *key = newKey;
369cc290419Sopenharmony_ci    ret = true;
370cc290419Sopenharmony_ci
371cc290419Sopenharmony_cicleanup:
372cc290419Sopenharmony_ci    if (!ret && newKey) {
373cc290419Sopenharmony_ci        RSA_free(newKey);
374cc290419Sopenharmony_ci    }
375cc290419Sopenharmony_ci    return ret;
376cc290419Sopenharmony_ci}
377cc290419Sopenharmony_ci
378cc290419Sopenharmony_civoid ReadDaemonKeys(const char *file, list<void *> *listPublicKey)
379cc290419Sopenharmony_ci{
380cc290419Sopenharmony_ci    char buf[BUF_SIZE_DEFAULT2] = { 0 };
381cc290419Sopenharmony_ci    char *sep = nullptr;
382cc290419Sopenharmony_ci    int ret;
383cc290419Sopenharmony_ci    FILE *f = Base::Fopen(file, "re");
384cc290419Sopenharmony_ci    if (!f) {
385cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "Can't open '%s'", file);
386cc290419Sopenharmony_ci        return;
387cc290419Sopenharmony_ci    }
388cc290419Sopenharmony_ci    while (fgets(buf, sizeof(buf), f)) {
389cc290419Sopenharmony_ci        RSAPublicKey *key = new RSAPublicKey();
390cc290419Sopenharmony_ci        if (!key) {
391cc290419Sopenharmony_ci            break;
392cc290419Sopenharmony_ci        }
393cc290419Sopenharmony_ci        sep = strpbrk(buf, " \t");
394cc290419Sopenharmony_ci        if (sep) {
395cc290419Sopenharmony_ci            *sep = '\0';
396cc290419Sopenharmony_ci        }
397cc290419Sopenharmony_ci        ret = Base::Base64DecodeBuf(reinterpret_cast<uint8_t *>(buf), strlen(buf), reinterpret_cast<uint8_t *>(key));
398cc290419Sopenharmony_ci        if (ret != sizeof(RSAPublicKey)) {
399cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "%s: Invalid base64 data ret=%d", file, ret);
400cc290419Sopenharmony_ci            delete key;
401cc290419Sopenharmony_ci            continue;
402cc290419Sopenharmony_ci        }
403cc290419Sopenharmony_ci
404cc290419Sopenharmony_ci        if (key->wordModulusSize != RSANUMWORDS) {
405cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "%s: Invalid key len %d\n", file, key->wordModulusSize);
406cc290419Sopenharmony_ci            delete key;
407cc290419Sopenharmony_ci            continue;
408cc290419Sopenharmony_ci        }
409cc290419Sopenharmony_ci        listPublicKey->push_back(key);
410cc290419Sopenharmony_ci    }
411cc290419Sopenharmony_ci    fclose(f);
412cc290419Sopenharmony_ci}
413cc290419Sopenharmony_ci
414cc290419Sopenharmony_cibool AuthVerify(uint8_t *token, uint8_t *sig, int siglen)
415cc290419Sopenharmony_ci{
416cc290419Sopenharmony_ci    list<void *> listPublicKey;
417cc290419Sopenharmony_ci    uint8_t authKeyIndex = 0;
418cc290419Sopenharmony_ci    void *ptr = nullptr;
419cc290419Sopenharmony_ci    int ret = 0;
420cc290419Sopenharmony_ci    int childRet = 0;
421cc290419Sopenharmony_ci    while (KeylistIncrement(&listPublicKey, authKeyIndex, &ptr)) {
422cc290419Sopenharmony_ci        RSA *rsa = nullptr;
423cc290419Sopenharmony_ci        if (!RSAPublicKey2RSA((const uint8_t *)ptr, &rsa)) {
424cc290419Sopenharmony_ci            break;
425cc290419Sopenharmony_ci        }
426cc290419Sopenharmony_ci        childRet = RSA_verify(NID_sha256, reinterpret_cast<const unsigned char *>(token),
427cc290419Sopenharmony_ci                              RSA_TOKEN_SIZE, reinterpret_cast<const unsigned char *>(sig),
428cc290419Sopenharmony_ci                              siglen, rsa);
429cc290419Sopenharmony_ci        RSA_free(rsa);
430cc290419Sopenharmony_ci        if (childRet) {
431cc290419Sopenharmony_ci            ret = 1;
432cc290419Sopenharmony_ci            break;
433cc290419Sopenharmony_ci        }
434cc290419Sopenharmony_ci    }
435cc290419Sopenharmony_ci    FreeKey(true, &listPublicKey);
436cc290419Sopenharmony_ci    return ret;
437cc290419Sopenharmony_ci}
438cc290419Sopenharmony_ci
439cc290419Sopenharmony_civoid LoadDaemonKey(list<void *> *listPublicKey)
440cc290419Sopenharmony_ci{
441cc290419Sopenharmony_ci#ifdef HDC_PCDEBUG
442cc290419Sopenharmony_ci    char keyPaths[][BUF_SIZE_SMALL] = { "/root/.harmony/hdckey.pub" };
443cc290419Sopenharmony_ci#else
444cc290419Sopenharmony_ci    char keyPaths[][BUF_SIZE_SMALL] = { "/data/service/el1/public/hdc/hdc_keys" };
445cc290419Sopenharmony_ci#endif
446cc290419Sopenharmony_ci    int num = sizeof(keyPaths) / sizeof(keyPaths[0]);
447cc290419Sopenharmony_ci    struct stat buf;
448cc290419Sopenharmony_ci
449cc290419Sopenharmony_ci    for (int i = 0; i < num; ++i) {
450cc290419Sopenharmony_ci        char *p = keyPaths[i];
451cc290419Sopenharmony_ci        if (!stat(p, &buf)) {
452cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "Loading keys from '%s'", p);
453cc290419Sopenharmony_ci            ReadDaemonKeys(p, listPublicKey);
454cc290419Sopenharmony_ci        }
455cc290419Sopenharmony_ci    }
456cc290419Sopenharmony_ci}
457cc290419Sopenharmony_ci
458cc290419Sopenharmony_cibool PostUIConfirm(string publicKey)
459cc290419Sopenharmony_ci{
460cc290419Sopenharmony_ci    // Because the Hi3516 development board has no UI support for the time being, all public keys are received and
461cc290419Sopenharmony_ci    // By default, the system UI will record the public key /data/misc/hdc/hdckey/data/misc/hdc/hdckey
462cc290419Sopenharmony_ci    return true;
463cc290419Sopenharmony_ci}
464cc290419Sopenharmony_ci#endif  // HDC_HOST
465cc290419Sopenharmony_ci
466cc290419Sopenharmony_ci// --------------------------------------common code------------------------------------------
467cc290419Sopenharmony_cibool KeylistIncrement(list<void *> *listKey, uint8_t &authKeyIndex, void **out)
468cc290419Sopenharmony_ci{
469cc290419Sopenharmony_ci    if (!listKey->size()) {
470cc290419Sopenharmony_ci#ifdef HDC_HOST
471cc290419Sopenharmony_ci        LoadHostUserKey(listKey);
472cc290419Sopenharmony_ci#else
473cc290419Sopenharmony_ci        LoadDaemonKey(listKey);
474cc290419Sopenharmony_ci#endif
475cc290419Sopenharmony_ci    }
476cc290419Sopenharmony_ci    if (authKeyIndex == listKey->size()) {
477cc290419Sopenharmony_ci        // all finish
478cc290419Sopenharmony_ci        return false;
479cc290419Sopenharmony_ci    }
480cc290419Sopenharmony_ci    auto listIndex = listKey->begin();
481cc290419Sopenharmony_ci    std::advance(listIndex, ++authKeyIndex);
482cc290419Sopenharmony_ci    *out = *listIndex;
483cc290419Sopenharmony_ci    if (!*out) {
484cc290419Sopenharmony_ci        return false;
485cc290419Sopenharmony_ci    }
486cc290419Sopenharmony_ci    return true;
487cc290419Sopenharmony_ci}
488cc290419Sopenharmony_ci
489cc290419Sopenharmony_civoid FreeKey(bool publicOrPrivate, list<void *> *listKey)
490cc290419Sopenharmony_ci{
491cc290419Sopenharmony_ci    for (auto &&v : *listKey) {
492cc290419Sopenharmony_ci        if (publicOrPrivate) {
493cc290419Sopenharmony_ci            delete (RSAPublicKey *)v;
494cc290419Sopenharmony_ci            v = nullptr;
495cc290419Sopenharmony_ci        } else {
496cc290419Sopenharmony_ci            RSA_free((RSA *)v);
497cc290419Sopenharmony_ci            v = nullptr;
498cc290419Sopenharmony_ci        }
499cc290419Sopenharmony_ci    }
500cc290419Sopenharmony_ci    listKey->clear();
501cc290419Sopenharmony_ci}
502cc290419Sopenharmony_ci
503cc290419Sopenharmony_ci#ifdef HDC_HOST
504cc290419Sopenharmony_ciEVP_PKEY *GenerateNewKey(void)
505cc290419Sopenharmony_ci{
506cc290419Sopenharmony_ci    bool success = false;
507cc290419Sopenharmony_ci    int bits = RSA_KEY_BITS;
508cc290419Sopenharmony_ci    RSA *rsa = RSA_new();
509cc290419Sopenharmony_ci    BIGNUM *e = BN_new();
510cc290419Sopenharmony_ci    EVP_PKEY *evp = EVP_PKEY_new();
511cc290419Sopenharmony_ci
512cc290419Sopenharmony_ci    while (true) {
513cc290419Sopenharmony_ci        if (!evp || !e || !rsa) {
514cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "allocate key failed");
515cc290419Sopenharmony_ci            break;
516cc290419Sopenharmony_ci        }
517cc290419Sopenharmony_ci
518cc290419Sopenharmony_ci        BN_set_word(e, RSA_F4);
519cc290419Sopenharmony_ci        if (!RSA_generate_key_ex(rsa, bits, e, nullptr)) {
520cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "generate rsa key failed");
521cc290419Sopenharmony_ci            break;
522cc290419Sopenharmony_ci        }
523cc290419Sopenharmony_ci        if (!EVP_PKEY_set1_RSA(evp, rsa)) {
524cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "evp set rsa failed");
525cc290419Sopenharmony_ci            break;
526cc290419Sopenharmony_ci        }
527cc290419Sopenharmony_ci
528cc290419Sopenharmony_ci        WRITE_LOG(LOG_INFO, "generate key pair success");
529cc290419Sopenharmony_ci        success = true;
530cc290419Sopenharmony_ci        break;
531cc290419Sopenharmony_ci    }
532cc290419Sopenharmony_ci
533cc290419Sopenharmony_ci    if (e)
534cc290419Sopenharmony_ci        BN_free(e);
535cc290419Sopenharmony_ci    if (success) {
536cc290419Sopenharmony_ci        return evp;
537cc290419Sopenharmony_ci    }
538cc290419Sopenharmony_ci
539cc290419Sopenharmony_ci    // if fail, need free rsa and evp
540cc290419Sopenharmony_ci    if (rsa)
541cc290419Sopenharmony_ci        RSA_free(rsa);
542cc290419Sopenharmony_ci    if (evp)
543cc290419Sopenharmony_ci        EVP_PKEY_free(evp);
544cc290419Sopenharmony_ci
545cc290419Sopenharmony_ci    return nullptr;
546cc290419Sopenharmony_ci}
547cc290419Sopenharmony_cibool GenerateKeyPair(const string& prikey_filename, const string& pubkey_filename)
548cc290419Sopenharmony_ci{
549cc290419Sopenharmony_ci    bool ret = false;
550cc290419Sopenharmony_ci    FILE *file_prikey = nullptr;
551cc290419Sopenharmony_ci    FILE *file_pubkey = nullptr;
552cc290419Sopenharmony_ci    EVP_PKEY *evp = nullptr;
553cc290419Sopenharmony_ci    mode_t old_mask = umask(077);  // 077:permission
554cc290419Sopenharmony_ci
555cc290419Sopenharmony_ci    while (true) {
556cc290419Sopenharmony_ci        evp = GenerateNewKey();
557cc290419Sopenharmony_ci        if (!evp) {
558cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "generate new key failed");
559cc290419Sopenharmony_ci            break;
560cc290419Sopenharmony_ci        }
561cc290419Sopenharmony_ci
562cc290419Sopenharmony_ci        file_prikey = Base::Fopen(prikey_filename.c_str(), "w");
563cc290419Sopenharmony_ci        if (!file_prikey) {
564cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "open %s failed", prikey_filename.c_str());
565cc290419Sopenharmony_ci            break;
566cc290419Sopenharmony_ci        }
567cc290419Sopenharmony_ci        if (!PEM_write_PrivateKey(file_prikey, evp, nullptr, nullptr, 0, nullptr, nullptr)) {
568cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "write private key failed");
569cc290419Sopenharmony_ci            break;
570cc290419Sopenharmony_ci        }
571cc290419Sopenharmony_ci        file_pubkey = Base::Fopen(pubkey_filename.c_str(), "w");
572cc290419Sopenharmony_ci        if (!file_pubkey) {
573cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "open %s failed", pubkey_filename.c_str());
574cc290419Sopenharmony_ci            break;
575cc290419Sopenharmony_ci        }
576cc290419Sopenharmony_ci        if (!PEM_write_PUBKEY(file_pubkey, evp)) {
577cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "write public key file failed");
578cc290419Sopenharmony_ci            break;
579cc290419Sopenharmony_ci        }
580cc290419Sopenharmony_ci        WRITE_LOG(LOG_INFO, "generate key pair success");
581cc290419Sopenharmony_ci        ret = true;
582cc290419Sopenharmony_ci        break;
583cc290419Sopenharmony_ci    }
584cc290419Sopenharmony_ci
585cc290419Sopenharmony_ci    if (evp)
586cc290419Sopenharmony_ci        EVP_PKEY_free(evp);
587cc290419Sopenharmony_ci    if (file_prikey)
588cc290419Sopenharmony_ci        fclose(file_prikey);
589cc290419Sopenharmony_ci    if (file_pubkey)
590cc290419Sopenharmony_ci        fclose(file_pubkey);
591cc290419Sopenharmony_ci    umask(old_mask);
592cc290419Sopenharmony_ci
593cc290419Sopenharmony_ci    return ret;
594cc290419Sopenharmony_ci}
595cc290419Sopenharmony_ci
596cc290419Sopenharmony_cibool LoadPublicKey(const string& pubkey_filename, string &pubkey)
597cc290419Sopenharmony_ci{
598cc290419Sopenharmony_ci    bool ret = false;
599cc290419Sopenharmony_ci    BIO *bio = nullptr;
600cc290419Sopenharmony_ci    EVP_PKEY *evp = nullptr;
601cc290419Sopenharmony_ci    FILE *file_pubkey = nullptr;
602cc290419Sopenharmony_ci
603cc290419Sopenharmony_ci    do {
604cc290419Sopenharmony_ci        file_pubkey = Base::Fopen(pubkey_filename.c_str(), "r");
605cc290419Sopenharmony_ci        if (!file_pubkey) {
606cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "open file %s failed", pubkey_filename.c_str());
607cc290419Sopenharmony_ci            break;
608cc290419Sopenharmony_ci        }
609cc290419Sopenharmony_ci        evp = PEM_read_PUBKEY(file_pubkey, NULL, NULL, NULL);
610cc290419Sopenharmony_ci        if (!evp) {
611cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "read pubkey from %s failed", pubkey_filename.c_str());
612cc290419Sopenharmony_ci            break;
613cc290419Sopenharmony_ci        }
614cc290419Sopenharmony_ci        bio = BIO_new(BIO_s_mem());
615cc290419Sopenharmony_ci        if (!bio) {
616cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "alloc bio mem failed");
617cc290419Sopenharmony_ci            break;
618cc290419Sopenharmony_ci        }
619cc290419Sopenharmony_ci        if (!PEM_write_bio_PUBKEY(bio, evp)) {
620cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "write bio failed");
621cc290419Sopenharmony_ci            break;
622cc290419Sopenharmony_ci        }
623cc290419Sopenharmony_ci        size_t len = 0;
624cc290419Sopenharmony_ci        char buf[RSA_KEY_BITS] = {0};
625cc290419Sopenharmony_ci        if (BIO_read_ex(bio, buf, sizeof(buf), &len) <= 0) {
626cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "read bio failed");
627cc290419Sopenharmony_ci            break;
628cc290419Sopenharmony_ci        }
629cc290419Sopenharmony_ci        pubkey = string(buf, len);
630cc290419Sopenharmony_ci        ret = true;
631cc290419Sopenharmony_ci        WRITE_LOG(LOG_INFO, "load pubkey from file(%s) success", pubkey_filename.c_str());
632cc290419Sopenharmony_ci    } while (0);
633cc290419Sopenharmony_ci
634cc290419Sopenharmony_ci    if (evp) {
635cc290419Sopenharmony_ci        EVP_PKEY_free(evp);
636cc290419Sopenharmony_ci        evp = nullptr;
637cc290419Sopenharmony_ci    }
638cc290419Sopenharmony_ci    if (bio) {
639cc290419Sopenharmony_ci        BIO_free(bio);
640cc290419Sopenharmony_ci        bio = nullptr;
641cc290419Sopenharmony_ci    }
642cc290419Sopenharmony_ci    if (file_pubkey) {
643cc290419Sopenharmony_ci        fclose(file_pubkey);
644cc290419Sopenharmony_ci        file_pubkey = nullptr;
645cc290419Sopenharmony_ci    }
646cc290419Sopenharmony_ci    return ret;
647cc290419Sopenharmony_ci}
648cc290419Sopenharmony_ci
649cc290419Sopenharmony_cibool TryLoadPublicKey(string &pubkey)
650cc290419Sopenharmony_ci{
651cc290419Sopenharmony_ci    string prikey_filename;
652cc290419Sopenharmony_ci    struct stat status;
653cc290419Sopenharmony_ci    if (!GetUserKeyPath(prikey_filename)) {
654cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "get key path failed");
655cc290419Sopenharmony_ci        return false;
656cc290419Sopenharmony_ci    }
657cc290419Sopenharmony_ci    string pubkey_filename = prikey_filename + ".pub";
658cc290419Sopenharmony_ci    if (stat(prikey_filename.c_str(), &status) == -1) {
659cc290419Sopenharmony_ci        if (!GenerateKeyPair(prikey_filename, pubkey_filename)) {
660cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "generate new key failed");
661cc290419Sopenharmony_ci            return false;
662cc290419Sopenharmony_ci        }
663cc290419Sopenharmony_ci    }
664cc290419Sopenharmony_ci    if (!LoadPublicKey(pubkey_filename, pubkey)) {
665cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "load key failed");
666cc290419Sopenharmony_ci        return false;
667cc290419Sopenharmony_ci    }
668cc290419Sopenharmony_ci
669cc290419Sopenharmony_ci    WRITE_LOG(LOG_INFO, "load pubkey success");
670cc290419Sopenharmony_ci
671cc290419Sopenharmony_ci    return true;
672cc290419Sopenharmony_ci}
673cc290419Sopenharmony_ci
674cc290419Sopenharmony_cibool GetHostName(string &hostname)
675cc290419Sopenharmony_ci{
676cc290419Sopenharmony_ci    int ret;
677cc290419Sopenharmony_ci    char buf[BUF_SIZE_DEFAULT] = {0};
678cc290419Sopenharmony_ci    size_t bufsize = sizeof(buf);
679cc290419Sopenharmony_ci
680cc290419Sopenharmony_ci    ret = uv_os_gethostname(buf, &bufsize);
681cc290419Sopenharmony_ci    if (ret != 0) {
682cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "get hostname failed: %d", ret);
683cc290419Sopenharmony_ci        return false;
684cc290419Sopenharmony_ci    }
685cc290419Sopenharmony_ci
686cc290419Sopenharmony_ci    hostname = string(buf, bufsize);
687cc290419Sopenharmony_ci
688cc290419Sopenharmony_ci    WRITE_LOG(LOG_INFO, "hostname: %s", hostname.c_str());
689cc290419Sopenharmony_ci
690cc290419Sopenharmony_ci    return true;
691cc290419Sopenharmony_ci}
692cc290419Sopenharmony_ci
693cc290419Sopenharmony_cibool GetPublicKeyinfo(string &pubkey_info)
694cc290419Sopenharmony_ci{
695cc290419Sopenharmony_ci    string hostname;
696cc290419Sopenharmony_ci    if (!GetHostName(hostname)) {
697cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "gethostname failed");
698cc290419Sopenharmony_ci        return false;
699cc290419Sopenharmony_ci    }
700cc290419Sopenharmony_ci    string pubkey;
701cc290419Sopenharmony_ci    if (!HdcAuth::TryLoadPublicKey(pubkey)) {
702cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "load public key failed");
703cc290419Sopenharmony_ci        return false;
704cc290419Sopenharmony_ci    }
705cc290419Sopenharmony_ci    pubkey_info = hostname;
706cc290419Sopenharmony_ci    pubkey_info.append(HDC_HOST_DAEMON_BUF_SEPARATOR);
707cc290419Sopenharmony_ci    pubkey_info.append(pubkey);
708cc290419Sopenharmony_ci
709cc290419Sopenharmony_ci    WRITE_LOG(LOG_INFO, "Get pubkey info success");
710cc290419Sopenharmony_ci
711cc290419Sopenharmony_ci    return true;
712cc290419Sopenharmony_ci}
713cc290419Sopenharmony_ci
714cc290419Sopenharmony_cistatic bool LoadPrivateKey(const string& prikey_filename, RSA **rsa, EVP_PKEY **evp)
715cc290419Sopenharmony_ci{
716cc290419Sopenharmony_ci    FILE *file_prikey = nullptr;
717cc290419Sopenharmony_ci    bool ret = false;
718cc290419Sopenharmony_ci
719cc290419Sopenharmony_ci    *rsa = nullptr;
720cc290419Sopenharmony_ci    *evp = nullptr;
721cc290419Sopenharmony_ci    do {
722cc290419Sopenharmony_ci        file_prikey = Base::Fopen(prikey_filename.c_str(), "r");
723cc290419Sopenharmony_ci        if (!file_prikey) {
724cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "open file %s failed", prikey_filename.c_str());
725cc290419Sopenharmony_ci            break;
726cc290419Sopenharmony_ci        }
727cc290419Sopenharmony_ci        *evp = PEM_read_PrivateKey(file_prikey, NULL, NULL, NULL);
728cc290419Sopenharmony_ci        if (*evp == nullptr) {
729cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "read prikey from %s failed", prikey_filename.c_str());
730cc290419Sopenharmony_ci            break;
731cc290419Sopenharmony_ci        }
732cc290419Sopenharmony_ci        *rsa = EVP_PKEY_get1_RSA(*evp);
733cc290419Sopenharmony_ci        ret = true;
734cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "load prikey success");
735cc290419Sopenharmony_ci    } while (0);
736cc290419Sopenharmony_ci
737cc290419Sopenharmony_ci    if (file_prikey) {
738cc290419Sopenharmony_ci        fclose(file_prikey);
739cc290419Sopenharmony_ci        file_prikey = nullptr;
740cc290419Sopenharmony_ci    }
741cc290419Sopenharmony_ci    return ret;
742cc290419Sopenharmony_ci}
743cc290419Sopenharmony_ci
744cc290419Sopenharmony_cistatic bool MakeRsaSign(EVP_PKEY_CTX *ctx, string &result, unsigned char *digest, int digestLen)
745cc290419Sopenharmony_ci{
746cc290419Sopenharmony_ci    size_t signResultLen = 0;
747cc290419Sopenharmony_ci    int signOutLen = 0;
748cc290419Sopenharmony_ci
749cc290419Sopenharmony_ci    // Determine the buffer length
750cc290419Sopenharmony_ci    if (EVP_PKEY_sign(ctx, nullptr, &signResultLen, digest, digestLen) <= 0) {
751cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "get sign result length failed");
752cc290419Sopenharmony_ci        return false;
753cc290419Sopenharmony_ci    }
754cc290419Sopenharmony_ci    try {
755cc290419Sopenharmony_ci        std::unique_ptr<unsigned char[]> signResult = std::make_unique<unsigned char[]>(signResultLen);
756cc290419Sopenharmony_ci        std::unique_ptr<unsigned char[]> signOut = std::make_unique<unsigned char[]>(signResultLen * 2);
757cc290419Sopenharmony_ci        if (EVP_PKEY_sign(ctx, signResult.get(), &signResultLen, digest, digestLen) <=0) {
758cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "sign failed");
759cc290419Sopenharmony_ci            return false;
760cc290419Sopenharmony_ci        }
761cc290419Sopenharmony_ci        signOutLen = EVP_EncodeBlock(signOut.get(), signResult.get(), signResultLen);
762cc290419Sopenharmony_ci        result = string(reinterpret_cast<char *>(signOut.get()), signOutLen);
763cc290419Sopenharmony_ci    } catch (std::exception &e) {
764cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "sign failed for exception %s", e.what());
765cc290419Sopenharmony_ci        return false;
766cc290419Sopenharmony_ci    }
767cc290419Sopenharmony_ci
768cc290419Sopenharmony_ci    WRITE_LOG(LOG_INFO, "sign success, and EVP_EncodeBlock is %s", result.c_str());
769cc290419Sopenharmony_ci    return true;
770cc290419Sopenharmony_ci}
771cc290419Sopenharmony_ci
772cc290419Sopenharmony_cistatic bool RsaSign(string &buf, EVP_PKEY *signKey)
773cc290419Sopenharmony_ci{
774cc290419Sopenharmony_ci    unsigned char sha512Hash[SHA512_DIGEST_LENGTH];
775cc290419Sopenharmony_ci    EVP_PKEY_CTX *ctx = nullptr;
776cc290419Sopenharmony_ci    bool signRet = false;
777cc290419Sopenharmony_ci
778cc290419Sopenharmony_ci    do {
779cc290419Sopenharmony_ci        ctx = EVP_PKEY_CTX_new(signKey, nullptr);
780cc290419Sopenharmony_ci        if (ctx == nullptr) {
781cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "EVP_PKEY_CTX_new failed");
782cc290419Sopenharmony_ci            break;
783cc290419Sopenharmony_ci        }
784cc290419Sopenharmony_ci        if (EVP_PKEY_sign_init(ctx) <= 0) {
785cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "EVP_PKEY_CTX_new failed");
786cc290419Sopenharmony_ci            break;
787cc290419Sopenharmony_ci        }
788cc290419Sopenharmony_ci        if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0 ||
789cc290419Sopenharmony_ci            EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, RSA_PSS_SALTLEN_DIGEST) <= 0) {
790cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "set saltlen or padding failed");
791cc290419Sopenharmony_ci            break;
792cc290419Sopenharmony_ci        }
793cc290419Sopenharmony_ci        if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha512()) <= 0) {
794cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "EVP_PKEY_CTX_set_signature_md failed");
795cc290419Sopenharmony_ci            break;
796cc290419Sopenharmony_ci        }
797cc290419Sopenharmony_ci        SHA512(reinterpret_cast<const unsigned char *>(buf.c_str()), buf.size(), sha512Hash);
798cc290419Sopenharmony_ci        signRet = MakeRsaSign(ctx, buf, sha512Hash, sizeof(sha512Hash));
799cc290419Sopenharmony_ci    } while (0);
800cc290419Sopenharmony_ci
801cc290419Sopenharmony_ci    if (ctx != nullptr) {
802cc290419Sopenharmony_ci        EVP_PKEY_CTX_free(ctx);
803cc290419Sopenharmony_ci    }
804cc290419Sopenharmony_ci    return signRet;
805cc290419Sopenharmony_ci}
806cc290419Sopenharmony_ci
807cc290419Sopenharmony_cistatic bool RsaEncrypt(string &buf, RSA *rsa)
808cc290419Sopenharmony_ci{
809cc290419Sopenharmony_ci    int signOriSize;
810cc290419Sopenharmony_ci    int signOutSize;
811cc290419Sopenharmony_ci    unsigned char signOri[BUF_SIZE_DEFAULT2] = { 0 };
812cc290419Sopenharmony_ci    unsigned char *signOut = nullptr;
813cc290419Sopenharmony_ci    int inSize = buf.size();
814cc290419Sopenharmony_ci    const unsigned char *in = reinterpret_cast<const unsigned char *>(buf.c_str());
815cc290419Sopenharmony_ci
816cc290419Sopenharmony_ci    signOriSize = RSA_private_encrypt(inSize, in, signOri, rsa, RSA_PKCS1_PADDING);
817cc290419Sopenharmony_ci    if (signOriSize <= 0) {
818cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "encrypt failed");
819cc290419Sopenharmony_ci        return false;
820cc290419Sopenharmony_ci    }
821cc290419Sopenharmony_ci    signOut = new(std::nothrow) unsigned char[signOriSize * 2];
822cc290419Sopenharmony_ci    if (signOut == nullptr) {
823cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "alloc mem failed");
824cc290419Sopenharmony_ci        return false;
825cc290419Sopenharmony_ci    }
826cc290419Sopenharmony_ci    signOutSize = EVP_EncodeBlock(signOut, signOri, signOriSize);
827cc290419Sopenharmony_ci    if (signOutSize <= 0) {
828cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "encode buf failed");
829cc290419Sopenharmony_ci        delete[] signOut;
830cc290419Sopenharmony_ci        signOut = nullptr;
831cc290419Sopenharmony_ci        return false;
832cc290419Sopenharmony_ci    }
833cc290419Sopenharmony_ci
834cc290419Sopenharmony_ci    buf = string(reinterpret_cast<char *>(signOut), signOutSize);
835cc290419Sopenharmony_ci    WRITE_LOG(LOG_INFO, "sign success");
836cc290419Sopenharmony_ci    delete[] signOut;
837cc290419Sopenharmony_ci    signOut = nullptr;
838cc290419Sopenharmony_ci
839cc290419Sopenharmony_ci    return true;
840cc290419Sopenharmony_ci}
841cc290419Sopenharmony_ci
842cc290419Sopenharmony_cibool RsaSignAndBase64(string &buf, AuthVerifyType type)
843cc290419Sopenharmony_ci{
844cc290419Sopenharmony_ci    RSA *rsa = nullptr;
845cc290419Sopenharmony_ci    EVP_PKEY *evp = nullptr;
846cc290419Sopenharmony_ci    string prikeyFileName;
847cc290419Sopenharmony_ci    bool signResult = false;
848cc290419Sopenharmony_ci
849cc290419Sopenharmony_ci    if (!GetUserKeyPath(prikeyFileName)) {
850cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "get key path failed");
851cc290419Sopenharmony_ci        return false;
852cc290419Sopenharmony_ci    }
853cc290419Sopenharmony_ci    if (!LoadPrivateKey(prikeyFileName, &rsa, &evp)) {
854cc290419Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "load prikey from file(%s) failed", prikeyFileName.c_str());
855cc290419Sopenharmony_ci        return false;
856cc290419Sopenharmony_ci    }
857cc290419Sopenharmony_ci    if (type == AuthVerifyType::RSA_3072_SHA512) {
858cc290419Sopenharmony_ci        signResult = RsaSign(buf, evp);
859cc290419Sopenharmony_ci    } else {
860cc290419Sopenharmony_ci        signResult = RsaEncrypt(buf, rsa);
861cc290419Sopenharmony_ci    }
862cc290419Sopenharmony_ci    if (rsa != nullptr) {
863cc290419Sopenharmony_ci        RSA_free(rsa);
864cc290419Sopenharmony_ci    }
865cc290419Sopenharmony_ci    if (evp != nullptr) {
866cc290419Sopenharmony_ci        EVP_PKEY_free(evp);
867cc290419Sopenharmony_ci    }
868cc290419Sopenharmony_ci
869cc290419Sopenharmony_ci    return signResult;
870cc290419Sopenharmony_ci}
871cc290419Sopenharmony_ci#endif
872cc290419Sopenharmony_ci}
873