GeezerVison is showing github.com — src: fix memory leaks and refactor `ByteSource` · nodejs/node@931ecfa
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_aes.cc +43-52Lines changed: 43 additions & 52 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -89,11 +89,10 @@ WebCryptoCipherStatus AES_Cipher( | 89 | 89 | case kWebCryptoCipherDecrypt: | 90 | 90 | // If in decrypt mode, the auth tag must be set in the params.tag. | 91 | 91 | CHECK(params.tag); | 92 | | - if (!EVP_CIPHER_CTX_ctrl( | 93 | | - ctx.get(), | 94 | | - EVP_CTRL_AEAD_SET_TAG, | 95 | | - params.tag.size(), | 96 | | - const_cast<char*>(params.tag.get()))) { | | 92 | + if (!EVP_CIPHER_CTX_ctrl(ctx.get(), | | 93 | + EVP_CTRL_AEAD_SET_TAG, | | 94 | + params.tag.size(), | | 95 | + const_cast<char*>(params.tag.data<char>()))) { | 97 | 96 | return WebCryptoCipherStatus::FAILED; | 98 | 97 | } | 99 | 98 | break; | @@ -125,9 +124,7 @@ WebCryptoCipherStatus AES_Cipher( | 125 | 124 | return WebCryptoCipherStatus::FAILED; | 126 | 125 | } | 127 | 126 |
| 128 | | - char* data = MallocOpenSSL<char>(buf_len); | 129 | | - ByteSource buf = ByteSource::Allocated(data, buf_len); | 130 | | - unsigned char* ptr = reinterpret_cast<unsigned char*>(data); | | 127 | + ByteSource::Builder buf(buf_len); | 131 | 128 |
| 132 | 129 | // In some outdated version of OpenSSL (e.g. | 133 | 130 | // ubi81_sharedlibs_openssl111fips_x64) may be used in sharedlib mode, the | @@ -139,36 +136,36 @@ WebCryptoCipherStatus AES_Cipher( | 139 | 136 | // Refs: https://github.com/nodejs/node/pull/38913#issuecomment-866505244 | 140 | 137 | if (in.size() == 0) { | 141 | 138 | out_len = 0; | 142 | | - } else if (!EVP_CipherUpdate( | 143 | | - ctx.get(), | 144 | | - ptr, | 145 | | - &out_len, | 146 | | - in.data<unsigned char>(), | 147 | | - in.size())) { | | 139 | + } else if (!EVP_CipherUpdate(ctx.get(), | | 140 | + buf.data<unsigned char>(), | | 141 | + &out_len, | | 142 | + in.data<unsigned char>(), | | 143 | + in.size())) { | 148 | 144 | return WebCryptoCipherStatus::FAILED; | 149 | 145 | } | 150 | 146 |
| 151 | 147 | total += out_len; | 152 | 148 | CHECK_LE(out_len, buf_len); | 153 | | - ptr += out_len; | 154 | 149 | out_len = EVP_CIPHER_CTX_block_size(ctx.get()); | 155 | | - if (!EVP_CipherFinal_ex(ctx.get(), ptr, &out_len)) { | | 150 | + if (!EVP_CipherFinal_ex( | | 151 | + ctx.get(), buf.data<unsigned char>() + total, &out_len)) { | 156 | 152 | return WebCryptoCipherStatus::FAILED; | 157 | 153 | } | 158 | 154 | total += out_len; | 159 | 155 |
| 160 | 156 | // If using AES_GCM, grab the generated auth tag and append | 161 | 157 | // it to the end of the ciphertext. | 162 | 158 | if (cipher_mode == kWebCryptoCipherEncrypt && mode == EVP_CIPH_GCM_MODE) { | 163 | | - data += out_len; | 164 | | - if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_GET_TAG, tag_len, ptr)) | | 159 | + if (!EVP_CIPHER_CTX_ctrl(ctx.get(), | | 160 | + EVP_CTRL_AEAD_GET_TAG, | | 161 | + tag_len, | | 162 | + buf.data<unsigned char>() + total)) | 165 | 163 | return WebCryptoCipherStatus::FAILED; | 166 | 164 | total += tag_len; | 167 | 165 | } | 168 | 166 |
| 169 | 167 | // It's possible that we haven't used the full allocated space. Size down. | 170 | | - buf.Resize(total); | 171 | | - *out = std::move(buf); | | 168 | + *out = std::move(buf).release(total); | 172 | 169 |
| 173 | 170 | return WebCryptoCipherStatus::OK; | 174 | 171 | } | @@ -295,38 +292,34 @@ WebCryptoCipherStatus AES_CTR_Cipher( | 295 | 292 | return WebCryptoCipherStatus::FAILED; | 296 | 293 | } | 297 | 294 |
| 298 | | - // Output size is identical to the input size | 299 | | - char* data = MallocOpenSSL<char>(in.size()); | 300 | | - ByteSource buf = ByteSource::Allocated(data, in.size()); | 301 | | - unsigned char* ptr = reinterpret_cast<unsigned char*>(data); | | 295 | + // Output size is identical to the input size. | | 296 | + ByteSource::Builder buf(in.size()); | 302 | 297 |
| 303 | 298 | // Also just like in chromium's implementation, if we can process | 304 | 299 | // the input without wrapping the counter, we'll do it as a single | 305 | 300 | // call here. If we can't, we'll fallback to the a two-step approach | 306 | 301 | if (BN_cmp(remaining_until_reset.get(), num_output.get()) >= 0) { | 307 | | - auto status = AES_CTR_Cipher2( | 308 | | - key_data, | 309 | | - cipher_mode, | 310 | | - params, | 311 | | - in, | 312 | | - params.iv.data<unsigned char>(), | 313 | | - ptr); | 314 | | - if (status == WebCryptoCipherStatus::OK) | 315 | | - *out = std::move(buf); | | 302 | + auto status = AES_CTR_Cipher2(key_data, | | 303 | + cipher_mode, | | 304 | + params, | | 305 | + in, | | 306 | + params.iv.data<unsigned char>(), | | 307 | + buf.data<unsigned char>()); | | 308 | + if (status == WebCryptoCipherStatus::OK) *out = std::move(buf).release(); | 316 | 309 | return status; | 317 | 310 | } | 318 | 311 |
| 319 | 312 | BN_ULONG blocks_part1 = BN_get_word(remaining_until_reset.get()); | 320 | 313 | BN_ULONG input_size_part1 = blocks_part1 * kAesBlockSize; | 321 | 314 |
| 322 | 315 | // Encrypt the first part... | 323 | | - auto status = AES_CTR_Cipher2( | 324 | | - key_data, | 325 | | - cipher_mode, | 326 | | - params, | 327 | | - ByteSource::Foreign(in.get(), input_size_part1), | 328 | | - params.iv.data<unsigned char>(), | 329 | | - ptr); | | 316 | + auto status = | | 317 | + AES_CTR_Cipher2(key_data, | | 318 | + cipher_mode, | | 319 | + params, | | 320 | + ByteSource::Foreign(in.data<char>(), input_size_part1), | | 321 | + params.iv.data<unsigned char>(), | | 322 | + buf.data<unsigned char>()); | 330 | 323 |
| 331 | 324 | if (status != WebCryptoCipherStatus::OK) | 332 | 325 | return status; | @@ -335,18 +328,16 @@ WebCryptoCipherStatus AES_CTR_Cipher( | 335 | 328 | std::vector<unsigned char> new_counter_block = BlockWithZeroedCounter(params); | 336 | 329 |
| 337 | 330 | // Encrypt the second part... | 338 | | - status = AES_CTR_Cipher2( | 339 | | - key_data, | 340 | | - cipher_mode, | 341 | | - params, | 342 | | - ByteSource::Foreign( | 343 | | - in.get() + input_size_part1, | 344 | | - in.size() - input_size_part1), | 345 | | - new_counter_block.data(), | 346 | | - ptr + input_size_part1); | 347 | | - | 348 | | - if (status == WebCryptoCipherStatus::OK) | 349 | | - *out = std::move(buf); | | 331 | + status = | | 332 | + AES_CTR_Cipher2(key_data, | | 333 | + cipher_mode, | | 334 | + params, | | 335 | + ByteSource::Foreign(in.data<char>() + input_size_part1, | | 336 | + in.size() - input_size_part1), | | 337 | + new_counter_block.data(), | | 338 | + buf.data<unsigned char>() + input_size_part1); | | 339 | + | | 340 | + if (status == WebCryptoCipherStatus::OK) *out = std::move(buf).release(); | 350 | 341 |
| 351 | 342 | return status; | 352 | 343 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_common.cc +1-2Lines changed: 1 addition & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -525,8 +525,7 @@ MaybeLocal<Value> GetSerialNumber(Environment* env, X509* cert) { | 525 | 525 | if (bn) { | 526 | 526 | char* data = BN_bn2hex(bn.get()); | 527 | 527 | ByteSource buf = ByteSource::Allocated(data, strlen(data)); | 528 | | - if (buf) | 529 | | - return OneByteString(env->isolate(), buf.get()); | | 528 | + if (buf) return OneByteString(env->isolate(), buf.data<unsigned char>()); | 530 | 529 | } | 531 | 530 | } | 532 | 531 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_dh.cc +4-9Lines changed: 4 additions & 9 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -606,18 +606,13 @@ ByteSource StatelessDiffieHellmanThreadsafe( | 606 | 606 | EVP_PKEY_derive(ctx.get(), nullptr, &out_size) <= 0) | 607 | 607 | return ByteSource(); | 608 | 608 |
| 609 | | - char* buf = MallocOpenSSL<char>(out_size); | 610 | | - ByteSource out = ByteSource::Allocated(buf, out_size); | 611 | | - | 612 | | - if (EVP_PKEY_derive( | 613 | | - ctx.get(), | 614 | | - reinterpret_cast<unsigned char*>(buf), | 615 | | - &out_size) <= 0) { | | 609 | + ByteSource::Builder out(out_size); | | 610 | + if (EVP_PKEY_derive(ctx.get(), out.data<unsigned char>(), &out_size) <= 0) { | 616 | 611 | return ByteSource(); | 617 | 612 | } | 618 | 613 |
| 619 | | - ZeroPadDiffieHellmanSecret(out_size, buf, out.size()); | 620 | | - return out; | | 614 | + ZeroPadDiffieHellmanSecret(out_size, out.data<char>(), out.size()); | | 615 | + return std::move(out).release(); | 621 | 616 | } | 622 | 617 | } // namespace | 623 | 618 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_ec.cc +31-51Lines changed: 31 additions & 51 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -486,12 +486,9 @@ Maybe<bool> ECDHBitsTraits::AdditionalConfig( | 486 | 486 | return Just(true); | 487 | 487 | } | 488 | 488 |
| 489 | | -bool ECDHBitsTraits::DeriveBits( | 490 | | - Environment* env, | 491 | | - const ECDHBitsConfig& params, | 492 | | - ByteSource* out) { | 493 | | - | 494 | | - char* data = nullptr; | | 489 | +bool ECDHBitsTraits::DeriveBits(Environment* env, | | 490 | + const ECDHBitsConfig& params, | | 491 | + ByteSource* out) { | 495 | 492 | size_t len = 0; | 496 | 493 | ManagedEVPPKey m_privkey = params.private_->GetAsymmetricKey(); | 497 | 494 | ManagedEVPPKey m_pubkey = params.public_->GetAsymmetricKey(); | @@ -513,15 +510,14 @@ bool ECDHBitsTraits::DeriveBits( | 513 | 510 | return false; | 514 | 511 | } | 515 | 512 |
| 516 | | - data = MallocOpenSSL<char>(len); | | 513 | + ByteSource::Builder buf(len); | 517 | 514 |
| 518 | | - if (EVP_PKEY_derive( | 519 | | - ctx.get(), | 520 | | - reinterpret_cast<unsigned char*>(data), | 521 | | - &len) <= 0) { | | 515 | + if (EVP_PKEY_derive(ctx.get(), buf.data<unsigned char>(), &len) <= 0) { | 522 | 516 | return false; | 523 | 517 | } | 524 | 518 |
| | 519 | + *out = std::move(buf).release(len); | | 520 | + | 525 | 521 | break; | 526 | 522 | } | 527 | 523 | default: { | @@ -543,22 +539,18 @@ bool ECDHBitsTraits::DeriveBits( | 543 | 539 | const EC_POINT* pub = EC_KEY_get0_public_key(public_key); | 544 | 540 | int field_size = EC_GROUP_get_degree(group); | 545 | 541 | len = (field_size + 7) / 8; | 546 | | - data = MallocOpenSSL<char>(len); | 547 | | - CHECK_NOT_NULL(data); | | 542 | + ByteSource::Builder buf(len); | 548 | 543 | CHECK_NOT_NULL(pub); | 549 | 544 | CHECK_NOT_NULL(private_key); | 550 | | - if (ECDH_compute_key( | 551 | | - data, | 552 | | - len, | 553 | | - pub, | 554 | | - private_key, | 555 | | - nullptr) <= 0) { | | 545 | + if (ECDH_compute_key(buf.data<char>(), len, pub, private_key, nullptr) <= | | 546 | + 0) { | 556 | 547 | return false; | 557 | 548 | } | | 549 | + | | 550 | + *out = std::move(buf).release(); | 558 | 551 | } | 559 | 552 | } | 560 | | - ByteSource buf = ByteSource::Allocated(data, len); | 561 | | - *out = std::move(buf); | | 553 | + | 562 | 554 | return true; | 563 | 555 | } | 564 | 556 |
| @@ -646,7 +638,6 @@ WebCryptoKeyExportStatus EC_Raw_Export( | 646 | 638 |
| 647 | 639 | const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(m_pkey.get()); | 648 | 640 |
| 649 | | - unsigned char* data; | 650 | 641 | size_t len = 0; | 651 | 642 |
| 652 | 643 | if (ec_key == nullptr) { | @@ -666,9 +657,10 @@ WebCryptoKeyExportStatus EC_Raw_Export( | 666 | 657 | // Get the size of the raw key data | 667 | 658 | if (fn(m_pkey.get(), nullptr, &len) == 0) | 668 | 659 | return WebCryptoKeyExportStatus::INVALID_KEY_TYPE; | 669 | | - data = MallocOpenSSL<unsigned char>(len); | 670 | | - if (fn(m_pkey.get(), data, &len) == 0) | | 660 | + ByteSource::Builder data(len); | | 661 | + if (fn(m_pkey.get(), data.data<unsigned char>(), &len) == 0) | 671 | 662 | return WebCryptoKeyExportStatus::INVALID_KEY_TYPE; | | 663 | + *out = std::move(data).release(len); | 672 | 664 | } else { | 673 | 665 | if (key_data->GetKeyType() != kKeyTypePublic) | 674 | 666 | return WebCryptoKeyExportStatus::INVALID_KEY_TYPE; | @@ -680,17 +672,16 @@ WebCryptoKeyExportStatus EC_Raw_Export( | 680 | 672 | len = EC_POINT_point2oct(group, point, form, nullptr, 0, nullptr); | 681 | 673 | if (len == 0) | 682 | 674 | return WebCryptoKeyExportStatus::FAILED; | 683 | | - data = MallocOpenSSL<unsigned char>(len); | 684 | | - size_t check_len = | 685 | | - EC_POINT_point2oct(group, point, form, data, len, nullptr); | | 675 | + ByteSource::Builder data(len); | | 676 | + size_t check_len = EC_POINT_point2oct( | | 677 | + group, point, form, data.data<unsigned char>(), len, nullptr); | 686 | 678 | if (check_len == 0) | 687 | 679 | return WebCryptoKeyExportStatus::FAILED; | 688 | 680 |
| 689 | 681 | CHECK_EQ(len, check_len); | | 682 | + *out = std::move(data).release(); | 690 | 683 | } | 691 | 684 |
| 692 | | - *out = ByteSource::Allocated(reinterpret_cast<char*>(data), len); | 693 | | - | 694 | 685 | return WebCryptoKeyExportStatus::OK; | 695 | 686 | } | 696 | 687 | } // namespace | @@ -853,38 +844,27 @@ Maybe<bool> ExportJWKEdKey( | 853 | 844 | if (!EVP_PKEY_get_raw_public_key(pkey.get(), nullptr, &len)) | 854 | 845 | return Nothing<bool>(); | 855 | 846 |
| 856 | | - unsigned char* data = MallocOpenSSL<unsigned char>(len); | 857 | | - ByteSource out = ByteSource::Allocated(reinterpret_cast<char*>(data), len); | | 847 | + ByteSource::Builder out(len); | 858 | 848 |
| 859 | 849 | if (key->GetKeyType() == kKeyTypePrivate) { | 860 | | - if (!EVP_PKEY_get_raw_private_key(pkey.get(), data, &len) || | | 850 | + if (!EVP_PKEY_get_raw_private_key( | | 851 | + pkey.get(), out.data<unsigned char>(), &len) || | 861 | 852 | !StringBytes::Encode( | 862 | | - env->isolate(), | 863 | | - reinterpret_cast<const char*>(data), | 864 | | - len, | 865 | | - BASE64URL, | 866 | | - &error).ToLocal(&encoded) || | 867 | | - !target->Set( | 868 | | - env->context(), | 869 | | - env->jwk_d_string(), | 870 | | - encoded).IsJust()) { | | 853 | + env->isolate(), out.data<const char>(), len, BASE64URL, &error) | | 854 | + .ToLocal(&encoded) || | | 855 | + !target->Set(env->context(), env->jwk_d_string(), encoded).IsJust()) { | 871 | 856 | if (!error.IsEmpty()) | 872 | 857 | env->isolate()->ThrowException(error); | 873 | 858 | return Nothing<bool>(); | 874 | 859 | } | 875 | 860 | } | 876 | 861 |
| 877 | | - if (!EVP_PKEY_get_raw_public_key(pkey.get(), data, &len) || | | 862 | + if (!EVP_PKEY_get_raw_public_key( | | 863 | + pkey.get(), out.data<unsigned char>(), &len) || | 878 | 864 | !StringBytes::Encode( | 879 | | - env->isolate(), | 880 | | - reinterpret_cast<const char*>(data), | 881 | | - len, | 882 | | - BASE64URL, | 883 | | - &error).ToLocal(&encoded) || | 884 | | - !target->Set( | 885 | | - env->context(), | 886 | | - env->jwk_x_string(), | 887 | | - encoded).IsJust()) { | | 865 | + env->isolate(), out.data<const char>(), len, BASE64URL, &error) | | 866 | + .ToLocal(&encoded) || | | 867 | + !target->Set(env->context(), env->jwk_x_string(), encoded).IsJust()) { | 888 | 868 | if (!error.IsEmpty()) | 889 | 869 | env->isolate()->ThrowException(error); | 890 | 870 | return Nothing<bool>(); | |
|