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,

`