@@ -6628,6 +6628,71 @@ class NidKeyPairGenerationConfig : public KeyPairGenerationConfig {
66286628 const int id_;
66296629};
66306630
6631+ // TODO(tniessen): Use std::variant instead.
6632+ // Diffie-Hellman can either generate keys using a fixed prime, or by first
6633+ // generating a random prime of a given size (in bits). Only one of both options
6634+ // may be specified.
6635+ struct PrimeInfo {
6636+ BignumPointer fixed_value_;
6637+ unsigned int prime_size_;
6638+ };
6639+
6640+ class DHKeyPairGenerationConfig : public KeyPairGenerationConfig {
6641+ public:
6642+ explicit DHKeyPairGenerationConfig (PrimeInfo&& prime_info,
6643+ unsigned int generator)
6644+ : prime_info_(std::move(prime_info)),
6645+ generator_(generator) {}
6646+
6647+ EVPKeyCtxPointer Setup () override {
6648+ EVPKeyPointer params;
6649+ if (prime_info_.fixed_value_ ) {
6650+ DHPointer dh (DH_new ());
6651+ if (!dh)
6652+ return nullptr ;
6653+
6654+ BIGNUM* prime = prime_info_.fixed_value_ .get ();
6655+ BignumPointer bn_g (BN_new ());
6656+ if (!BN_set_word (bn_g.get (), generator_) ||
6657+ !DH_set0_pqg (dh.get (), prime, nullptr , bn_g.get ()))
6658+ return nullptr ;
6659+
6660+ prime_info_.fixed_value_ .release ();
6661+ bn_g.release ();
6662+
6663+ params = EVPKeyPointer (EVP_PKEY_new ());
6664+ CHECK (params);
6665+ EVP_PKEY_assign_DH (params.get (), dh.release ());
6666+ } else {
6667+ EVPKeyCtxPointer param_ctx (EVP_PKEY_CTX_new_id (EVP_PKEY_DH, nullptr ));
6668+ if (!param_ctx)
6669+ return nullptr ;
6670+
6671+ if (EVP_PKEY_paramgen_init (param_ctx.get ()) <= 0 )
6672+ return nullptr ;
6673+
6674+ if (EVP_PKEY_CTX_set_dh_paramgen_prime_len (param_ctx.get (),
6675+ prime_info_.prime_size_ ) <= 0 )
6676+ return nullptr ;
6677+
6678+ if (EVP_PKEY_CTX_set_dh_paramgen_generator (param_ctx.get (),
6679+ generator_) <= 0 )
6680+ return nullptr ;
6681+
6682+ EVP_PKEY* raw_params = nullptr ;
6683+ if (EVP_PKEY_paramgen (param_ctx.get (), &raw_params) <= 0 )
6684+ return nullptr ;
6685+ params = EVPKeyPointer (raw_params);
6686+ }
6687+
6688+ return EVPKeyCtxPointer (EVP_PKEY_CTX_new (params.get (), nullptr ));
6689+ }
6690+
6691+ private:
6692+ PrimeInfo prime_info_;
6693+ unsigned int generator_;
6694+ };
6695+
66316696class GenerateKeyPairJob : public CryptoJob {
66326697 public:
66336698 GenerateKeyPairJob (Environment* env,
@@ -6847,6 +6912,39 @@ void GenerateKeyPairNid(const FunctionCallbackInfo<Value>& args) {
68476912 GenerateKeyPair (args, 1 , std::move (config));
68486913}
68496914
6915+ void GenerateKeyPairDH (const FunctionCallbackInfo<Value>& args) {
6916+ Environment* env = Environment::GetCurrent (args);
6917+
6918+ PrimeInfo prime_info = {};
6919+ unsigned int generator;
6920+ if (args[0 ]->IsString ()) {
6921+ String::Utf8Value group_name (args.GetIsolate (), args[0 ].As <String>());
6922+ const modp_group* group = FindDiffieHellmanGroup (*group_name);
6923+ if (group == nullptr )
6924+ return THROW_ERR_CRYPTO_UNKNOWN_DH_GROUP (env);
6925+
6926+ prime_info.fixed_value_ = BignumPointer (
6927+ BN_bin2bn (reinterpret_cast <const unsigned char *>(group->prime ),
6928+ group->prime_size , nullptr ));
6929+ generator = group->gen ;
6930+ } else {
6931+ if (args[0 ]->IsInt32 ()) {
6932+ prime_info.prime_size_ = args[0 ].As <Int32>()->Value ();
6933+ } else {
6934+ ArrayBufferViewContents<unsigned char > input (args[0 ]);
6935+ prime_info.fixed_value_ = BignumPointer (
6936+ BN_bin2bn (input.data (), input.length (), nullptr ));
6937+ }
6938+
6939+ CHECK (args[1 ]->IsInt32 ());
6940+ generator = args[1 ].As <Int32>()->Value ();
6941+ }
6942+
6943+ std::unique_ptr<KeyPairGenerationConfig> config (
6944+ new DHKeyPairGenerationConfig (std::move (prime_info), generator));
6945+ GenerateKeyPair (args, 2 , std::move (config));
6946+ }
6947+
68506948
68516949void GetSSLCiphers (const FunctionCallbackInfo<Value>& args) {
68526950 Environment* env = Environment::GetCurrent (args);
@@ -7253,6 +7351,7 @@ void Initialize(Local<Object> target,
72537351 env->SetMethod (target, " generateKeyPairDSA" , GenerateKeyPairDSA);
72547352 env->SetMethod (target, " generateKeyPairEC" , GenerateKeyPairEC);
72557353 env->SetMethod (target, " generateKeyPairNid" , GenerateKeyPairNid);
7354+ env->SetMethod (target, " generateKeyPairDH" , GenerateKeyPairDH);
72567355 NODE_DEFINE_CONSTANT (target, EVP_PKEY_ED25519);
72577356 NODE_DEFINE_CONSTANT (target, EVP_PKEY_ED448);
72587357 NODE_DEFINE_CONSTANT (target, EVP_PKEY_X25519);
0 commit comments