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