GeezerVison is showing github.com — crypto: add internal error codes · nodejs/node@a2d08d5
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_cipher.h +8-8Lines changed: 8 additions & 8 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -227,18 +227,18 @@ class CipherJob final : public CryptoJob<CipherTraits> { | 227 | 227 | // Success! | 228 | 228 | return; | 229 | 229 | } | 230 | | - CryptoErrorVector* errors = CryptoJob<CipherTraits>::errors(); | | 230 | + CryptoErrorStore* errors = CryptoJob<CipherTraits>::errors(); | 231 | 231 | errors->Capture(); | 232 | | - if (errors->empty()) { | | 232 | + if (errors->Empty()) { | 233 | 233 | switch (status) { | 234 | 234 | case WebCryptoCipherStatus::OK: | 235 | 235 | UNREACHABLE(); | 236 | 236 | break; | 237 | 237 | case WebCryptoCipherStatus::INVALID_KEY_TYPE: | 238 | | - errors->emplace_back("Invalid key type."); | | 238 | + errors->Insert(NodeCryptoError::INVALID_KEY_TYPE); | 239 | 239 | break; | 240 | 240 | case WebCryptoCipherStatus::FAILED: | 241 | | - errors->emplace_back("Cipher job failed."); | | 241 | + errors->Insert(NodeCryptoError::CIPHER_JOB_FAILED); | 242 | 242 | break; | 243 | 243 | } | 244 | 244 | } | @@ -248,17 +248,17 @@ class CipherJob final : public CryptoJob<CipherTraits> { | 248 | 248 | v8::Local<v8::Value>* err, | 249 | 249 | v8::Local<v8::Value>* result) override { | 250 | 250 | Environment* env = AsyncWrap::env(); | 251 | | - CryptoErrorVector* errors = CryptoJob<CipherTraits>::errors(); | | 251 | + CryptoErrorStore* errors = CryptoJob<CipherTraits>::errors(); | 252 | 252 | if (out_.size() > 0) { | 253 | | - CHECK(errors->empty()); | | 253 | + CHECK(errors->Empty()); | 254 | 254 | *err = v8::Undefined(env->isolate()); | 255 | 255 | *result = out_.ToArrayBuffer(env); | 256 | 256 | return v8::Just(!result->IsEmpty()); | 257 | 257 | } | 258 | 258 |
| 259 | | - if (errors->empty()) | | 259 | + if (errors->Empty()) | 260 | 260 | errors->Capture(); | 261 | | - CHECK(!errors->empty()); | | 261 | + CHECK(!errors->Empty()); | 262 | 262 | *result = v8::Undefined(env->isolate()); | 263 | 263 | return v8::Just(errors->ToException(env).ToLocal(err)); | 264 | 264 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_context.cc +2-2Lines changed: 2 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -551,7 +551,7 @@ void SecureContext::SetEngineKey(const FunctionCallbackInfo<Value>& args) { | 551 | 551 |
| 552 | 552 | CHECK_EQ(args.Length(), 2); | 553 | 553 |
| 554 | | - CryptoErrorVector errors; | | 554 | + CryptoErrorStore errors; | 555 | 555 | Utf8Value engine_id(env->isolate(), args[1]); | 556 | 556 | EnginePointer engine = LoadEngineById(*engine_id, &errors); | 557 | 557 | if (!engine) { | @@ -987,7 +987,7 @@ void SecureContext::SetClientCertEngine( | 987 | 987 | // support multiple calls to SetClientCertEngine. | 988 | 988 | CHECK(!sc->client_cert_engine_provided_); | 989 | 989 |
| 990 | | - CryptoErrorVector errors; | | 990 | + CryptoErrorStore errors; | 991 | 991 | const Utf8Value engine_id(env->isolate(), args[0]); | 992 | 992 | EnginePointer engine = LoadEngineById(*engine_id, &errors); | 993 | 993 | if (!engine) { | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_keygen.h +6-6Lines changed: 6 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -82,10 +82,10 @@ class KeyGenJob final : public CryptoJob<KeyGenTraits> { | 82 | 82 | // Success! | 83 | 83 | break; | 84 | 84 | case KeyGenJobStatus::FAILED: { | 85 | | - CryptoErrorVector* errors = CryptoJob<KeyGenTraits>::errors(); | | 85 | + CryptoErrorStore* errors = CryptoJob<KeyGenTraits>::errors(); | 86 | 86 | errors->Capture(); | 87 | | - if (errors->empty()) | 88 | | - errors->push_back(std::string("Key generation job failed")); | | 87 | + if (errors->Empty()) | | 88 | + errors->Insert(NodeCryptoError::KEY_GENERATION_JOB_FAILED); | 89 | 89 | } | 90 | 90 | } | 91 | 91 | } | @@ -94,17 +94,17 @@ class KeyGenJob final : public CryptoJob<KeyGenTraits> { | 94 | 94 | v8::Local<v8::Value>* err, | 95 | 95 | v8::Local<v8::Value>* result) override { | 96 | 96 | Environment* env = AsyncWrap::env(); | 97 | | - CryptoErrorVector* errors = CryptoJob<KeyGenTraits>::errors(); | | 97 | + CryptoErrorStore* errors = CryptoJob<KeyGenTraits>::errors(); | 98 | 98 | AdditionalParams* params = CryptoJob<KeyGenTraits>::params(); | 99 | 99 | if (status_ == KeyGenJobStatus::OK && | 100 | 100 | LIKELY(!KeyGenTraits::EncodeKey(env, params, result).IsNothing())) { | 101 | 101 | *err = Undefined(env->isolate()); | 102 | 102 | return v8::Just(true); | 103 | 103 | } | 104 | 104 |
| 105 | | - if (errors->empty()) | | 105 | + if (errors->Empty()) | 106 | 106 | errors->Capture(); | 107 | | - CHECK(!errors->empty()); | | 107 | + CHECK(!errors->Empty()); | 108 | 108 | *result = Undefined(env->isolate()); | 109 | 109 | return v8::Just(errors->ToException(env).ToLocal(err)); | 110 | 110 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_keys.h +8-8Lines changed: 8 additions & 8 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -347,18 +347,18 @@ class KeyExportJob final : public CryptoJob<KeyExportTraits> { | 347 | 347 | // Success! | 348 | 348 | return; | 349 | 349 | } | 350 | | - CryptoErrorVector* errors = CryptoJob<KeyExportTraits>::errors(); | | 350 | + CryptoErrorStore* errors = CryptoJob<KeyExportTraits>::errors(); | 351 | 351 | errors->Capture(); | 352 | | - if (errors->empty()) { | | 352 | + if (errors->Empty()) { | 353 | 353 | switch (status) { | 354 | 354 | case WebCryptoKeyExportStatus::OK: | 355 | 355 | UNREACHABLE(); | 356 | 356 | break; | 357 | 357 | case WebCryptoKeyExportStatus::INVALID_KEY_TYPE: | 358 | | - errors->emplace_back("Invalid key type."); | | 358 | + errors->Insert(NodeCryptoError::INVALID_KEY_TYPE); | 359 | 359 | break; | 360 | 360 | case WebCryptoKeyExportStatus::FAILED: | 361 | | - errors->emplace_back("Cipher job failed."); | | 361 | + errors->Insert(NodeCryptoError::CIPHER_JOB_FAILED); | 362 | 362 | break; | 363 | 363 | } | 364 | 364 | } | @@ -368,17 +368,17 @@ class KeyExportJob final : public CryptoJob<KeyExportTraits> { | 368 | 368 | v8::Local<v8::Value>* err, | 369 | 369 | v8::Local<v8::Value>* result) override { | 370 | 370 | Environment* env = AsyncWrap::env(); | 371 | | - CryptoErrorVector* errors = CryptoJob<KeyExportTraits>::errors(); | | 371 | + CryptoErrorStore* errors = CryptoJob<KeyExportTraits>::errors(); | 372 | 372 | if (out_.size() > 0) { | 373 | | - CHECK(errors->empty()); | | 373 | + CHECK(errors->Empty()); | 374 | 374 | *err = v8::Undefined(env->isolate()); | 375 | 375 | *result = out_.ToArrayBuffer(env); | 376 | 376 | return v8::Just(!result->IsEmpty()); | 377 | 377 | } | 378 | 378 |
| 379 | | - if (errors->empty()) | | 379 | + if (errors->Empty()) | 380 | 380 | errors->Capture(); | 381 | | - CHECK(!errors->empty()); | | 381 | + CHECK(!errors->Empty()); | 382 | 382 | *result = v8::Undefined(env->isolate()); | 383 | 383 | return v8::Just(errors->ToException(env).ToLocal(err)); | 384 | 384 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_util.cc +25-17Lines changed: 25 additions & 17 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -187,44 +187,52 @@ void TestFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args) { | 187 | 187 | args.GetReturnValue().Set(enabled); | 188 | 188 | } | 189 | 189 |
| 190 | | -void CryptoErrorVector::Capture() { | 191 | | - clear(); | 192 | | - while (auto err = ERR_get_error()) { | | 190 | +void CryptoErrorStore::Capture() { | | 191 | + errors_.clear(); | | 192 | + while (const uint32_t err = ERR_get_error()) { | 193 | 193 | char buf[256]; | 194 | 194 | ERR_error_string_n(err, buf, sizeof(buf)); | 195 | | - push_back(buf); | | 195 | + errors_.emplace_back(buf); | 196 | 196 | } | 197 | | - std::reverse(begin(), end()); | | 197 | + std::reverse(std::begin(errors_), std::end(errors_)); | 198 | 198 | } | 199 | 199 |
| 200 | | -MaybeLocal<Value> CryptoErrorVector::ToException( | | 200 | +bool CryptoErrorStore::Empty() const { | | 201 | + return errors_.empty(); | | 202 | +} | | 203 | + | | 204 | +MaybeLocal<Value> CryptoErrorStore::ToException( | 201 | 205 | Environment* env, | 202 | 206 | Local<String> exception_string) const { | 203 | 207 | if (exception_string.IsEmpty()) { | 204 | | - CryptoErrorVector copy(*this); | 205 | | - if (copy.empty()) copy.push_back("no error"); // But possibly a bug... | | 208 | + CryptoErrorStore copy(*this); | | 209 | + if (copy.Empty()) { | | 210 | + // But possibly a bug... | | 211 | + copy.Insert(NodeCryptoError::OK); | | 212 | + } | 206 | 213 | // Use last element as the error message, everything else goes | 207 | 214 | // into the .opensslErrorStack property on the exception object. | | 215 | + const std::string& last_error_string = copy.errors_.back(); | 208 | 216 | Local<String> exception_string; | 209 | 217 | if (!String::NewFromUtf8( | 210 | 218 | env->isolate(), | 211 | | - copy.back().data(), | | 219 | + last_error_string.data(), | 212 | 220 | NewStringType::kNormal, | 213 | | - copy.back().size()).ToLocal(&exception_string)) { | | 221 | + last_error_string.size()).ToLocal(&exception_string)) { | 214 | 222 | return MaybeLocal<Value>(); | 215 | 223 | } | 216 | | - copy.pop_back(); | | 224 | + copy.errors_.pop_back(); | 217 | 225 | return copy.ToException(env, exception_string); | 218 | 226 | } | 219 | 227 |
| 220 | 228 | Local<Value> exception_v = Exception::Error(exception_string); | 221 | 229 | CHECK(!exception_v.IsEmpty()); | 222 | 230 |
| 223 | | - if (!empty()) { | | 231 | + if (!Empty()) { | 224 | 232 | CHECK(exception_v->IsObject()); | 225 | 233 | Local<Object> exception = exception_v.As<Object>(); | 226 | 234 | Local<Value> stack; | 227 | | - if (!ToV8Value(env->context(), *this).ToLocal(&stack) || | | 235 | + if (!ToV8Value(env->context(), errors_).ToLocal(&stack) || | 228 | 236 | exception->Set(env->context(), env->openssl_error_stack(), stack) | 229 | 237 | .IsNothing()) { | 230 | 238 | return MaybeLocal<Value>(); | @@ -509,7 +517,7 @@ void ThrowCryptoError(Environment* env, | 509 | 517 | Local<Object> obj; | 510 | 518 | if (!String::NewFromUtf8(env->isolate(), message).ToLocal(&exception_string)) | 511 | 519 | return; | 512 | | - CryptoErrorVector errors; | | 520 | + CryptoErrorStore errors; | 513 | 521 | errors.Capture(); | 514 | 522 | if (!errors.ToException(env, exception_string).ToLocal(&exception) || | 515 | 523 | !exception->ToObject(env->context()).ToLocal(&obj) || | @@ -520,7 +528,7 @@ void ThrowCryptoError(Environment* env, | 520 | 528 | } | 521 | 529 |
| 522 | 530 | #ifndef OPENSSL_NO_ENGINE | 523 | | -EnginePointer LoadEngineById(const char* id, CryptoErrorVector* errors) { | | 531 | +EnginePointer LoadEngineById(const char* id, CryptoErrorStore* errors) { | 524 | 532 | MarkPopErrorOnReturn mark_pop_error_on_return; | 525 | 533 |
| 526 | 534 | EnginePointer engine(ENGINE_by_id(id)); | @@ -539,14 +547,14 @@ EnginePointer LoadEngineById(const char* id, CryptoErrorVector* errors) { | 539 | 547 | if (ERR_get_error() != 0) { | 540 | 548 | errors->Capture(); | 541 | 549 | } else { | 542 | | - errors->push_back(std::string("Engine \"") + id + "\" was not found"); | | 550 | + errors->Insert(NodeCryptoError::ENGINE_NOT_FOUND, id); | 543 | 551 | } | 544 | 552 | } | 545 | 553 |
| 546 | 554 | return engine; | 547 | 555 | } | 548 | 556 |
| 549 | | -bool SetEngine(const char* id, uint32_t flags, CryptoErrorVector* errors) { | | 557 | +bool SetEngine(const char* id, uint32_t flags, CryptoErrorStore* errors) { | 550 | 558 | ClearErrorOnReturn clear_error_on_return; | 551 | 559 | EnginePointer engine = LoadEngineById(id, errors); | 552 | 560 | if (!engine) | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_util.h +61-12Lines changed: 61 additions & 12 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -159,15 +159,64 @@ void Decode(const v8::FunctionCallbackInfo<v8::Value>& args, | 159 | 159 | } | 160 | 160 | } | 161 | 161 |
| | 162 | +enum class NodeCryptoError { | | 163 | + CIPHER_JOB_FAILED, | | 164 | + DERIVING_BITS_FAILED, | | 165 | + ENGINE_NOT_FOUND, | | 166 | + INVALID_KEY_TYPE, | | 167 | + KEY_GENERATION_JOB_FAILED, | | 168 | + OK | | 169 | +}; | | 170 | + | 162 | 171 | // Utility struct used to harvest error information from openssl's error stack | 163 | | -struct CryptoErrorVector : public std::vector<std::string> { | | 172 | +struct CryptoErrorStore final : public MemoryRetainer { | | 173 | + public: | 164 | 174 | void Capture(); | 165 | 175 |
| | 176 | + bool Empty() const; | | 177 | + | | 178 | + template <typename... Args> | | 179 | + void Insert(const NodeCryptoError error, Args&&... args); | | 180 | + | 166 | 181 | v8::MaybeLocal<v8::Value> ToException( | 167 | 182 | Environment* env, | 168 | 183 | v8::Local<v8::String> exception_string = v8::Local<v8::String>()) const; | | 184 | + | | 185 | + SET_NO_MEMORY_INFO() | | 186 | + SET_MEMORY_INFO_NAME(CryptoErrorStore); | | 187 | + SET_SELF_SIZE(CryptoErrorStore); | | 188 | + | | 189 | + private: | | 190 | + std::vector<std::string> errors_; | 169 | 191 | }; | 170 | 192 |
| | 193 | +template <typename... Args> | | 194 | +void CryptoErrorStore::Insert(const NodeCryptoError error, Args&&... args) { | | 195 | + const char* error_string = nullptr; | | 196 | + switch (error) { | | 197 | + case NodeCryptoError::CIPHER_JOB_FAILED: | | 198 | + error_string = "Cipher job failed"; | | 199 | + break; | | 200 | + case NodeCryptoError::DERIVING_BITS_FAILED: | | 201 | + error_string = "Deriving bits failed"; | | 202 | + break; | | 203 | + case NodeCryptoError::ENGINE_NOT_FOUND: | | 204 | + error_string = "Engine \"%s\" was not found"; | | 205 | + break; | | 206 | + case NodeCryptoError::INVALID_KEY_TYPE: | | 207 | + error_string = "Invalid key type"; | | 208 | + break; | | 209 | + case NodeCryptoError::KEY_GENERATION_JOB_FAILED: | | 210 | + error_string = "Key generation failed"; | | 211 | + break; | | 212 | + case NodeCryptoError::OK: | | 213 | + error_string = "Ok"; | | 214 | + break; | | 215 | + } | | 216 | + errors_.emplace_back(SPrintF(error_string, | | 217 | + std::forward<Args>(args)...)); | | 218 | +} | | 219 | + | 171 | 220 | template <typename T> | 172 | 221 | T* MallocOpenSSL(size_t count) { | 173 | 222 | void* mem = OPENSSL_malloc(MultiplyWithOverflowCheck(count, sizeof(T))); | @@ -320,7 +369,7 @@ class CryptoJob : public AsyncWrap, public ThreadPoolWork { | 320 | 369 |
| 321 | 370 | CryptoJobMode mode() const { return mode_; } | 322 | 371 |
| 323 | | - CryptoErrorVector* errors() { return &errors_; } | | 372 | + CryptoErrorStore* errors() { return &errors_; } | 324 | 373 |
| 325 | 374 | AdditionalParams* params() { return ¶ms_; } | 326 | 375 |
| @@ -364,7 +413,7 @@ class CryptoJob : public AsyncWrap, public ThreadPoolWork { | 364 | 413 |
| 365 | 414 | private: | 366 | 415 | const CryptoJobMode mode_; | 367 | | - CryptoErrorVector errors_; | | 416 | + CryptoErrorStore errors_; | 368 | 417 | AdditionalParams params_; | 369 | 418 | }; | 370 | 419 |
| @@ -412,10 +461,10 @@ class DeriveBitsJob final : public CryptoJob<DeriveBitsTraits> { | 412 | 461 | if (!DeriveBitsTraits::DeriveBits( | 413 | 462 | AsyncWrap::env(), | 414 | 463 | *CryptoJob<DeriveBitsTraits>::params(), &out_)) { | 415 | | - CryptoErrorVector* errors = CryptoJob<DeriveBitsTraits>::errors(); | | 464 | + CryptoErrorStore* errors = CryptoJob<DeriveBitsTraits>::errors(); | 416 | 465 | errors->Capture(); | 417 | | - if (errors->empty()) | 418 | | - errors->push_back("Deriving bits failed"); | | 466 | + if (errors->Empty()) | | 467 | + errors->Insert(NodeCryptoError::DERIVING_BITS_FAILED); | 419 | 468 | return; | 420 | 469 | } | 421 | 470 | success_ = true; | @@ -425,9 +474,9 @@ class DeriveBitsJob final : public CryptoJob<DeriveBitsTraits> { | 425 | 474 | v8::Local<v8::Value>* err, | 426 | 475 | v8::Local<v8::Value>* result) override { | 427 | 476 | Environment* env = AsyncWrap::env(); | 428 | | - CryptoErrorVector* errors = CryptoJob<DeriveBitsTraits>::errors(); | | 477 | + CryptoErrorStore* errors = CryptoJob<DeriveBitsTraits>::errors(); | 429 | 478 | if (success_) { | 430 | | - CHECK(errors->empty()); | | 479 | + CHECK(errors->Empty()); | 431 | 480 | *err = v8::Undefined(env->isolate()); | 432 | 481 | return DeriveBitsTraits::EncodeOutput( | 433 | 482 | env, | @@ -436,9 +485,9 @@ class DeriveBitsJob final : public CryptoJob<DeriveBitsTraits> { | 436 | 485 | result); | 437 | 486 | } | 438 | 487 |
| 439 | | - if (errors->empty()) | | 488 | + if (errors->Empty()) | 440 | 489 | errors->Capture(); | 441 | | - CHECK(!errors->empty()); | | 490 | + CHECK(!errors->Empty()); | 442 | 491 | *result = v8::Undefined(env->isolate()); | 443 | 492 | return v8::Just(errors->ToException(env).ToLocal(err)); | 444 | 493 | } | @@ -505,12 +554,12 @@ struct EnginePointer { | 505 | 554 | } | 506 | 555 | }; | 507 | 556 |
| 508 | | -EnginePointer LoadEngineById(const char* id, CryptoErrorVector* errors); | | 557 | +EnginePointer LoadEngineById(const char* id, CryptoErrorStore* errors); | 509 | 558 |
| 510 | 559 | bool SetEngine( | 511 | 560 | const char* id, | 512 | 561 | uint32_t flags, | 513 | | - CryptoErrorVector* errors = nullptr); | | 562 | + CryptoErrorStore* errors = nullptr); | 514 | 563 |
| 515 | 564 | void SetEngine(const v8::FunctionCallbackInfo<v8::Value>& args); | 516 | 565 | #endif // !OPENSSL_NO_ENGINE | |
|