• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "auth.h"
16 #include <openssl/evp.h>
17 #include <openssl/objects.h>
18 #include <openssl/pem.h>
19 #include <openssl/rsa.h>
20 #include <openssl/sha.h>
21 #include <openssl/err.h>
22 #include <fstream>
23 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
24 #include "password.h"
25 #endif
26 
27 using namespace Hdc;
28 #define BIGNUMTOBIT 32
29 
30 namespace HdcAuth {
31 // ---------------------------------------Cheat compiler---------------------------------------------------------
32 #ifdef HDC_HOST
33 
AuthVerify(uint8_t * token,uint8_t * sig,int siglen)34 bool AuthVerify(uint8_t *token, uint8_t *sig, int siglen)
35 {
36     return false;
37 };
PostUIConfirm(string publicKey)38 bool PostUIConfirm(string publicKey)
39 {
40     return false;
41 }
42 
43 #else  // daemon
44 
45 bool GenerateKey(const char *file)
46 {
47     return false;
48 };
49 int AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig)
50 {
51     return 0;
52 };
53 int GetPublicKeyFileBuf(unsigned char *data, size_t len)
54 {
55     return 0;
56 }
57 
58 #endif
59 // ------------------------------------------------------------------------------------------------
60 
61 const uint32_t RSANUMBYTES = 512;  // 4096 bit key length
62 const uint32_t RSANUMWORDS = (RSANUMBYTES / sizeof(uint32_t));
63 struct RSAPublicKey {
64     int wordModulusSize;            // Length of n[] in number of uint32_t */
65     uint32_t rsaN0inv;              // -1 / n[0] mod 2^32
66     uint32_t modulus[RSANUMWORDS];  // modulus as little endian array
67     uint32_t rr[RSANUMWORDS];       // R^2 as little endian array
68     BN_ULONG exponent;                   // 3 or 65537
69 };
70 
71 #ifdef HDC_HOST
72 // Convert OpenSSL RSA private key to pre-computed RSAPublicKey format
RSA2RSAPublicKey(RSA * rsa,RSAPublicKey * publicKey)73 int RSA2RSAPublicKey(RSA *rsa, RSAPublicKey *publicKey)
74 {
75     int result = 1;
76     unsigned int i;
77     BN_CTX *ctx = BN_CTX_new();
78     BIGNUM *r32 = BN_new();
79     BIGNUM *rsaRR = BN_new();
80     BIGNUM *rsaR = BN_new();
81     BIGNUM *rsaRem = BN_new();
82     BIGNUM *rsaN0inv = BN_new();
83 #ifdef OPENSSL_IS_BORINGSSL
84     // boringssl
85     BIGNUM *n = BN_new();
86     BN_copy(n, rsa->n);
87     publicKey->exponent = BN_get_word(rsa->e);
88 #else
89     // openssl
90 #if OPENSSL_VERSION_NUMBER >= 0x10100005L
91     BIGNUM *n = (BIGNUM *)RSA_get0_n(rsa);
92     publicKey->exponent = BN_get_word(RSA_get0_e(rsa));
93 #else
94     BIGNUM *n = BN_new();
95     BN_copy(n, rsa->n);
96     publicKey->exponent = BN_get_word(rsa->e);
97 #endif
98 
99 #endif  // OPENSSL_IS_BORINGSSL
100     while (true) {
101         if (RSA_size(rsa) != RSANUMBYTES) {
102             result = 0;
103             break;
104         }
105 
106         BN_set_bit(r32, BIGNUMTOBIT);
107         BN_set_bit(rsaR, RSANUMWORDS * BIGNUMTOBIT);
108         BN_mod_sqr(rsaRR, rsaR, n, ctx);
109         BN_div(nullptr, rsaRem, n, r32, ctx);
110         BN_mod_inverse(rsaN0inv, rsaRem, r32, ctx);
111         publicKey->wordModulusSize = RSANUMWORDS;
112         publicKey->rsaN0inv = 0 - BN_get_word(rsaN0inv);
113         for (i = 0; i < RSANUMWORDS; ++i) {
114             BN_div(rsaRR, rsaRem, rsaRR, r32, ctx);
115             publicKey->rr[i] = BN_get_word(rsaRem);
116             BN_div(n, rsaRem, n, r32, ctx);
117             publicKey->modulus[i] = BN_get_word(rsaRem);
118         }
119         break;
120     }
121 
122     BN_free(rsaR);
123     BN_free(rsaRR);
124     BN_free(n);
125     BN_free(r32);
126     BN_free(rsaN0inv);
127     BN_free(rsaRem);
128     BN_CTX_free(ctx);
129     return result;
130 }
131 
GetUserInfo(char * buf,size_t len)132 int GetUserInfo(char *buf, size_t len)
133 {
134     char hostname[BUF_SIZE_DEFAULT];
135     char username[BUF_SIZE_DEFAULT];
136     uv_passwd_t pwd;
137     int ret = -1;
138     size_t bufSize = sizeof(hostname);
139     if (uv_os_gethostname(hostname, &bufSize) < 0 && EOK != strcpy_s(hostname, sizeof(hostname), "unknown")) {
140         return ERR_API_FAIL;
141     }
142     if (!uv_os_get_passwd(&pwd) && !strcpy_s(username, sizeof(username), pwd.username)) {
143         ret = 0;
144     }
145     uv_os_free_passwd(&pwd);
146     if (ret < 0 && EOK != strcpy_s(username, sizeof(username), "unknown")) {
147         return ERR_API_FAIL;
148     }
149     if (snprintf_s(buf, len, len - 1, " %s@%s", username, hostname) < 0) {
150         return ERR_BUF_OVERFLOW;
151     }
152     return RET_SUCCESS;
153 }
154 
WritePublicKeyfile(RSA * private_key,const char * private_key_path)155 int WritePublicKeyfile(RSA *private_key, const char *private_key_path)
156 {
157     RSAPublicKey publicKey;
158     char info[BUF_SIZE_DEFAULT];
159     int ret = 0;
160     string path = private_key_path + string(".pub");
161 
162     ret = RSA2RSAPublicKey(private_key, &publicKey);
163     if (!ret) {
164         WRITE_LOG(LOG_DEBUG, "Failed to convert to publickey\n");
165         return 0;
166     }
167     vector<uint8_t> vec = Base::Base64Encode((const uint8_t *)&publicKey, sizeof(RSAPublicKey));
168     if (!vec.size()) {
169         return 0;
170     }
171     GetUserInfo(info, sizeof(info));
172     vec.insert(vec.end(), (uint8_t *)info, (uint8_t *)info + strlen(info));
173     ret = Base::WriteBinFile(path.c_str(), vec.data(), vec.size(), true);
174     return ret >= 0 ? 1 : 0;
175 }
176 
GenerateKey(const char * file)177 bool GenerateKey(const char *file)
178 {
179 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
180     Base::PrintMessage("[E002105] Unsupport command]");
181     return false;
182 #endif
183     EVP_PKEY *publicKey = EVP_PKEY_new();
184     BIGNUM *exponent = BN_new();
185     RSA *rsa = RSA_new();
186     int bits = 4096;
187     mode_t old_mask;
188     FILE *fKey = nullptr;
189     bool ret = false;
190 
191     while (true) {
192         WRITE_LOG(LOG_DEBUG, "generate_key '%s'\n", file);
193         if (!publicKey || !exponent || !rsa) {
194             WRITE_LOG(LOG_DEBUG, "Failed to allocate key");
195             break;
196         }
197 
198         BN_set_word(exponent, RSA_F4);
199         RSA_generate_key_ex(rsa, bits, exponent, nullptr);
200         EVP_PKEY_set1_RSA(publicKey, rsa);
201         old_mask = umask(077);  // 077:permission
202 
203         fKey = Base::Fopen(file, "w");
204         if (!fKey) {
205             WRITE_LOG(LOG_DEBUG, "Failed to open '%s'\n", file);
206             umask(old_mask);
207             break;
208         }
209         umask(old_mask);
210         if (!PEM_write_PrivateKey(fKey, publicKey, nullptr, nullptr, 0, nullptr, nullptr)) {
211             WRITE_LOG(LOG_DEBUG, "Failed to write key");
212             break;
213         }
214         if (!WritePublicKeyfile(rsa, file)) {
215             WRITE_LOG(LOG_DEBUG, "Failed to write public key");
216             break;
217         }
218         ret = true;
219         break;
220     }
221 
222     EVP_PKEY_free(publicKey);
223     BN_free(exponent);
224     if (fKey)
225         fclose(fKey);
226     return ret;
227 }
228 
ReadKey(const char * file,list<void * > * listPrivateKey)229 bool ReadKey(const char *file, list<void *> *listPrivateKey)
230 {
231     FILE *f = nullptr;
232     bool ret = false;
233 
234     if (file == nullptr || listPrivateKey == nullptr) {
235         WRITE_LOG(LOG_FATAL, "file or listPrivateKey is null");
236         return ret;
237     }
238     while (true) {
239         if (!(f = fopen(file, "r"))) {
240             break;
241         }
242         RSA *rsa = RSA_new();
243         if (!PEM_read_RSAPrivateKey(f, &rsa, nullptr, nullptr)) {
244             RSA_free(rsa);
245             break;
246         }
247         listPrivateKey->push_back((void *)rsa);
248         ret = true;
249         break;
250     }
251     if (f) {
252         fclose(f);
253     }
254     return ret;
255 }
256 
GetUserKeyPath(string & path)257 bool GetUserKeyPath(string &path)
258 {
259     struct stat status;
260     const char harmoneyPath[] = ".harmony";
261     const char hdcKeyFile[] = "hdckey";
262     char buf[BUF_SIZE_DEFAULT];
263     size_t len = BUF_SIZE_DEFAULT;
264     // $home
265     if (uv_os_homedir(buf, &len) < 0)
266         return false;
267     string dir = string(buf) + Base::GetPathSep() + string(harmoneyPath) + Base::GetPathSep();
268     path = Base::CanonicalizeSpecPath(dir);
269     if (path.empty()) {
270         path = dir;
271     } else {
272         path += Base::GetPathSep(); // bugfix for unix platform create key file not in dir.
273     }
274     if (stat(path.c_str(), &status)) {
275         uv_fs_t req;
276         uv_fs_mkdir(nullptr, &req, path.c_str(), 0750, nullptr);  // 0750:permission
277         uv_fs_req_cleanup(&req);
278         uv_fs_stat(nullptr, &req, path.c_str(), nullptr);
279         uv_fs_req_cleanup(&req);
280         if (req.result < 0) {
281             WRITE_LOG(LOG_FATAL, "Cannot mkdir '%s'", path.c_str());
282             return false;
283         }
284     }
285     path += hdcKeyFile;
286     return true;
287 }
288 
LoadHostUserKey(list<void * > * listPrivateKey)289 bool LoadHostUserKey(list<void *> *listPrivateKey)
290 {
291     struct stat status;
292     string path;
293     if (!GetUserKeyPath(path)) {
294         return false;
295     }
296     if (stat(path.c_str(), &status) == -1) {
297         if (!GenerateKey(path.c_str())) {
298             WRITE_LOG(LOG_DEBUG, "Failed to generate new key");
299             return false;
300         }
301     }
302     if (!ReadKey(path.c_str(), listPrivateKey)) {
303         return false;
304     }
305     return true;
306 }
307 
AuthSign(void * rsa,const unsigned char * token,size_t tokenSize,void * sig)308 int AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig)
309 {
310     unsigned int len;
311     if (!RSA_sign(NID_sha256, token, tokenSize, (unsigned char *)sig, &len, (RSA *)rsa)) {
312         return 0;
313     }
314     return static_cast<int>(len);
315 }
316 
GetPublicKeyFileBuf(unsigned char * data,size_t len)317 int GetPublicKeyFileBuf(unsigned char *data, size_t len)
318 {
319     string path;
320     int ret;
321 
322     if (!GetUserKeyPath(path)) {
323         return 0;
324     }
325     path += ".pub";
326     ret = Base::ReadBinFile(path.c_str(), (void **)data, len);
327     if (ret <= 0) {
328         return 0;
329     }
330     data[ret] = '\0';
331     return ret + 1;
332 }
333 
334 #else  // daemon
335 
RSAPublicKey2RSA(const uint8_t * keyBuf,RSA ** key)336 bool RSAPublicKey2RSA(const uint8_t *keyBuf, RSA **key)
337 {
338     const int pubKeyModulusSize = 256;
339     const int pubKeyModulusSizeWords = pubKeyModulusSize / 4;
340 
341     const RSAPublicKey *keyStruct = reinterpret_cast<const RSAPublicKey *>(keyBuf);
342     bool ret = false;
343     uint8_t modulusBuffer[pubKeyModulusSize];
344     RSA *newKey = RSA_new();
345     if (!newKey) {
346         goto cleanup;
347     }
348     if (keyStruct->wordModulusSize != pubKeyModulusSizeWords) {
349         goto cleanup;
350     }
351     if (memcpy_s(modulusBuffer, sizeof(modulusBuffer), keyStruct->modulus, sizeof(modulusBuffer)) != EOK) {
352         goto cleanup;
353     }
354     Base::ReverseBytes(modulusBuffer, sizeof(modulusBuffer));
355 
356 #ifdef OPENSSL_IS_BORINGSSL
357     // boringssl
358     newKey->n = BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr);
359     newKey->e = BN_new();
360     if (!newKey->e || !BN_set_word(newKey->e, keyStruct->exponent) || !newKey->n) {
361         goto cleanup;
362     }
363 #else
364     // openssl
365 #if OPENSSL_VERSION_NUMBER >= 0x10100005L
366     RSA_set0_key(newKey, BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr), BN_new(), BN_new());
367 #else
368     newKey->n = BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr);
369     newKey->e = BN_new();
370     if (!newKey->e || !BN_set_word(newKey->e, keyStruct->exponent) || !newKey->n) {
371         goto cleanup;
372     }
373 #endif
374 #endif
375 
376     *key = newKey;
377     ret = true;
378 
379 cleanup:
380     if (!ret && newKey) {
381         RSA_free(newKey);
382     }
383     return ret;
384 }
385 
ReadDaemonKeys(const char * file,list<void * > * listPublicKey)386 void ReadDaemonKeys(const char *file, list<void *> *listPublicKey)
387 {
388     char buf[BUF_SIZE_DEFAULT2] = { 0 };
389     char *sep = nullptr;
390     int ret;
391     FILE *f = Base::Fopen(file, "re");
392     if (!f) {
393         WRITE_LOG(LOG_DEBUG, "Can't open '%s'", file);
394         return;
395     }
396     while (fgets(buf, sizeof(buf), f)) {
397         RSAPublicKey *key = new RSAPublicKey();
398         if (!key) {
399             break;
400         }
401         sep = strpbrk(buf, " \t");
402         if (sep) {
403             *sep = '\0';
404         }
405         ret = Base::Base64DecodeBuf(reinterpret_cast<uint8_t *>(buf), strlen(buf), reinterpret_cast<uint8_t *>(key));
406         if (ret != sizeof(RSAPublicKey)) {
407             WRITE_LOG(LOG_DEBUG, "%s: Invalid base64 data ret=%d", file, ret);
408             delete key;
409             continue;
410         }
411 
412         if (key->wordModulusSize != RSANUMWORDS) {
413             WRITE_LOG(LOG_DEBUG, "%s: Invalid key len %d\n", file, key->wordModulusSize);
414             delete key;
415             continue;
416         }
417         listPublicKey->push_back(key);
418     }
419     fclose(f);
420 }
421 
AuthVerify(uint8_t * token,uint8_t * sig,int siglen)422 bool AuthVerify(uint8_t *token, uint8_t *sig, int siglen)
423 {
424     list<void *> listPublicKey;
425     uint8_t authKeyIndex = 0;
426     void *ptr = nullptr;
427     int ret = 0;
428     int childRet = 0;
429     while (KeylistIncrement(&listPublicKey, authKeyIndex, &ptr)) {
430         RSA *rsa = nullptr;
431         if (!RSAPublicKey2RSA((const uint8_t *)ptr, &rsa)) {
432             break;
433         }
434         childRet = RSA_verify(NID_sha256, reinterpret_cast<const unsigned char *>(token),
435                               RSA_TOKEN_SIZE, reinterpret_cast<const unsigned char *>(sig),
436                               siglen, rsa);
437         RSA_free(rsa);
438         if (childRet) {
439             ret = 1;
440             break;
441         }
442     }
443     FreeKey(true, &listPublicKey);
444     return ret;
445 }
446 
LoadDaemonKey(list<void * > * listPublicKey)447 void LoadDaemonKey(list<void *> *listPublicKey)
448 {
449 #ifdef HDC_PCDEBUG
450     char keyPaths[][BUF_SIZE_SMALL] = { "/root/.harmony/hdckey.pub" };
451 #else
452     char keyPaths[][BUF_SIZE_SMALL] = { "/data/service/el1/public/hdc/hdc_keys" };
453 #endif
454     int num = sizeof(keyPaths) / sizeof(keyPaths[0]);
455     struct stat buf;
456 
457     for (int i = 0; i < num; ++i) {
458         char *p = keyPaths[i];
459         if (!stat(p, &buf)) {
460             WRITE_LOG(LOG_DEBUG, "Loading keys from '%s'", p);
461             ReadDaemonKeys(p, listPublicKey);
462         }
463     }
464 }
465 
PostUIConfirm(string publicKey)466 bool PostUIConfirm(string publicKey)
467 {
468     // Because the Hi3516 development board has no UI support for the time being, all public keys are received and
469     // By default, the system UI will record the public key /data/misc/hdc/hdckey/data/misc/hdc/hdckey
470     return true;
471 }
472 #endif  // HDC_HOST
473 
474 // --------------------------------------common code------------------------------------------
KeylistIncrement(list<void * > * listKey,uint8_t & authKeyIndex,void ** out)475 bool KeylistIncrement(list<void *> *listKey, uint8_t &authKeyIndex, void **out)
476 {
477     if (!listKey->size()) {
478 #ifdef HDC_HOST
479         LoadHostUserKey(listKey);
480 #else
481         LoadDaemonKey(listKey);
482 #endif
483     }
484     if (authKeyIndex == listKey->size()) {
485         // all finish
486         return false;
487     }
488     auto listIndex = listKey->begin();
489     std::advance(listIndex, ++authKeyIndex);
490     *out = *listIndex;
491     if (!*out) {
492         return false;
493     }
494     return true;
495 }
496 
FreeKey(bool publicOrPrivate,list<void * > * listKey)497 void FreeKey(bool publicOrPrivate, list<void *> *listKey)
498 {
499     for (auto &&v : *listKey) {
500         if (publicOrPrivate) {
501             delete (RSAPublicKey *)v;
502             v = nullptr;
503         } else {
504             RSA_free((RSA *)v);
505             v = nullptr;
506         }
507     }
508     listKey->clear();
509 }
510 
511 #ifdef HDC_HOST
GenerateNewKey(void)512 EVP_PKEY *GenerateNewKey(void)
513 {
514     bool success = false;
515     int bits = RSA_KEY_BITS;
516     RSA *rsa = RSA_new();
517     BIGNUM *e = BN_new();
518     EVP_PKEY *evp = EVP_PKEY_new();
519 
520     while (true) {
521         if (!evp || !e || !rsa) {
522             WRITE_LOG(LOG_FATAL, "allocate key failed");
523             break;
524         }
525 
526         BN_set_word(e, RSA_F4);
527         if (!RSA_generate_key_ex(rsa, bits, e, nullptr)) {
528             WRITE_LOG(LOG_FATAL, "generate rsa key failed");
529             break;
530         }
531         if (!EVP_PKEY_set1_RSA(evp, rsa)) {
532             WRITE_LOG(LOG_FATAL, "evp set rsa failed");
533             break;
534         }
535 
536         WRITE_LOG(LOG_INFO, "generate key pair success");
537         success = true;
538         break;
539     }
540 
541     if (e)
542         BN_free(e);
543     if (success) {
544         return evp;
545     }
546 
547     // if fail, need free rsa and evp
548     if (rsa)
549         RSA_free(rsa);
550     if (evp)
551         EVP_PKEY_free(evp);
552 
553     return nullptr;
554 }
555 
WritePublicFile(const std::string & fileName,EVP_PKEY * evp)556 static bool WritePublicFile(const std::string& fileName, EVP_PKEY *evp)
557 {
558     FILE *fp = nullptr;
559     fp = Base::Fopen(fileName.c_str(), "w");
560     if (fp == nullptr) {
561         WRITE_LOG(LOG_FATAL, "open %s failed", fileName.c_str());
562         return false;
563     }
564     if (!PEM_write_PUBKEY(fp, evp)) {
565         WRITE_LOG(LOG_FATAL, "write public key file %s failed", fileName.c_str());
566         (void)fclose(fp);
567         return false;
568     }
569     (void)fclose(fp);
570     return true;
571 }
572 
573 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
WritePrivatePwdFile(const std::string & fileName,const std::string & encryptPwd)574 static bool WritePrivatePwdFile(const std::string& fileName, const std::string& encryptPwd)
575 {
576     return Base::WriteToFile(fileName, encryptPwd, std::ios::out | std::ios::trunc);
577 }
578 #endif
579 
WritePrivateFile(const std::string & fileName,EVP_PKEY * evp)580 static bool WritePrivateFile(const std::string& fileName, EVP_PKEY *evp)
581 {
582     FILE *fp = nullptr;
583 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
584     Hdc::HdcPassword pwd(HDC_PRIVATE_KEY_FILE_PWD_KEY_ALIAS);
585     pwd.GeneratePassword();
586     if (!pwd.EncryptPwd()) {
587         WRITE_LOG(LOG_FATAL, "encrypt pwd failed");
588         return false;
589     }
590     std::pair<uint8_t*, int> pwdValue = pwd.GetPassword();
591 #endif
592     fp = Base::Fopen(fileName.c_str(), "w");
593     if (fp == nullptr) {
594         WRITE_LOG(LOG_FATAL, "open %s failed", fileName.c_str());
595         return false;
596     }
597 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
598     if (!PEM_write_PrivateKey(fp, evp, EVP_aes_256_cbc(), pwdValue.first, pwdValue.second, nullptr, nullptr)) {
599 #else
600     if (!PEM_write_PrivateKey(fp, evp, nullptr, nullptr, 0, nullptr, nullptr)) {
601 #endif
602         WRITE_LOG(LOG_FATAL, "write private key failed");
603         (void)fclose(fp);
604         return false;
605     }
606     (void)fclose(fp);
607 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
608     if (!WritePrivatePwdFile(fileName + ".key", pwd.GetEncryptPassword())) {
609         WRITE_LOG(LOG_FATAL, "write private key pwd failed");
610         return false;
611     }
612 #endif
613     return true;
614 }
615 
616 bool GenerateKeyPair(const string& prikey_filename, const string& pubkey_filename)
617 {
618     bool ret = false;
619     EVP_PKEY *evp = nullptr;
620 #ifdef __OHOS__
621     mode_t old_mask = umask(027);  // 027:permission
622 #else
623     mode_t old_mask = umask(077);  // 077:permission
624 #endif
625 
626     while (true) {
627         evp = GenerateNewKey();
628         if (!evp) {
629             WRITE_LOG(LOG_FATAL, "generate new key failed");
630             break;
631         }
632 
633         if (!WritePublicFile(pubkey_filename, evp)) {
634             break;
635         }
636 
637         if (!WritePrivateFile(prikey_filename, evp)) {
638             break;
639         }
640         WRITE_LOG(LOG_INFO, "generate key pair success");
641         ret = true;
642         break;
643     }
644 
645     if (evp) {
646         EVP_PKEY_free(evp);
647     }
648     umask(old_mask);
649     return ret;
650 }
651 
652 bool LoadPublicKey(const string& pubkey_filename, string &pubkey)
653 {
654     bool ret = false;
655     BIO *bio = nullptr;
656     EVP_PKEY *evp = nullptr;
657     FILE *file_pubkey = nullptr;
658 
659     do {
660         file_pubkey = Base::Fopen(pubkey_filename.c_str(), "r");
661         if (!file_pubkey) {
662             WRITE_LOG(LOG_FATAL, "open file %s failed", pubkey_filename.c_str());
663             break;
664         }
665         evp = PEM_read_PUBKEY(file_pubkey, NULL, NULL, NULL);
666         if (!evp) {
667             WRITE_LOG(LOG_FATAL, "read pubkey from %s failed", pubkey_filename.c_str());
668             break;
669         }
670         bio = BIO_new(BIO_s_mem());
671         if (!bio) {
672             WRITE_LOG(LOG_FATAL, "alloc bio mem failed");
673             break;
674         }
675         if (!PEM_write_bio_PUBKEY(bio, evp)) {
676             WRITE_LOG(LOG_FATAL, "write bio failed");
677             break;
678         }
679         size_t len = 0;
680         char buf[RSA_KEY_BITS] = {0};
681         if (BIO_read_ex(bio, buf, sizeof(buf), &len) <= 0) {
682             WRITE_LOG(LOG_FATAL, "read bio failed");
683             break;
684         }
685         pubkey = string(buf, len);
686         ret = true;
687         WRITE_LOG(LOG_INFO, "load pubkey from file(%s) success", pubkey_filename.c_str());
688     } while (0);
689 
690     if (evp) {
691         EVP_PKEY_free(evp);
692         evp = nullptr;
693     }
694     if (bio) {
695         BIO_free(bio);
696         bio = nullptr;
697     }
698     if (file_pubkey) {
699         fclose(file_pubkey);
700         file_pubkey = nullptr;
701     }
702     return ret;
703 }
704 
705 bool TryLoadPublicKey(string &pubkey)
706 {
707     string prikey_filename;
708     struct stat status;
709     if (!GetUserKeyPath(prikey_filename)) {
710         WRITE_LOG(LOG_FATAL, "get key path failed");
711         return false;
712     }
713     string pubkey_filename = prikey_filename + ".pub";
714 #ifdef _WIN32
715     string prikeyFilenameWin = Base::UnicodeToUtf8(prikey_filename.c_str(), true);
716     if (stat(prikeyFilenameWin.c_str(), &status) == -1) {
717 #else
718     if (stat(prikey_filename.c_str(), &status) == -1) {
719 #endif
720         if (!GenerateKeyPair(prikey_filename, pubkey_filename)) {
721             WRITE_LOG(LOG_FATAL, "generate new key failed");
722             return false;
723         }
724     }
725     if (!LoadPublicKey(pubkey_filename, pubkey)) {
726         WRITE_LOG(LOG_FATAL, "load key failed");
727         return false;
728     }
729 
730     WRITE_LOG(LOG_INFO, "load pubkey success");
731 
732     return true;
733 }
734 
735 bool GetHostName(string &hostname)
736 {
737     int ret;
738     char buf[BUF_SIZE_DEFAULT] = {0};
739     size_t bufsize = sizeof(buf);
740 
741     ret = uv_os_gethostname(buf, &bufsize);
742     if (ret != 0) {
743         WRITE_LOG(LOG_FATAL, "get hostname failed: %d", ret);
744         return false;
745     }
746 
747     hostname = string(buf, bufsize);
748 
749     WRITE_LOG(LOG_INFO, "hostname: %s", hostname.c_str());
750 
751     return true;
752 }
753 
754 bool GetPublicKeyinfo(string &pubkey_info)
755 {
756     string hostname;
757     if (!GetHostName(hostname)) {
758         WRITE_LOG(LOG_FATAL, "gethostname failed");
759         return false;
760     }
761     string pubkey;
762     if (!HdcAuth::TryLoadPublicKey(pubkey)) {
763         WRITE_LOG(LOG_FATAL, "load public key failed");
764         return false;
765     }
766     pubkey_info = hostname;
767     pubkey_info.append(HDC_HOST_DAEMON_BUF_SEPARATOR);
768     pubkey_info.append(pubkey);
769 
770     WRITE_LOG(LOG_INFO, "Get pubkey info success");
771 
772     return true;
773 }
774 
775 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
776 bool ReadEncryptKeyFile(const std::string& privateKeyFile, std::vector<uint8_t>& fileData, int needFileLength)
777 {
778     std::string privateKeyKeyFile = privateKeyFile + ".key";
779     std::ifstream inFile(privateKeyKeyFile.c_str(), std::ios::binary);
780     if (!inFile) {
781         WRITE_LOG(LOG_FATAL, "open file %s failed", privateKeyKeyFile.c_str());
782         return false;
783     }
784     fileData.resize(needFileLength);
785     inFile.read(reinterpret_cast<char*>(fileData.data()), needFileLength);
786     if (inFile.eof() || inFile.fail()) {
787         WRITE_LOG(LOG_FATAL, "read file %s failed", privateKeyKeyFile.c_str());
788         inFile.close();
789         return false;
790     }
791     inFile.close();
792     return true;
793 }
794 
795 static uint8_t* GetPlainPwd(const std::string& privateKeyFile)
796 {
797     std::vector<uint8_t> encryptPwd;
798     Hdc::HdcPassword pwd(HDC_PRIVATE_KEY_FILE_PWD_KEY_ALIAS);
799 
800     if (!ReadEncryptKeyFile(privateKeyFile, encryptPwd, pwd.GetEncryptPwdLength())) {
801         return nullptr;
802     }
803     if (!pwd.DecryptPwd(encryptPwd)) {
804         return nullptr;
805     }
806     std::pair<uint8_t*, int> plainPwd = pwd.GetPassword();
807     if (plainPwd.first == nullptr) {
808         return nullptr;
809     }
810     uint8_t *localPwd = new(std::nothrow)uint8_t[plainPwd.second + 1];
811     if (localPwd == nullptr) {
812         WRITE_LOG(LOG_FATAL, "out of mem %d", plainPwd.second);
813         return nullptr;
814     }
815     memcpy_s(localPwd, plainPwd.second, plainPwd.first, plainPwd.second);
816     localPwd[plainPwd.second] = '\0';
817     return localPwd;
818 }
819 #endif
820 
821 static bool LoadPrivateKey(const string& prikey_filename, RSA **rsa, EVP_PKEY **evp)
822 {
823     FILE *file_prikey = nullptr;
824     bool ret = false;
825     *rsa = nullptr;
826     *evp = nullptr;
827 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
828     char *pwd = reinterpret_cast<char*>(GetPlainPwd(prikey_filename));
829     if (pwd == nullptr) {
830         return false;
831     }
832 #endif
833     do {
834         file_prikey = Base::Fopen(prikey_filename.c_str(), "r");
835         if (!file_prikey) {
836             WRITE_LOG(LOG_FATAL, "open file %s failed", prikey_filename.c_str());
837             break;
838         }
839 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
840         *evp = PEM_read_PrivateKey(file_prikey, NULL, NULL, pwd);
841 #else
842         *evp = PEM_read_PrivateKey(file_prikey, NULL, NULL, NULL);
843 #endif
844         if (*evp == nullptr) {
845             WRITE_LOG(LOG_FATAL, "read prikey from %s failed", prikey_filename.c_str());
846             break;
847         }
848         *rsa = EVP_PKEY_get1_RSA(*evp);
849         ret = true;
850         WRITE_LOG(LOG_FATAL, "load prikey success");
851     } while (0);
852 
853 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
854     memset_s(pwd, strlen(pwd), 0, strlen(pwd));
855     delete[] pwd;
856 #endif
857     if (file_prikey) {
858         fclose(file_prikey);
859         file_prikey = nullptr;
860     }
861     return ret;
862 }
863 
864 static bool MakeRsaSign(EVP_PKEY_CTX *ctx, string &result, unsigned char *digest, int digestLen)
865 {
866     size_t signResultLen = 0;
867     int signOutLen = 0;
868 
869     // Determine the buffer length
870     if (EVP_PKEY_sign(ctx, nullptr, &signResultLen, digest, digestLen) <= 0) {
871         WRITE_LOG(LOG_FATAL, "get sign result length failed");
872         return false;
873     }
874     try {
875         std::unique_ptr<unsigned char[]> signResult = std::make_unique<unsigned char[]>(signResultLen);
876         std::unique_ptr<unsigned char[]> signOut = std::make_unique<unsigned char[]>(signResultLen * 2);
877         if (EVP_PKEY_sign(ctx, signResult.get(), &signResultLen, digest, digestLen) <=0) {
878             WRITE_LOG(LOG_FATAL, "sign failed");
879             return false;
880         }
881         signOutLen = EVP_EncodeBlock(signOut.get(), signResult.get(), signResultLen);
882         result = string(reinterpret_cast<char *>(signOut.get()), signOutLen);
883     } catch (std::exception &e) {
884         WRITE_LOG(LOG_FATAL, "sign failed for exception %s", e.what());
885         return false;
886     }
887 
888     WRITE_LOG(LOG_INFO, "sign success");
889     return true;
890 }
891 
892 static bool RsaSign(string &buf, EVP_PKEY *signKey)
893 {
894     unsigned char sha512Hash[SHA512_DIGEST_LENGTH];
895     EVP_PKEY_CTX *ctx = nullptr;
896     bool signRet = false;
897 
898     do {
899         ctx = EVP_PKEY_CTX_new(signKey, nullptr);
900         if (ctx == nullptr) {
901             WRITE_LOG(LOG_FATAL, "EVP_PKEY_CTX_new failed");
902             break;
903         }
904         if (EVP_PKEY_sign_init(ctx) <= 0) {
905             WRITE_LOG(LOG_FATAL, "EVP_PKEY_CTX_new failed");
906             break;
907         }
908         if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0 ||
909             EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, RSA_PSS_SALTLEN_DIGEST) <= 0) {
910             WRITE_LOG(LOG_FATAL, "set saltlen or padding failed");
911             break;
912         }
913         if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha512()) <= 0) {
914             WRITE_LOG(LOG_FATAL, "EVP_PKEY_CTX_set_signature_md failed");
915             break;
916         }
917         SHA512(reinterpret_cast<const unsigned char *>(buf.c_str()), buf.size(), sha512Hash);
918         signRet = MakeRsaSign(ctx, buf, sha512Hash, sizeof(sha512Hash));
919     } while (0);
920 
921     if (ctx != nullptr) {
922         EVP_PKEY_CTX_free(ctx);
923     }
924     return signRet;
925 }
926 
927 static bool RsaEncrypt(string &buf, RSA *rsa)
928 {
929     int signOriSize;
930     int signOutSize;
931     unsigned char signOri[BUF_SIZE_DEFAULT2] = { 0 };
932     unsigned char *signOut = nullptr;
933     int inSize = buf.size();
934     const unsigned char *in = reinterpret_cast<const unsigned char *>(buf.c_str());
935 
936     signOriSize = RSA_private_encrypt(inSize, in, signOri, rsa, RSA_PKCS1_PADDING);
937     if (signOriSize <= 0) {
938         WRITE_LOG(LOG_FATAL, "encrypt failed");
939         return false;
940     }
941     signOut = new(std::nothrow) unsigned char[signOriSize * 2];
942     if (signOut == nullptr) {
943         WRITE_LOG(LOG_FATAL, "alloc mem failed");
944         return false;
945     }
946     signOutSize = EVP_EncodeBlock(signOut, signOri, signOriSize);
947     if (signOutSize <= 0) {
948         WRITE_LOG(LOG_FATAL, "encode buf failed");
949         delete[] signOut;
950         signOut = nullptr;
951         return false;
952     }
953 
954     buf = string(reinterpret_cast<char *>(signOut), signOutSize);
955     WRITE_LOG(LOG_INFO, "sign success");
956     delete[] signOut;
957     signOut = nullptr;
958 
959     return true;
960 }
961 
962 bool RsaSignAndBase64(string &buf, AuthVerifyType type)
963 {
964     RSA *rsa = nullptr;
965     EVP_PKEY *evp = nullptr;
966     string prikeyFileName;
967     bool signResult = false;
968 
969     if (!GetUserKeyPath(prikeyFileName)) {
970         WRITE_LOG(LOG_FATAL, "get key path failed");
971         return false;
972     }
973     if (!LoadPrivateKey(prikeyFileName, &rsa, &evp)) {
974         WRITE_LOG(LOG_FATAL, "load prikey from file(%s) failed", prikeyFileName.c_str());
975         return false;
976     }
977     if (type == AuthVerifyType::RSA_3072_SHA512) {
978         signResult = RsaSign(buf, evp);
979     } else {
980         signResult = RsaEncrypt(buf, rsa);
981     }
982     if (rsa != nullptr) {
983         RSA_free(rsa);
984     }
985     if (evp != nullptr) {
986         EVP_PKEY_free(evp);
987     }
988 
989     return signResult;
990 }
991 
992 int RsaPrikeyDecryptPsk(const unsigned char* in, int inLen, unsigned char* out, int outBufSize)
993 {
994     if (in == nullptr || out == nullptr) {
995         WRITE_LOG(LOG_FATAL, "RsaPrikeyDecryptPsk IO buf is alloc failed");
996         return -1;
997     }
998     if (inLen > BUF_SIZE_DEFAULT2 || inLen <= 0) {
999         WRITE_LOG(LOG_FATAL, "invalid encryptToken, length is %d", inLen);
1000         return -1;
1001     }
1002     if (outBufSize < PSK_MAX_PSK_LEN) {
1003         WRITE_LOG(LOG_FATAL, "out buffer is too small");
1004         return -1;
1005     }
1006     RSA *rsa = nullptr;
1007     EVP_PKEY *evp = nullptr;
1008     string prikeyFileName;
1009     int outLen = -1;
1010     do {
1011         if (!GetUserKeyPath(prikeyFileName)) {
1012             WRITE_LOG(LOG_FATAL, "get key path failed");
1013             break;
1014         }
1015         if (!LoadPrivateKey(prikeyFileName, &rsa, &evp)) {
1016             WRITE_LOG(LOG_FATAL, "load prikey from file(%s) failed", prikeyFileName.c_str());
1017             break;
1018         }
1019         unsigned char tokenDecode[BUF_SIZE_DEFAULT] = { 0 };
1020         int tbytes = EVP_DecodeBlock(tokenDecode, in, inLen);
1021         if (tbytes <= 0) {
1022             WRITE_LOG(LOG_FATAL, "base64 decode PreShared Key failed");
1023             break;
1024         }
1025         outLen = RSA_private_decrypt(tbytes, tokenDecode, out, rsa, RSA_PKCS1_OAEP_PADDING);
1026         if (outLen < 0) {
1027             WRITE_LOG(LOG_FATAL, "RSA_private_decrypt failed(%lu)", ERR_get_error());
1028             break;
1029         }
1030     } while (0);
1031     if (rsa != nullptr) {
1032         RSA_free(rsa);
1033     }
1034     if (evp != nullptr) {
1035         EVP_PKEY_free(evp);
1036     }
1037     return outLen;
1038 }
1039 
1040 #ifdef HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
1041 int IsEncryptedPEM(const std::string& prikeyFileName)
1042 {
1043     if (prikeyFileName.empty()) {
1044         WRITE_LOG(LOG_FATAL, "private key file name is empty");
1045         return -1;
1046     }
1047 
1048     FILE* filePrikey = Base::Fopen(prikeyFileName.c_str(), "r");
1049     if (filePrikey == nullptr) {
1050         WRITE_LOG(LOG_FATAL, "open private key file failed!error code: %d", strerror(errno));
1051         return 1; // file not exist or open failed
1052     }
1053 
1054     char buf[BUF_SIZE_SMALL] = {0};
1055     int ret = 1;
1056     if (fgets(buf, sizeof(buf), filePrikey) != nullptr) {
1057         if (strncmp(buf, HDC_PRIVATE_KEY_FILE_FIRST_LINE_STR.c_str(),
1058             HDC_PRIVATE_KEY_FILE_FIRST_LINE_STR.size())  == 0) {
1059             WRITE_LOG(LOG_INFO, "private key is not encrypted, Re encrypt!");
1060             ret = 0; // not encrypted
1061         } else {
1062             WRITE_LOG(LOG_INFO, "private key is encrypted, not re encrypt!");
1063             ret = 1; // encrypted
1064         }
1065     }
1066 
1067     if (fclose(filePrikey) != 0) {
1068         WRITE_LOG(LOG_FATAL, "fclose error:%d", strerror(errno));
1069         return -1;
1070     }
1071     return ret;
1072 }
1073 bool CheckPrivateKeyFile()
1074 {
1075     std::string prikeyFileName;
1076     if (!GetUserKeyPath(prikeyFileName)) {
1077         WRITE_LOG(LOG_FATAL, "get key path failed");
1078         return false;
1079     }
1080 
1081     int ret = IsEncryptedPEM(prikeyFileName);
1082     if (ret == 0) {
1083         EVP_PKEY* evp = GenerateNewKey();
1084         if (evp == nullptr) {
1085             WRITE_LOG(LOG_FATAL, "generate new key failed");
1086             return false;
1087         }
1088         if (!WritePrivateFile(prikeyFileName, evp)) {
1089             WRITE_LOG(LOG_FATAL, "write private key failed");
1090             EVP_PKEY_free(evp);
1091             return false;
1092         }
1093     } else if (ret < 0) {
1094         WRITE_LOG(LOG_FATAL, "check private key file failed");
1095         return false;
1096     }
1097     return true;
1098 }
1099 #endif // HDC_SUPPORT_ENCRYPT_PRIVATE_KEY
1100 
1101 #else // DAEMON
1102 int RsaPubkeyEncryptPsk(const unsigned char* in, int inLen, unsigned char* out, int outBufSize, const string& pubkey)
1103 {
1104     if (in == nullptr || out == nullptr) {
1105         WRITE_LOG(LOG_FATAL, "RsaPubkeyEncryptPsk IO buf is alloc failed");
1106         return -1;
1107     }
1108     BIO *bio = nullptr;
1109     RSA *rsa = nullptr;
1110     int outLen = -1;
1111     do {
1112         bio = BIO_new(BIO_s_mem());
1113         if (bio == nullptr) {
1114             WRITE_LOG(LOG_FATAL, "RsaPubkeyEncryptPsk create bio failed");
1115             break;
1116         }
1117         int wbytes = BIO_write(bio, reinterpret_cast<const unsigned char *>(pubkey.c_str()), pubkey.length());
1118         if (wbytes <= 0) {
1119             WRITE_LOG(LOG_FATAL, "RsaPubkeyEncryptPsk bio write failed %d ", wbytes);
1120             break;
1121         }
1122         rsa = PEM_read_bio_RSA_PUBKEY(bio, nullptr, nullptr, nullptr);
1123         if (rsa == nullptr) {
1124             WRITE_LOG(LOG_FATAL, "RsaPubkeyEncryptPsk rsa failed");
1125             break;
1126         }
1127         unsigned char encryptedBuf[BUF_SIZE_DEFAULT2] = { 0 };
1128         int encryptedBufSize = RSA_public_encrypt(inLen, in, encryptedBuf, rsa, RSA_PKCS1_OAEP_PADDING);
1129         if (encryptedBufSize <= 0 || (outBufSize < ((encryptedBufSize + 2) / 3 * 4))) { // (x+2)/3*4 base64 encode size
1130             WRITE_LOG(LOG_FATAL, "encrypt PreShared Key failed, encryptedBufSize: %d", encryptedBufSize);
1131             break;
1132         }
1133         outLen = EVP_EncodeBlock(out, encryptedBuf, encryptedBufSize);
1134         if (outLen <= 0) {
1135             WRITE_LOG(LOG_FATAL, "base64 encode PreShared Key failed");
1136             break;
1137         }
1138     } while (0);
1139 
1140     if (bio != nullptr) {
1141         BIO_free(bio);
1142     }
1143     if (rsa != nullptr) {
1144         RSA_free(rsa);
1145     }
1146     return outLen;
1147 }
1148 #endif // HDC_HOST
1149 }
1150