@@ -105,6 +105,8 @@ using v8::Value;
105105# define IS_OCB_MODE (mode ) ((mode) == EVP_CIPH_OCB_MODE)
106106#endif
107107
108+ void CheckThrow (Environment* env, SignBase::Error error);
109+
108110static const char * const root_certs[] = {
109111#include " node_root_certs.h" // NOLINT(build/include_order)
110112};
@@ -4349,6 +4351,112 @@ void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
43494351}
43504352
43514353
4354+ void Mac::Initialize (Environment* env, Local<Object> target) {
4355+ Local<FunctionTemplate> t = env->NewFunctionTemplate (New);
4356+ t->InstanceTemplate ()->SetInternalFieldCount (Mac::kInternalFieldCount );
4357+
4358+ env->SetProtoMethod (t, " update" , Update);
4359+ env->SetProtoMethod (t, " digest" , Digest);
4360+
4361+ target->Set (env->context (),
4362+ FIXED_ONE_BYTE_STRING (env->isolate (), " Mac" ),
4363+ t->GetFunction (env->context ()).ToLocalChecked ()).Check ();
4364+ }
4365+
4366+
4367+ Mac::Mac (Environment* env, Local<Object> wrap, int nid, EVPMDPointer&& mdctx)
4368+ : BaseObject(env, wrap)
4369+ , nid_(nid)
4370+ , mdctx_(std::move(mdctx)) {
4371+ MakeWeak ();
4372+ }
4373+
4374+
4375+ void Mac::New (const FunctionCallbackInfo<Value>& args) {
4376+ MarkPopErrorOnReturn mark_pop_error_on_return;
4377+ Environment* env = Environment::GetCurrent (args);
4378+
4379+ CHECK (args[0 ]->IsInt32 ());
4380+ const int nid = args[0 ].As <Int32>()->Value ();
4381+
4382+ CHECK (args[1 ]->IsArrayBufferView ());
4383+ ByteSource key = ByteSource::FromBuffer (args[1 ]);
4384+
4385+ const EVP_MD* md = nullptr ;
4386+ if (nid == EVP_PKEY_HMAC) {
4387+ CHECK (args[2 ]->IsString ());
4388+ const node::Utf8Value name (env->isolate (), args[2 ]);
4389+ md = EVP_get_digestbyname (*name);
4390+ if (md == nullptr )
4391+ return CheckThrow (env, SignBase::Error::kSignUnknownDigest );
4392+ }
4393+
4394+ ManagedEVPPKey pkey (
4395+ EVPKeyPointer (
4396+ EVP_PKEY_new_raw_private_key (
4397+ nid, nullptr , reinterpret_cast <const unsigned char *>(key.get ()),
4398+ key.size ())));
4399+
4400+ EVPMDPointer mdctx (EVP_MD_CTX_new ());
4401+
4402+
4403+ EVP_PKEY_CTX* pkctx = nullptr ;
4404+ if (!EVP_DigestSignInit (mdctx.get (), &pkctx, md, nullptr , pkey.get ()))
4405+ return ThrowCryptoError (env, ERR_get_error (), " EVP_DigestSignInit" );
4406+
4407+ // TODO(bnoordhuis) Call EVP_PKEY_CTX_ctrl() or EVP_PKEY_CTX_ctrl_str().
4408+ USE (pkctx);
4409+
4410+ new Mac (env, args.This (), nid, std::move (mdctx));
4411+ }
4412+
4413+
4414+ void Mac::Update (const FunctionCallbackInfo<Value>& args) {
4415+ Decode<Mac>(args, [](Mac* mac, const FunctionCallbackInfo<Value>& args,
4416+ const char * data, size_t size) {
4417+ const int rc = EVP_DigestSignUpdate (mac->mdctx_ .get (), data, size);
4418+ args.GetReturnValue ().Set (rc == 1 );
4419+ });
4420+ }
4421+
4422+
4423+ void Mac::Digest (const FunctionCallbackInfo<Value>& args) {
4424+ Mac* mac;
4425+ ASSIGN_OR_RETURN_UNWRAP (&mac, args.Holder ());
4426+
4427+ MarkPopErrorOnReturn mark_pop_error_on_return;
4428+ Environment* env = Environment::GetCurrent (args);
4429+
4430+ enum encoding encoding = BUFFER;
4431+ if (args.Length () > 0 )
4432+ encoding = ParseEncoding (env->isolate (), args[0 ], BUFFER);
4433+
4434+ size_t size;
4435+ if (!EVP_DigestSignFinal (mac->mdctx_ .get (), nullptr , &size))
4436+ return ThrowCryptoError (env, ERR_get_error (), " EVP_DigestSignFinal" );
4437+
4438+ unsigned char * data = MallocOpenSSL<unsigned char >(size);
4439+ ByteSource source =
4440+ ByteSource::Allocated (reinterpret_cast <char *>(data), size);
4441+
4442+ if (!EVP_DigestSignFinal (mac->mdctx_ .get (), data, &size))
4443+ return ThrowCryptoError (env, ERR_get_error (), " EVP_DigestSignFinal" );
4444+
4445+ Local<Value> error;
4446+ MaybeLocal<Value> rc =
4447+ StringBytes::Encode (env->isolate (), source.get (), source.size (),
4448+ encoding, &error);
4449+
4450+ if (rc.IsEmpty ()) {
4451+ CHECK (!error.IsEmpty ());
4452+ env->isolate ()->ThrowException (error);
4453+ return ;
4454+ }
4455+
4456+ args.GetReturnValue ().Set (rc.ToLocalChecked ());
4457+ }
4458+
4459+
43524460SignBase::Error SignBase::Init (const char * sign_type) {
43534461 CHECK_NULL (mdctx_);
43544462 // Historically, "dss1" and "DSS1" were DSA aliases for SHA-1
@@ -6864,6 +6972,7 @@ void Initialize(Local<Object> target,
68646972 ECDH::Initialize (env, target);
68656973 Hmac::Initialize (env, target);
68666974 Hash::Initialize (env, target);
6975+ Mac::Initialize (env, target);
68676976 Sign::Initialize (env, target);
68686977 Verify::Initialize (env, target);
68696978
@@ -6895,6 +7004,9 @@ void Initialize(Local<Object> target,
68957004 env->SetMethod (target, " generateKeyPairDH" , GenerateKeyPairDH);
68967005 NODE_DEFINE_CONSTANT (target, EVP_PKEY_ED25519);
68977006 NODE_DEFINE_CONSTANT (target, EVP_PKEY_ED448);
7007+ NODE_DEFINE_CONSTANT (target, EVP_PKEY_HMAC);
7008+ NODE_DEFINE_CONSTANT (target, EVP_PKEY_POLY1305);
7009+ NODE_DEFINE_CONSTANT (target, EVP_PKEY_SIPHASH);
68987010 NODE_DEFINE_CONSTANT (target, EVP_PKEY_X25519);
68997011 NODE_DEFINE_CONSTANT (target, EVP_PKEY_X448);
69007012 NODE_DEFINE_CONSTANT (target, OPENSSL_EC_NAMED_CURVE);
0 commit comments