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