@@ -153,13 +153,33 @@ template int SSLWrap<TLSWrap>::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_t >(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<Value>& 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<PrivateKeyEncodingConfig> GetPrivateKeyEncodingFromJs (
3288
3332
const FunctionCallbackInfo<Value>& 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<KeyObject>(args[*offset].As <Object>());
@@ -3585,6 +3631,7 @@ KeyType KeyObject::GetKeyType() const {
3585
3631
void KeyObject::Init (const FunctionCallbackInfo<Value>& 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<Value>& 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<Value>& args) {
4791
4840
CHECK (args[offset + 1 ]->IsInt32 ());
4792
4841
int salt_len = args[offset + 1 ].As <Int32>()->Value ();
4793
4842
4794
- ClearErrorOnReturn clear_error_on_return;
4795
-
4796
4843
SignResult ret = sign->SignFinal (
4797
4844
key,
4798
4845
padding,
0 commit comments