GeezerVison is showing github.com — crypto: guard WebCrypto cipher output length · nodejs/node@98fbc89
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 +12-2Lines changed: 12 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -118,7 +118,17 @@ WebCryptoCipherStatus AES_Cipher(Environment* env, | 118 | 118 | } | 119 | 119 |
| 120 | 120 | size_t total = 0; | 121 | | - int buf_len = data_len + ctx.getBlockSize() + (encrypt ? tag_len : 0); | | 121 | + const int block_size = ctx.getBlockSize(); | | 122 | + if (block_size < 0) { | | 123 | + return WebCryptoCipherStatus::FAILED; | | 124 | + } | | 125 | + int buf_len; | | 126 | + if (!TryGetIntCipherOutputLength( | | 127 | + data_len, | | 128 | + static_cast<size_t>(block_size) + (encrypt ? tag_len : 0), | | 129 | + &buf_len)) { | | 130 | + return WebCryptoCipherStatus::FAILED; | | 131 | + } | 122 | 132 | int out_len; | 123 | 133 |
| 124 | 134 | ncrypto::Buffer<const unsigned char> buffer = { | @@ -154,7 +164,7 @@ WebCryptoCipherStatus AES_Cipher(Environment* env, | 154 | 164 |
| 155 | 165 | total += out_len; | 156 | 166 | CHECK_LE(out_len, buf_len); | 157 | | - out_len = ctx.getBlockSize(); | | 167 | + out_len = block_size; | 158 | 168 | if (!ctx.update({}, ptr + total, &out_len, true)) { | 159 | 169 | return WebCryptoCipherStatus::FAILED; | 160 | 170 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_chacha20_poly1305.cc +12-2Lines changed: 12 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -265,7 +265,17 @@ WebCryptoCipherStatus ChaCha20Poly1305CipherTraits::DoCipher( | 265 | 265 | } | 266 | 266 |
| 267 | 267 | size_t total = 0; | 268 | | - int buf_len = data_len + ctx.getBlockSize() + (encrypt ? tag_len : 0); | | 268 | + const int block_size = ctx.getBlockSize(); | | 269 | + if (block_size < 0) { | | 270 | + return WebCryptoCipherStatus::FAILED; | | 271 | + } | | 272 | + int buf_len; | | 273 | + if (!TryGetIntCipherOutputLength( | | 274 | + data_len, | | 275 | + static_cast<size_t>(block_size) + (encrypt ? tag_len : 0), | | 276 | + &buf_len)) { | | 277 | + return WebCryptoCipherStatus::FAILED; | | 278 | + } | 269 | 279 | int out_len; | 270 | 280 |
| 271 | 281 | // Process additional authenticated data if present | @@ -295,7 +305,7 @@ WebCryptoCipherStatus ChaCha20Poly1305CipherTraits::DoCipher( | 295 | 305 |
| 296 | 306 | total += out_len; | 297 | 307 | CHECK_LE(out_len, buf_len); | 298 | | - out_len = ctx.getBlockSize(); | | 308 | + out_len = block_size; | 299 | 309 | if (!ctx.update({}, ptr + total, &out_len, true)) { | 300 | 310 | return WebCryptoCipherStatus::FAILED; | 301 | 311 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_cipher.h +13Lines changed: 13 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 10 | 10 | #include "memory_tracker.h" | 11 | 11 | #include "v8.h" | 12 | 12 |
| | 13 | +#include <climits> | 13 | 14 | #include <string> | 14 | 15 |
| 15 | 16 | namespace node { | @@ -124,6 +125,18 @@ enum class WebCryptoCipherStatus { | 124 | 125 | FAILED | 125 | 126 | }; | 126 | 127 |
| | 128 | +inline bool TryGetIntCipherOutputLength(size_t input_len, | | 129 | + size_t output_overhead, | | 130 | + int* output_len) { | | 131 | + static constexpr size_t kMaxLength = INT_MAX; | | 132 | + if (output_overhead > kMaxLength || | | 133 | + input_len > kMaxLength - output_overhead) { | | 134 | + return false; | | 135 | + } | | 136 | + *output_len = static_cast<int>(input_len + output_overhead); | | 137 | + return true; | | 138 | +} | | 139 | + | 127 | 140 | // CipherJob is a base implementation class for implementations of | 128 | 141 | // one-shot sync and async ciphers. It has been added primarily to | 129 | 142 | // support the AES and RSA ciphers underlying the WebCrypt API. | |
Collapse file Copy file name to clipboardExpand all lines: test/cctest/test_node_crypto.cc +18-1Lines changed: 18 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
| 2 | 2 | // and setting it to a file that does not exist. | 3 | 3 | #define NODE_OPENSSL_SYSTEM_CERT_PATH "/missing/ca.pem" | 4 | 4 |
| | 5 | +#include "crypto/crypto_cipher.h" | 5 | 6 | #include "crypto/crypto_context.h" | | 7 | +#include "gtest/gtest.h" | 6 | 8 | #include "node_options.h" | 7 | 9 | #include "openssl/err.h" | 8 | | -#include "gtest/gtest.h" | | 10 | + | | 11 | +#include <climits> | 9 | 12 |
| 10 | 13 | /* | 11 | 14 | * This test verifies that a call to NewRootCertDir with the build time | @@ -48,3 +51,17 @@ TEST(NodeCrypto, MemoryTrackingConstants) { | 48 | 51 | EXPECT_EQ(node::crypto::kSizeOf_X509, 128); | 49 | 52 | EXPECT_EQ(node::crypto::kSizeOf_EVP_MD_CTX, 48); | 50 | 53 | } | | 54 | + | | 55 | +TEST(NodeCrypto, TryGetIntCipherOutputLength) { | | 56 | + int output_len = 0; | | 57 | + | | 58 | + EXPECT_TRUE( | | 59 | + node::crypto::TryGetIntCipherOutputLength(INT_MAX - 16, 16, &output_len)); | | 60 | + EXPECT_EQ(output_len, INT_MAX); | | 61 | + | | 62 | + EXPECT_FALSE( | | 63 | + node::crypto::TryGetIntCipherOutputLength(INT_MAX - 15, 16, &output_len)); | | 64 | + | | 65 | + EXPECT_FALSE(node::crypto::TryGetIntCipherOutputLength( | | 66 | + 0, static_cast<size_t>(INT_MAX) + 1, &output_len)); | | 67 | +} |
|