• 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 (path.empty()) {
261         path = dir;
262     }
263     if (stat(path.c_str(), &status)) {
264         uv_fs_t req;
265         uv_fs_mkdir(nullptr, &req, path.c_str(), 0750, nullptr);  // 0750:permission
266         uv_fs_req_cleanup(&req);
267         if (req.result < 0) {
268             WRITE_LOG(LOG_DEBUG, "Cannot mkdir '%s'", path.c_str());
269             return false;
270         }
271     }
272     path += hdcKeyFile;
273     return true;
274 }
275 
LoadHostUserKey(list<void * > * listPrivateKey)276 bool LoadHostUserKey(list<void *> *listPrivateKey)
277 {
278     struct stat status;
279     string path;
280     if (!GetUserKeyPath(path)) {
281         return false;
282     }
283     if (stat(path.c_str(), &status) == -1) {
284         if (!GenerateKey(path.c_str())) {
285             WRITE_LOG(LOG_DEBUG, "Failed to generate new key");
286             return false;
287         }
288     }
289     if (!ReadKey(path.c_str(), listPrivateKey)) {
290         return false;
291     }
292     return true;
293 }
294 
AuthSign(void * rsa,const unsigned char * token,size_t tokenSize,void * sig)295 int AuthSign(void *rsa, const unsigned char *token, size_t tokenSize, void *sig)
296 {
297     unsigned int len;
298     if (!RSA_sign(NID_sha256, token, tokenSize, (unsigned char *)sig, &len, (RSA *)rsa)) {
299         return 0;
300     }
301     return static_cast<int>(len);
302 }
303 
GetPublicKeyFileBuf(unsigned char * data,size_t len)304 int GetPublicKeyFileBuf(unsigned char *data, size_t len)
305 {
306     string path;
307     int ret;
308 
309     if (!GetUserKeyPath(path)) {
310         return 0;
311     }
312     path += ".pub";
313     ret = Base::ReadBinFile(path.c_str(), (void **)data, len);
314     if (ret <= 0) {
315         return 0;
316     }
317     data[ret] = '\0';
318     return ret + 1;
319 }
320 
321 #else  // daemon
322 
RSAPublicKey2RSA(const uint8_t * keyBuf,RSA ** key)323 bool RSAPublicKey2RSA(const uint8_t *keyBuf, RSA **key)
324 {
325     const int pubKeyModulusSize = 256;
326     const int pubKeyModulusSizeWords = pubKeyModulusSize / 4;
327 
328     const RSAPublicKey *keyStruct = reinterpret_cast<const RSAPublicKey *>(keyBuf);
329     bool ret = false;
330     uint8_t modulusBuffer[pubKeyModulusSize];
331     RSA *newKey = RSA_new();
332     if (!newKey) {
333         goto cleanup;
334     }
335     if (keyStruct->wordModulusSize != pubKeyModulusSizeWords) {
336         goto cleanup;
337     }
338     if (memcpy_s(modulusBuffer, sizeof(modulusBuffer), keyStruct->modulus, sizeof(modulusBuffer)) != EOK) {
339         goto cleanup;
340     }
341     Base::ReverseBytes(modulusBuffer, sizeof(modulusBuffer));
342 
343 #ifdef OPENSSL_IS_BORINGSSL
344     // boringssl
345     newKey->n = BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr);
346     newKey->e = BN_new();
347     if (!newKey->e || !BN_set_word(newKey->e, keyStruct->exponent) || !newKey->n) {
348         goto cleanup;
349     }
350 #else
351     // openssl
352 #if OPENSSL_VERSION_NUMBER >= 0x10100005L
353     RSA_set0_key(newKey, BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr), BN_new(), BN_new());
354 #else
355     newKey->n = BN_bin2bn(modulusBuffer, sizeof(modulusBuffer), nullptr);
356     newKey->e = BN_new();
357     if (!newKey->e || !BN_set_word(newKey->e, keyStruct->exponent) || !newKey->n) {
358         goto cleanup;
359     }
360 #endif
361 #endif
362 
363     *key = newKey;
364     ret = true;
365 
366 cleanup:
367     if (!ret && newKey) {
368         RSA_free(newKey);
369     }
370     return ret;
371 }
372 
ReadDaemonKeys(const char * file,list<void * > * listPublicKey)373 void ReadDaemonKeys(const char *file, list<void *> *listPublicKey)
374 {
375     char buf[BUF_SIZE_DEFAULT2] = { 0 };
376     char *sep = nullptr;
377     int ret;
378     FILE *f = fopen(file, "re");
379     if (!f) {
380         WRITE_LOG(LOG_DEBUG, "Can't open '%s'", file);
381         return;
382     }
383     while (fgets(buf, sizeof(buf), f)) {
384         RSAPublicKey *key = new RSAPublicKey();
385         if (!key) {
386             break;
387         }
388         sep = strpbrk(buf, " \t");
389         if (sep) {
390             *sep = '\0';
391         }
392         ret = Base::Base64DecodeBuf(reinterpret_cast<uint8_t *>(buf), strlen(buf), reinterpret_cast<uint8_t *>(key));
393         if (ret != sizeof(RSAPublicKey)) {
394             WRITE_LOG(LOG_DEBUG, "%s: Invalid base64 data ret=%d", file, ret);
395             delete key;
396             continue;
397         }
398 
399         if (key->wordModulusSize != RSANUMWORDS) {
400             WRITE_LOG(LOG_DEBUG, "%s: Invalid key len %d\n", file, key->wordModulusSize);
401             delete key;
402             continue;
403         }
404         listPublicKey->push_back(key);
405     }
406     fclose(f);
407 }
408 
AuthVerify(uint8_t * token,uint8_t * sig,int siglen)409 bool AuthVerify(uint8_t *token, uint8_t *sig, int siglen)
410 {
411     list<void *> listPublicKey;
412     uint8_t authKeyIndex = 0;
413     void *ptr = nullptr;
414     int ret = 0;
415     int childRet = 0;
416     while (KeylistIncrement(&listPublicKey, authKeyIndex, &ptr)) {
417         RSA *rsa = nullptr;
418         if (!RSAPublicKey2RSA((const uint8_t *)ptr, &rsa)) {
419             break;
420         }
421         childRet = RSA_verify(NID_sha256, reinterpret_cast<const unsigned char *>(token),
422                               RSA_TOKEN_SIZE, reinterpret_cast<const unsigned char *>(sig),
423                               siglen, rsa);
424         RSA_free(rsa);
425         if (childRet) {
426             ret = 1;
427             break;
428         }
429     }
430     FreeKey(true, &listPublicKey);
431     return ret;
432 }
433 
LoadDaemonKey(list<void * > * listPublicKey)434 void LoadDaemonKey(list<void *> *listPublicKey)
435 {
436 #ifdef HDC_PCDEBUG
437     char keyPaths[][BUF_SIZE_SMALL] = { "/root/.harmony/hdckey.pub" };
438 #else
439     char keyPaths[][BUF_SIZE_SMALL] = { "/data/service/el0/hdc/hdc_keys" };
440 #endif
441     int num = sizeof(keyPaths) / sizeof(keyPaths[0]);
442     struct stat buf;
443 
444     for (int i = 0; i < num; ++i) {
445         char *p = keyPaths[i];
446         if (!stat(p, &buf)) {
447             WRITE_LOG(LOG_DEBUG, "Loading keys from '%s'", p);
448             ReadDaemonKeys(p, listPublicKey);
449         }
450     }
451 }
452 
PostUIConfirm(string publicKey)453 bool PostUIConfirm(string publicKey)
454 {
455     // Because the Hi3516 development board has no UI support for the time being, all public keys are received and
456     // By default, the system UI will record the public key /data/misc/hdc/hdckey/data/misc/hdc/hdckey
457     return true;
458 }
459 #endif  // HDC_HOST
460 
461 // --------------------------------------common code------------------------------------------
KeylistIncrement(list<void * > * listKey,uint8_t & authKeyIndex,void ** out)462 bool KeylistIncrement(list<void *> *listKey, uint8_t &authKeyIndex, void **out)
463 {
464     if (!listKey->size()) {
465 #ifdef HDC_HOST
466         LoadHostUserKey(listKey);
467 #else
468         LoadDaemonKey(listKey);
469 #endif
470     }
471     if (authKeyIndex == listKey->size()) {
472         // all finish
473         return false;
474     }
475     auto listIndex = listKey->begin();
476     std::advance(listIndex, ++authKeyIndex);
477     *out = *listIndex;
478     if (!*out) {
479         return false;
480     }
481     return true;
482 }
483 
FreeKey(bool publicOrPrivate,list<void * > * listKey)484 void FreeKey(bool publicOrPrivate, list<void *> *listKey)
485 {
486     for (auto &&v : *listKey) {
487         if (publicOrPrivate) {
488             delete (RSAPublicKey *)v;
489             v = nullptr;
490         } else {
491             RSA_free((RSA *)v);
492             v = nullptr;
493         }
494     }
495     listKey->clear();
496 }
497 
498 #ifdef HDC_HOST
GenerateNewKey(void)499 EVP_PKEY *GenerateNewKey(void)
500 {
501     bool success = false;
502     int bits = RSA_KEY_BITS;
503     RSA *rsa = RSA_new();
504     BIGNUM *e = BN_new();
505     EVP_PKEY *evp = EVP_PKEY_new();
506 
507     while (true) {
508         if (!evp || !e || !rsa) {
509             WRITE_LOG(LOG_FATAL, "allocate key failed");
510             break;
511         }
512 
513         BN_set_word(e, RSA_F4);
514         if (!RSA_generate_key_ex(rsa, bits, e, nullptr)) {
515             WRITE_LOG(LOG_FATAL, "generate rsa key failed");
516             break;
517         }
518         if (!EVP_PKEY_set1_RSA(evp, rsa)) {
519             WRITE_LOG(LOG_FATAL, "evp set rsa failed");
520             break;
521         }
522 
523         WRITE_LOG(LOG_INFO, "generate key pair success");
524         success = true;
525         break;
526     }
527 
528     if (e)
529         BN_free(e);
530     if (success) {
531         return evp;
532     }
533 
534     // if fail, need free rsa and evp
535     if (rsa)
536         RSA_free(rsa);
537     if (evp)
538         EVP_PKEY_free(evp);
539 
540     return nullptr;
541 }
GenerateKeyPair(const string & prikey_filename,const string & pubkey_filename)542 bool GenerateKeyPair(const string& prikey_filename, const string& pubkey_filename)
543 {
544     bool ret = false;
545     FILE *file_prikey = nullptr;
546     FILE *file_pubkey = nullptr;
547     EVP_PKEY *evp = nullptr;
548     mode_t old_mask = umask(077);  // 077:permission
549 
550     while (true) {
551         evp = GenerateNewKey();
552         if (!evp) {
553             WRITE_LOG(LOG_FATAL, "generate new key failed");
554             break;
555         }
556 
557         file_prikey = fopen(prikey_filename.c_str(), "w");
558         if (!file_prikey) {
559             WRITE_LOG(LOG_FATAL, "open %s failed", prikey_filename.c_str());
560             break;
561         }
562         if (!PEM_write_PrivateKey(file_prikey, evp, nullptr, nullptr, 0, nullptr, nullptr)) {
563             WRITE_LOG(LOG_FATAL, "write private key failed");
564             break;
565         }
566         file_pubkey = fopen(pubkey_filename.c_str(), "w");
567         if (!file_pubkey) {
568             WRITE_LOG(LOG_FATAL, "open %s failed", pubkey_filename.c_str());
569             break;
570         }
571         if (!PEM_write_PUBKEY(file_pubkey, evp)) {
572             WRITE_LOG(LOG_FATAL, "write public key file failed");
573             break;
574         }
575         WRITE_LOG(LOG_INFO, "generate key pair success");
576         ret = true;
577         break;
578     }
579 
580     if (evp)
581         EVP_PKEY_free(evp);
582     if (file_prikey)
583         fclose(file_prikey);
584     if (file_pubkey)
585         fclose(file_pubkey);
586     umask(old_mask);
587 
588     return ret;
589 }
590 
LoadPublicKey(const string & pubkey_filename,string & pubkey)591 bool LoadPublicKey(const string& pubkey_filename, string &pubkey)
592 {
593     bool ret = false;
594     BIO *bio = nullptr;
595     EVP_PKEY *evp = nullptr;
596     FILE *file_pubkey = nullptr;
597 
598     do {
599         file_pubkey = fopen(pubkey_filename.c_str(), "r");
600         if (!file_pubkey) {
601             WRITE_LOG(LOG_FATAL, "open file %s failed", pubkey_filename.c_str());
602             break;
603         }
604         evp = PEM_read_PUBKEY(file_pubkey, NULL, NULL, NULL);
605         if (!evp) {
606             WRITE_LOG(LOG_FATAL, "read pubkey from %s failed", pubkey_filename.c_str());
607             break;
608         }
609         bio = BIO_new(BIO_s_mem());
610         if (!bio) {
611             WRITE_LOG(LOG_FATAL, "alloc bio mem failed");
612             break;
613         }
614         if (!PEM_write_bio_PUBKEY(bio, evp)) {
615             WRITE_LOG(LOG_FATAL, "write bio failed");
616             break;
617         }
618         size_t len = 0;
619         char buf[RSA_KEY_BITS] = {0};
620         if (BIO_read_ex(bio, buf, sizeof(buf), &len) <= 0) {
621             WRITE_LOG(LOG_FATAL, "read bio failed");
622             break;
623         }
624         pubkey = string(buf, len);
625         ret = true;
626         WRITE_LOG(LOG_INFO, "load pubkey from file(%s) success", pubkey_filename.c_str());
627     } while (0);
628 
629     if (evp) {
630         EVP_PKEY_free(evp);
631         evp = nullptr;
632     }
633     if (bio) {
634         BIO_free(bio);
635         bio = nullptr;
636     }
637     if (file_pubkey) {
638         fclose(file_pubkey);
639         file_pubkey = nullptr;
640     }
641     return ret;
642 }
643 
TryLoadPublicKey(string & pubkey)644 bool TryLoadPublicKey(string &pubkey)
645 {
646     string prikey_filename;
647     struct stat status;
648     if (!GetUserKeyPath(prikey_filename)) {
649         WRITE_LOG(LOG_FATAL, "get key path failed");
650         return false;
651     }
652     string pubkey_filename = prikey_filename + ".pub";
653     if (stat(prikey_filename.c_str(), &status) == -1) {
654         if (!GenerateKeyPair(prikey_filename, pubkey_filename)) {
655             WRITE_LOG(LOG_FATAL, "generate new key failed");
656             return false;
657         }
658     }
659     if (!LoadPublicKey(pubkey_filename, pubkey)) {
660         WRITE_LOG(LOG_FATAL, "load key failed");
661         return false;
662     }
663 
664     WRITE_LOG(LOG_INFO, "load pubkey success");
665 
666     return true;
667 }
668 
GetHostName(string & hostname)669 bool GetHostName(string &hostname)
670 {
671     int ret;
672     char buf[BUF_SIZE_DEFAULT] = {0};
673     size_t bufsize = sizeof(buf);
674 
675     ret = uv_os_gethostname(buf, &bufsize);
676     if (ret != 0) {
677         WRITE_LOG(LOG_FATAL, "get hostname failed: %d", ret);
678         return false;
679     }
680 
681     hostname = string(buf, bufsize);
682 
683     WRITE_LOG(LOG_INFO, "hostname: %s", hostname.c_str());
684 
685     return true;
686 }
687 
GetPublicKeyinfo(string & pubkey_info)688 bool GetPublicKeyinfo(string &pubkey_info)
689 {
690     string hostname;
691     if (!GetHostName(hostname)) {
692         WRITE_LOG(LOG_FATAL, "gethostname failed");
693         return false;
694     }
695     string pubkey;
696     if (!HdcAuth::TryLoadPublicKey(pubkey)) {
697         WRITE_LOG(LOG_FATAL, "load public key failed");
698         return false;
699     }
700     pubkey_info = hostname;
701     pubkey_info.append(HDC_HOST_DAEMON_BUF_SEPARATOR);
702     pubkey_info.append(pubkey);
703 
704     WRITE_LOG(LOG_INFO, "Get pubkey info success");
705 
706     return true;
707 }
708 
LoadPrivateKey(const string & prikey_filename)709 RSA *LoadPrivateKey(const string& prikey_filename)
710 {
711     RSA *rsa = nullptr;
712     EVP_PKEY *evp = nullptr;
713     FILE *file_prikey = nullptr;
714 
715     do {
716         file_prikey = fopen(prikey_filename.c_str(), "r");
717         if (!file_prikey) {
718             WRITE_LOG(LOG_FATAL, "open file %s failed", prikey_filename.c_str());
719             break;
720         }
721         evp = PEM_read_PrivateKey(file_prikey, NULL, NULL, NULL);
722         if (!evp) {
723             WRITE_LOG(LOG_FATAL, "read prikey from %s failed", prikey_filename.c_str());
724             break;
725         }
726         rsa = EVP_PKEY_get1_RSA(evp);
727         WRITE_LOG(LOG_FATAL, "load prikey success");
728     } while (0);
729 
730     if (evp) {
731         EVP_PKEY_free(evp);
732         evp = nullptr;
733     }
734     if (file_prikey) {
735         fclose(file_prikey);
736         file_prikey = nullptr;
737     }
738 
739     return rsa;
740 }
741 
RsaSignAndBase64(string & buf)742 bool RsaSignAndBase64(string &buf)
743 {
744     RSA *rsa = nullptr;
745     string prikey_filename;
746     int sign_ori_size;
747     int sign_out_size;
748     unsigned char sign_ori[BUF_SIZE_DEFAULT2] = { 0 };
749     unsigned char *sign_out = nullptr;
750     int in_size = buf.size();
751     const unsigned char *in = reinterpret_cast<const unsigned char *>(buf.c_str());
752 
753     WRITE_LOG(LOG_INFO, "plain(%s)", buf.c_str());
754     if (!GetUserKeyPath(prikey_filename)) {
755         WRITE_LOG(LOG_FATAL, "get key path failed");
756         return false;
757     }
758 
759     rsa = LoadPrivateKey(prikey_filename);
760     if (!rsa) {
761         WRITE_LOG(LOG_FATAL, "load prikey from file(%s) failed", prikey_filename.c_str());
762         return false;
763     }
764     sign_ori_size = RSA_private_encrypt(in_size, in, sign_ori, rsa, RSA_PKCS1_PADDING);
765     if (sign_ori_size <= 0) {
766         WRITE_LOG(LOG_FATAL, "encrypt failed");
767         return false;
768     }
769     sign_out = new unsigned char[sign_ori_size * 2];
770     if (!sign_out) {
771         WRITE_LOG(LOG_FATAL, "alloc mem failed");
772         return false;
773     }
774     sign_out_size = EVP_EncodeBlock(sign_out, sign_ori, sign_ori_size);
775     if (sign_out_size <= 0) {
776         WRITE_LOG(LOG_FATAL, "encode buf failed");
777         delete[] sign_out;
778         sign_out = nullptr;
779         return false;
780     }
781 
782     buf = string(reinterpret_cast<char *>(sign_out), sign_out_size);
783 
784     WRITE_LOG(LOG_INFO, "sign success");
785 
786     delete[] sign_out;
787     sign_out = nullptr;
788 
789     return true;
790 }
791 #endif
792 }
793