@@ -6086,6 +6086,71 @@ class NidKeyPairGenerationConfig : public KeyPairGenerationConfig {
60866086 const int id_;
60876087};
60886088
6089+ // TODO(tniessen): Use std::variant instead.
6090+ // Diffie-Hellman can either generate keys using a fixed prime, or by first
6091+ // generating a random prime of a given size (in bits). Only one of both options
6092+ // may be specified.
6093+ struct PrimeInfo {
6094+ BignumPointer fixed_value_;
6095+ unsigned int prime_size_;
6096+ };
6097+
6098+ class DHKeyPairGenerationConfig : public KeyPairGenerationConfig {
6099+ public:
6100+ explicit DHKeyPairGenerationConfig (PrimeInfo&& prime_info,
6101+ unsigned int generator)
6102+ : prime_info_(std::move(prime_info)),
6103+ generator_(generator) {}
6104+
6105+ EVPKeyCtxPointer Setup () override {
6106+ EVPKeyPointer params;
6107+ if (prime_info_.fixed_value_ ) {
6108+ DHPointer dh (DH_new ());
6109+ if (!dh)
6110+ return nullptr ;
6111+
6112+ BIGNUM* prime = prime_info_.fixed_value_ .get ();
6113+ BignumPointer bn_g (BN_new ());
6114+ if (!BN_set_word (bn_g.get (), generator_) ||
6115+ !DH_set0_pqg (dh.get (), prime, nullptr , bn_g.get ()))
6116+ return nullptr ;
6117+
6118+ prime_info_.fixed_value_ .release ();
6119+ bn_g.release ();
6120+
6121+ params = EVPKeyPointer (EVP_PKEY_new ());
6122+ CHECK (params);
6123+ EVP_PKEY_assign_DH (params.get (), dh.release ());
6124+ } else {
6125+ EVPKeyCtxPointer param_ctx (EVP_PKEY_CTX_new_id (EVP_PKEY_DH, nullptr ));
6126+ if (!param_ctx)
6127+ return nullptr ;
6128+
6129+ if (EVP_PKEY_paramgen_init (param_ctx.get ()) <= 0 )
6130+ return nullptr ;
6131+
6132+ if (EVP_PKEY_CTX_set_dh_paramgen_prime_len (param_ctx.get (),
6133+ prime_info_.prime_size_ ) <= 0 )
6134+ return nullptr ;
6135+
6136+ if (EVP_PKEY_CTX_set_dh_paramgen_generator (param_ctx.get (),
6137+ generator_) <= 0 )
6138+ return nullptr ;
6139+
6140+ EVP_PKEY* raw_params = nullptr ;
6141+ if (EVP_PKEY_paramgen (param_ctx.get (), &raw_params) <= 0 )
6142+ return nullptr ;
6143+ params = EVPKeyPointer (raw_params);
6144+ }
6145+
6146+ return EVPKeyCtxPointer (EVP_PKEY_CTX_new (params.get (), nullptr ));
6147+ }
6148+
6149+ private:
6150+ PrimeInfo prime_info_;
6151+ unsigned int generator_;
6152+ };
6153+
60896154class GenerateKeyPairJob : public CryptoJob {
60906155 public:
60916156 GenerateKeyPairJob (Environment* env,
@@ -6299,6 +6364,39 @@ void GenerateKeyPairNid(const FunctionCallbackInfo<Value>& args) {
62996364 GenerateKeyPair (args, 1 , std::move (config));
63006365}
63016366
6367+ void GenerateKeyPairDH (const FunctionCallbackInfo<Value>& args) {
6368+ Environment* env = Environment::GetCurrent (args);
6369+
6370+ PrimeInfo prime_info = {};
6371+ unsigned int generator;
6372+ if (args[0 ]->IsString ()) {
6373+ String::Utf8Value group_name (args.GetIsolate (), args[0 ].As <String>());
6374+ const modp_group* group = FindDiffieHellmanGroup (*group_name);
6375+ if (group == nullptr )
6376+ return THROW_ERR_CRYPTO_UNKNOWN_DH_GROUP (env);
6377+
6378+ prime_info.fixed_value_ = BignumPointer (
6379+ BN_bin2bn (reinterpret_cast <const unsigned char *>(group->prime ),
6380+ group->prime_size , nullptr ));
6381+ generator = group->gen ;
6382+ } else {
6383+ if (args[0 ]->IsInt32 ()) {
6384+ prime_info.prime_size_ = args[0 ].As <Int32>()->Value ();
6385+ } else {
6386+ ArrayBufferViewContents<unsigned char > input (args[0 ]);
6387+ prime_info.fixed_value_ = BignumPointer (
6388+ BN_bin2bn (input.data (), input.length (), nullptr ));
6389+ }
6390+
6391+ CHECK (args[1 ]->IsInt32 ());
6392+ generator = args[1 ].As <Int32>()->Value ();
6393+ }
6394+
6395+ std::unique_ptr<KeyPairGenerationConfig> config (
6396+ new DHKeyPairGenerationConfig (std::move (prime_info), generator));
6397+ GenerateKeyPair (args, 2 , std::move (config));
6398+ }
6399+
63026400
63036401void GetSSLCiphers (const FunctionCallbackInfo<Value>& args) {
63046402 Environment* env = Environment::GetCurrent (args);
@@ -6732,6 +6830,7 @@ void Initialize(Local<Object> target,
67326830 env->SetMethod (target, " generateKeyPairDSA" , GenerateKeyPairDSA);
67336831 env->SetMethod (target, " generateKeyPairEC" , GenerateKeyPairEC);
67346832 env->SetMethod (target, " generateKeyPairNid" , GenerateKeyPairNid);
6833+ env->SetMethod (target, " generateKeyPairDH" , GenerateKeyPairDH);
67356834 NODE_DEFINE_CONSTANT (target, EVP_PKEY_ED25519);
67366835 NODE_DEFINE_CONSTANT (target, EVP_PKEY_ED448);
67376836 NODE_DEFINE_CONSTANT (target, EVP_PKEY_X25519);
0 commit comments