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