crypto: decode missing passphrase errors · nodejs/node@2e2c015 (original) (raw)
`@@ -153,13 +153,33 @@ template int SSLWrap::SelectALPNCallback(
`
153
153
`unsigned int inlen,
`
154
154
`void* arg);
`
155
155
``
``
156
`+
class PasswordCallbackInfo {
`
``
157
`+
public:
`
``
158
`+
explicit PasswordCallbackInfo(const char* passphrase)
`
``
159
`+
: passphrase_(passphrase) {}
`
``
160
+
``
161
`+
inline const char* GetPassword() {
`
``
162
`+
needs_passphrase_ = true;
`
``
163
`+
return passphrase_;
`
``
164
`+
}
`
``
165
+
``
166
`+
inline bool CalledButEmpty() {
`
``
167
`+
return needs_passphrase_ && passphrase_ == nullptr;
`
``
168
`+
}
`
``
169
+
``
170
`+
private:
`
``
171
`+
const char* passphrase_;
`
``
172
`+
bool needs_passphrase_ = false;
`
``
173
`+
};
`
156
174
``
157
175
`static int PasswordCallback(char* buf, int size, int rwflag, void* u) {
`
158
``
`-
if (u) {
`
``
176
`+
PasswordCallbackInfo* info = static_cast<PasswordCallbackInfo*>(u);
`
``
177
`+
const char* passphrase = info->GetPassword();
`
``
178
`+
if (passphrase != nullptr) {
`
159
179
`size_t buflen = static_cast(size);
`
160
``
`-
size_t len = strlen(static_cast<const char*>(u));
`
``
180
`+
size_t len = strlen(passphrase);
`
161
181
` len = len > buflen ? buflen : len;
`
162
``
`-
memcpy(buf, u, len);
`
``
182
`+
memcpy(buf, passphrase, len);
`
163
183
`return len;
`
164
184
` }
`
165
185
``
`@@ -698,11 +718,12 @@ void SecureContext::SetKey(const FunctionCallbackInfo& args) {
`
698
718
``
699
719
` node::Utf8Value passphrase(env->isolate(), args[1]);
`
700
720
``
``
721
`+
PasswordCallbackInfo cb_info(len == 1 ? nullptr : *passphrase);
`
701
722
` EVPKeyPointer key(
`
702
723
`PEM_read_bio_PrivateKey(bio.get(),
`
703
724
`nullptr,
`
704
725
` PasswordCallback,
`
705
``
`-
len == 1 ? nullptr : *passphrase));
`
``
726
`+
&cb_info));
`
706
727
``
707
728
`if (!key) {
`
708
729
`unsigned long err = ERR_get_error(); // NOLINT(runtime/int)
`
`@@ -2899,13 +2920,14 @@ static bool IsSupportedAuthenticatedMode(const EVP_CIPHER_CTX* ctx) {
`
2899
2920
`return IsSupportedAuthenticatedMode(cipher);
`
2900
2921
`}
`
2901
2922
``
2902
``
`-
enum class ParsePublicKeyResult {
`
2903
``
`-
kParsePublicOk,
`
2904
``
`-
kParsePublicNotRecognized,
`
2905
``
`-
kParsePublicFailed
`
``
2923
`+
enum class ParseKeyResult {
`
``
2924
`+
kParseKeyOk,
`
``
2925
`+
kParseKeyNotRecognized,
`
``
2926
`+
kParseKeyNeedPassphrase,
`
``
2927
`+
kParseKeyFailed
`
2906
2928
`};
`
2907
2929
``
2908
``
`-
static ParsePublicKeyResult TryParsePublicKey(
`
``
2930
`+
static ParseKeyResult TryParsePublicKey(
`
2909
2931
` EVPKeyPointer* pkey,
`
2910
2932
`const BIOPointer& bp,
`
2911
2933
`const char* name,
`
`@@ -2919,33 +2941,33 @@ static ParsePublicKeyResult TryParsePublicKey(
`
2919
2941
` MarkPopErrorOnReturn mark_pop_error_on_return;
`
2920
2942
`if (PEM_bytes_read_bio(&der_data, &der_len, nullptr, name,
`
2921
2943
` bp.get(), nullptr, nullptr) != 1)
`
2922
``
`-
return ParsePublicKeyResult::kParsePublicNotRecognized;
`
``
2944
`+
return ParseKeyResult::kParseKeyNotRecognized;
`
2923
2945
` }
`
2924
2946
``
2925
2947
`// OpenSSL might modify the pointer, so we need to make a copy before parsing.
`
2926
2948
`const unsigned char* p = der_data;
`
2927
2949
` pkey->reset(parse(&p, der_len));
`
2928
2950
`OPENSSL_clear_free(der_data, der_len);
`
2929
2951
``
2930
``
`-
return *pkey ? ParsePublicKeyResult::kParsePublicOk :
`
2931
``
`-
ParsePublicKeyResult::kParsePublicFailed;
`
``
2952
`+
return *pkey ? ParseKeyResult::kParseKeyOk :
`
``
2953
`+
ParseKeyResult::kParseKeyFailed;
`
2932
2954
`}
`
2933
2955
``
2934
``
`-
static ParsePublicKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
`
2935
``
`-
const char* key_pem,
`
2936
``
`-
int key_pem_len) {
`
``
2956
`+
static ParseKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
`
``
2957
`+
const char* key_pem,
`
``
2958
`+
int key_pem_len) {
`
2937
2959
` BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
`
2938
2960
`if (!bp)
`
2939
``
`-
return ParsePublicKeyResult::kParsePublicFailed;
`
``
2961
`+
return ParseKeyResult::kParseKeyFailed;
`
2940
2962
``
2941
``
`-
ParsePublicKeyResult ret;
`
``
2963
`+
ParseKeyResult ret;
`
2942
2964
``
2943
2965
`// Try parsing as a SubjectPublicKeyInfo first.
`
2944
2966
` ret = TryParsePublicKey(pkey, bp, "PUBLIC KEY",
`
2945
2967
` [](const unsigned char** p, long l) { // NOLINT(runtime/int)
`
2946
2968
`return d2i_PUBKEY(nullptr, p, l);
`
2947
2969
` });
`
2948
``
`-
if (ret != ParsePublicKeyResult::kParsePublicNotRecognized)
`
``
2970
`+
if (ret != ParseKeyResult::kParseKeyNotRecognized)
`
2949
2971
`return ret;
`
2950
2972
``
2951
2973
`// Maybe it is PKCS#1.
`
`@@ -2954,7 +2976,7 @@ static ParsePublicKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
`
2954
2976
` [](const unsigned char** p, long l) { // NOLINT(runtime/int)
`
2955
2977
`return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l);
`
2956
2978
` });
`
2957
``
`-
if (ret != ParsePublicKeyResult::kParsePublicNotRecognized)
`
``
2979
`+
if (ret != ParseKeyResult::kParseKeyNotRecognized)
`
2958
2980
`return ret;
`
2959
2981
``
2960
2982
`// X.509 fallback.
`
`@@ -2966,25 +2988,25 @@ static ParsePublicKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
`
2966
2988
` });
`
2967
2989
`}
`
2968
2990
``
2969
``
`-
static bool ParsePublicKey(EVPKeyPointer* pkey,
`
2970
``
`-
const PublicKeyEncodingConfig& config,
`
2971
``
`-
const char* key,
`
2972
``
`-
size_t key_len) {
`
``
2991
`+
static ParseKeyResult ParsePublicKey(EVPKeyPointer* pkey,
`
``
2992
`+
const PublicKeyEncodingConfig& config,
`
``
2993
`+
const char* key,
`
``
2994
`+
size_t key_len) {
`
2973
2995
`if (config.format_ == kKeyFormatPEM) {
`
2974
``
`-
ParsePublicKeyResult r =
`
2975
``
`-
ParsePublicKeyPEM(pkey, key, key_len);
`
2976
``
`-
return r == ParsePublicKeyResult::kParsePublicOk;
`
``
2996
`+
return ParsePublicKeyPEM(pkey, key, key_len);
`
2977
2997
` } else {
`
2978
2998
`CHECK_EQ(config.format_, kKeyFormatDER);
`
``
2999
+
2979
3000
`const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
`
2980
3001
`if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
`
2981
3002
` pkey->reset(d2i_PublicKey(EVP_PKEY_RSA, nullptr, &p, key_len));
`
2982
``
`-
return pkey;
`
2983
3003
` } else {
`
2984
3004
`CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
`
2985
3005
` pkey->reset(d2i_PUBKEY(nullptr, &p, key_len));
`
2986
``
`-
return pkey;
`
2987
3006
` }
`
``
3007
+
``
3008
`+
return *pkey ? ParseKeyResult::kParseKeyOk :
`
``
3009
`+
ParseKeyResult::kParseKeyFailed;
`
2988
3010
` }
`
2989
3011
`}
`
2990
3012
``
`@@ -3099,56 +3121,59 @@ static bool IsEncryptedPrivateKeyInfo(const unsigned char* data, size_t size) {
`
3099
3121
` data[offset] != 2;
`
3100
3122
`}
`
3101
3123
``
3102
``
`-
static EVPKeyPointer ParsePrivateKey(const PrivateKeyEncodingConfig& config,
`
3103
``
`-
const char* key,
`
3104
``
`-
size_t key_len) {
`
3105
``
`-
EVPKeyPointer pkey;
`
``
3124
`+
static ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
`
``
3125
`+
const PrivateKeyEncodingConfig& config,
`
``
3126
`+
const char* key,
`
``
3127
`+
size_t key_len) {
`
``
3128
`+
PasswordCallbackInfo pc_info(config.passphrase_.get());
`
3106
3129
``
3107
3130
`if (config.format_ == kKeyFormatPEM) {
`
3108
3131
` BIOPointer bio(BIO_new_mem_buf(key, key_len));
`
3109
3132
`if (!bio)
`
3110
``
`-
return pkey;
`
``
3133
`+
return ParseKeyResult::kParseKeyFailed;
`
3111
3134
``
3112
``
`-
char* pass = const_cast<char*>(config.passphrase_.get());
`
3113
``
`-
pkey.reset(PEM_read_bio_PrivateKey(bio.get(),
`
3114
``
`-
nullptr,
`
3115
``
`-
PasswordCallback,
`
3116
``
`-
pass));
`
``
3135
`+
pkey->reset(PEM_read_bio_PrivateKey(bio.get(),
`
``
3136
`+
nullptr,
`
``
3137
`+
PasswordCallback,
`
``
3138
`+
&pc_info));
`
3117
3139
` } else {
`
3118
3140
`CHECK_EQ(config.format_, kKeyFormatDER);
`
3119
3141
``
3120
3142
`if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
`
3121
3143
`const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
`
3122
``
`-
pkey.reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, key_len));
`
``
3144
`+
pkey->reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, key_len));
`
3123
3145
` } else if (config.type_.ToChecked() == kKeyEncodingPKCS8) {
`
3124
3146
` BIOPointer bio(BIO_new_mem_buf(key, key_len));
`
3125
3147
`if (!bio)
`
3126
``
`-
return pkey;
`
``
3148
`+
return ParseKeyResult::kParseKeyFailed;
`
3127
3149
``
3128
3150
`if (IsEncryptedPrivateKeyInfo(
`
3129
3151
`reinterpret_cast<const unsigned char*>(key), key_len)) {
`
3130
``
`-
char* pass = const_cast<char*>(config.passphrase_.get());
`
3131
``
`-
pkey.reset(d2i_PKCS8PrivateKey_bio(bio.get(),
`
3132
``
`-
nullptr,
`
3133
``
`-
PasswordCallback,
`
3134
``
`-
pass));
`
``
3152
`+
pkey->reset(d2i_PKCS8PrivateKey_bio(bio.get(),
`
``
3153
`+
nullptr,
`
``
3154
`+
PasswordCallback,
`
``
3155
`+
&pc_info));
`
3135
3156
` } else {
`
3136
3157
` PKCS8Pointer p8inf(d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr));
`
3137
3158
`if (p8inf)
`
3138
``
`-
pkey.reset(EVP_PKCS82PKEY(p8inf.get()));
`
``
3159
`+
pkey->reset(EVP_PKCS82PKEY(p8inf.get()));
`
3139
3160
` }
`
3140
3161
` } else {
`
3141
3162
`CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSEC1);
`
3142
3163
`const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
`
3143
``
`-
pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, key_len));
`
``
3164
`+
pkey->reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, key_len));
`
3144
3165
` }
`
3145
3166
` }
`
3146
3167
``
3147
3168
`// OpenSSL can fail to parse the key but still return a non-null pointer.
`
3148
3169
`if (ERR_peek_error() != 0)
`
3149
``
`-
pkey.reset();
`
``
3170
`+
pkey->reset();
`
3150
3171
``
3151
``
`-
return pkey;
`
``
3172
`+
if (*pkey)
`
``
3173
`+
return ParseKeyResult::kParseKeyOk;
`
``
3174
`+
if (pc_info.CalledButEmpty())
`
``
3175
`+
return ParseKeyResult::kParseKeyNeedPassphrase;
`
``
3176
`+
return ParseKeyResult::kParseKeyFailed;
`
3152
3177
`}
`
3153
3178
``
3154
3179
`ByteSource::ByteSource(ByteSource&& other)
`
`@@ -3284,6 +3309,25 @@ static PublicKeyEncodingConfig GetPublicKeyEncodingFromJs(
`
3284
3309
`return result;
`
3285
3310
`}
`
3286
3311
``
``
3312
`+
static inline ManagedEVPPKey GetParsedKey(Environment* env,
`
``
3313
`+
EVPKeyPointer&& pkey,
`
``
3314
`+
ParseKeyResult ret,
`
``
3315
`+
const char* default_msg) {
`
``
3316
`+
switch (ret) {
`
``
3317
`+
case ParseKeyResult::kParseKeyOk:
`
``
3318
`+
CHECK(pkey);
`
``
3319
`+
break;
`
``
3320
`+
case ParseKeyResult::kParseKeyNeedPassphrase:
`
``
3321
`+
THROW_ERR_MISSING_PASSPHRASE(env,
`
``
3322
`+
"Passphrase required for encrypted key");
`
``
3323
`+
break;
`
``
3324
`+
default:
`
``
3325
`+
ThrowCryptoError(env, ERR_get_error(), default_msg);
`
``
3326
`+
}
`
``
3327
+
``
3328
`+
return ManagedEVPPKey(std::move(pkey));
`
``
3329
`+
}
`
``
3330
+
3287
3331
`static NonCopyableMaybe GetPrivateKeyEncodingFromJs(
`
3288
3332
`const FunctionCallbackInfo& args,
`
3289
3333
`unsigned int* offset,
`
`@@ -3339,11 +3383,12 @@ static ManagedEVPPKey GetPrivateKeyFromJs(
`
3339
3383
`GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
`
3340
3384
`if (config.IsEmpty())
`
3341
3385
`return ManagedEVPPKey();
`
3342
``
`-
EVPKeyPointer pkey =
`
3343
``
`-
ParsePrivateKey(config.Release(), key.get(), key.size());
`
3344
``
`-
if (!pkey)
`
3345
``
`-
ThrowCryptoError(env, ERR_get_error(), "Failed to read private key");
`
3346
``
`-
return ManagedEVPPKey(std::move(pkey));
`
``
3386
+
``
3387
`+
EVPKeyPointer pkey;
`
``
3388
`+
ParseKeyResult ret =
`
``
3389
`+
ParsePrivateKey(&pkey, config.Release(), key.get(), key.size());
`
``
3390
`+
return GetParsedKey(env, std::move(pkey), ret,
`
``
3391
`+
"Failed to read private key");
`
3347
3392
` } else {
`
3348
3393
`CHECK(args[*offset]->IsObject() && allow_key_object);
`
3349
3394
` KeyObject* key;
`
`@@ -3364,15 +3409,16 @@ static ManagedEVPPKey GetPublicOrPrivateKeyFromJs(
`
3364
3409
`GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
`
3365
3410
`if (config_.IsEmpty())
`
3366
3411
`return ManagedEVPPKey();
`
``
3412
+
``
3413
`+
ParseKeyResult ret;
`
3367
3414
` PrivateKeyEncodingConfig config = config_.Release();
`
3368
3415
` EVPKeyPointer pkey;
`
3369
3416
`if (config.format_ == kKeyFormatPEM) {
`
3370
3417
`// For PEM, we can easily determine whether it is a public or private key
`
3371
3418
`// by looking for the respective PEM tags.
`
3372
``
`-
ParsePublicKeyResult ret = ParsePublicKeyPEM(&pkey, data.get(),
`
3373
``
`-
data.size());
`
3374
``
`-
if (ret == ParsePublicKeyResult::kParsePublicNotRecognized) {
`
3375
``
`-
pkey = ParsePrivateKey(config, data.get(), data.size());
`
``
3419
`+
ret = ParsePublicKeyPEM(&pkey, data.get(), data.size());
`
``
3420
`+
if (ret == ParseKeyResult::kParseKeyNotRecognized) {
`
``
3421
`+
ret = ParsePrivateKey(&pkey, config, data.get(), data.size());
`
3376
3422
` }
`
3377
3423
` } else {
`
3378
3424
`// For DER, the type determines how to parse it. SPKI, PKCS#8 and SEC1 are
`
`@@ -3395,14 +3441,14 @@ static ManagedEVPPKey GetPublicOrPrivateKeyFromJs(
`
3395
3441
` }
`
3396
3442
``
3397
3443
`if (is_public) {
`
3398
``
`-
ParsePublicKey(&pkey, config, data.get(), data.size());
`
``
3444
`+
ret = ParsePublicKey(&pkey, config, data.get(), data.size());
`
3399
3445
` } else {
`
3400
``
`-
pkey = ParsePrivateKey(config, data.get(), data.size());
`
``
3446
`+
ret = ParsePrivateKey(&pkey, config, data.get(), data.size());
`
3401
3447
` }
`
3402
3448
` }
`
3403
``
`-
if (!pkey)
`
3404
``
`-
ThrowCryptoError(env, ERR_get_error(), "Failed to read asymmetric key");
`
3405
``
`-
return ManagedEVPPKey(std::move(pkey));
`
``
3449
+
``
3450
`+
return GetParsedKey(env, std::move(pkey), ret,
`
``
3451
`+
"Failed to read asymmetric key");
`
3406
3452
` } else {
`
3407
3453
`CHECK(args[*offset]->IsObject());
`
3408
3454
` KeyObject* key = Unwrap(args[*offset].As());
`
`@@ -3585,6 +3631,7 @@ KeyType KeyObject::GetKeyType() const {
`
3585
3631
`void KeyObject::Init(const FunctionCallbackInfo& args) {
`
3586
3632
` KeyObject* key;
`
3587
3633
`ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
`
``
3634
`+
MarkPopErrorOnReturn mark_pop_error_on_return;
`
3588
3635
``
3589
3636
`unsigned int offset;
`
3590
3637
` ManagedEVPPKey pkey;
`
`@@ -4780,6 +4827,8 @@ void Sign::SignFinal(const FunctionCallbackInfo& args) {
`
4780
4827
` Sign* sign;
`
4781
4828
`ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder());
`
4782
4829
``
``
4830
`+
ClearErrorOnReturn clear_error_on_return;
`
``
4831
+
4783
4832
`unsigned int offset = 0;
`
4784
4833
` ManagedEVPPKey key = GetPrivateKeyFromJs(args, &offset, true);
`
4785
4834
`if (!key)
`
`@@ -4791,8 +4840,6 @@ void Sign::SignFinal(const FunctionCallbackInfo& args) {
`
4791
4840
`CHECK(args[offset + 1]->IsInt32());
`
4792
4841
`int salt_len = args[offset + 1].As()->Value();
`
4793
4842
``
4794
``
`-
ClearErrorOnReturn clear_error_on_return;
`
4795
``
-
4796
4843
` SignResult ret = sign->SignFinal(
`
4797
4844
` key,
`
4798
4845
` padding,
`