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