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