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