88#include " crypto/crypto_util.h"
99#include " env-inl.h"
1010#include " memory_tracker-inl.h"
11- #include " node_buffer.h"
1211#include " threadpoolwork-inl.h"
1312#include " v8.h"
1413
1514namespace node {
1615
1716using ncrypto::EVPKeyPointer;
1817using v8::Array;
19- using v8::ArrayBufferView;
2018using v8::FunctionCallbackInfo;
2119using v8::Local;
2220using v8::Maybe;
2321using v8::MaybeLocal;
2422using v8::Nothing;
2523using v8::Object;
24+ using v8::Uint8Array;
2625using v8::Value;
2726
2827namespace crypto {
@@ -49,49 +48,6 @@ void KEMConfiguration::MemoryInfo(MemoryTracker* tracker) const {
4948
5049namespace {
5150
52- bool DoKEMEncapsulate (Environment* env,
53- const EVPKeyPointer& public_key,
54- ByteSource* out,
55- CryptoJobMode mode,
56- CryptoErrorStore* errors) {
57- auto result = ncrypto::KEM::Encapsulate (public_key);
58- if (!result) {
59- errors->Insert (NodeCryptoError::ENCAPSULATION_FAILED );
60- errors->SetNodeErrorCode (" ERR_CRYPTO_OPERATION_FAILED" );
61- return false ;
62- }
63-
64- // Pack the result: [ciphertext_len][shared_key_len][ciphertext][shared_key]
65- size_t ciphertext_len = result->ciphertext .size ();
66- size_t shared_key_len = result->shared_key .size ();
67- size_t total_len =
68- sizeof (uint32_t ) + sizeof (uint32_t ) + ciphertext_len + shared_key_len;
69-
70- auto data = ncrypto::DataPointer::Alloc (total_len);
71- if (!data) {
72- errors->Insert (NodeCryptoError::ALLOCATION_FAILED );
73- errors->SetNodeErrorCode (" ERR_CRYPTO_OPERATION_FAILED" );
74- return false ;
75- }
76-
77- unsigned char * ptr = static_cast <unsigned char *>(data.get ());
78-
79- // Write size headers
80- *reinterpret_cast <uint32_t *>(ptr) = static_cast <uint32_t >(ciphertext_len);
81- *reinterpret_cast <uint32_t *>(ptr + sizeof (uint32_t )) =
82- static_cast <uint32_t >(shared_key_len);
83-
84- // Write ciphertext and shared key data
85- unsigned char * ciphertext_ptr = ptr + 2 * sizeof (uint32_t );
86- unsigned char * shared_key_ptr = ciphertext_ptr + ciphertext_len;
87-
88- std::memcpy (ciphertext_ptr, result->ciphertext .get (), ciphertext_len);
89- std::memcpy (shared_key_ptr, result->shared_key .get (), shared_key_len);
90-
91- *out = ByteSource::Allocated (data.release ());
92- return true ;
93- }
94-
9551bool DoKEMDecapsulate (Environment* env,
9652 const EVPKeyPointer& private_key,
9753 const ByteSource& ciphertext,
@@ -133,72 +89,109 @@ Maybe<void> KEMEncapsulateTraits::AdditionalConfig(
13389 return v8::JustVoid ();
13490}
13591
136- bool KEMEncapsulateTraits::DeriveBits (Environment* env,
137- const KEMConfiguration& params,
138- ByteSource* out,
139- CryptoJobMode mode,
140- CryptoErrorStore* errors) {
141- Mutex::ScopedLock lock (params.key .mutex ());
142- const auto & public_key = params.key .GetAsymmetricKey ();
92+ void KEMEncapsulateJob::New (const FunctionCallbackInfo<Value>& args) {
93+ Environment* env = Environment::GetCurrent (args);
94+ CHECK (args.IsConstructCall ());
95+
96+ CryptoJobMode mode = GetCryptoJobMode (args[0 ]);
97+ AdditionalParams params;
98+ if (KEMEncapsulateTraits::AdditionalConfig (mode, args, 1 , ¶ms)
99+ .IsNothing ()) {
100+ return ;
101+ }
143102
144- return DoKEMEncapsulate (env, public_key, out, mode, errors );
103+ new KEMEncapsulateJob (env, args. This (), mode, std::move (params) );
145104}
146105
147- MaybeLocal<Value> KEMEncapsulateTraits::EncodeOutput (
148- Environment* env, const KEMConfiguration& params, ByteSource* out) {
149- // The output contains:
150- // [ciphertext_len][shared_key_len][ciphertext][shared_key]
151- const unsigned char * data = out-> data < unsigned char >();
152-
153- uint32_t ciphertext_len = * reinterpret_cast < const uint32_t *>(data );
154- uint32_t shared_key_len =
155- * reinterpret_cast < const uint32_t *>(data + sizeof ( uint32_t ));
156-
157- const unsigned char * ciphertext_ptr = data + 2 * sizeof ( uint32_t );
158- const unsigned char * shared_key_ptr = ciphertext_ptr + ciphertext_len;
159-
160- MaybeLocal<Object> ciphertext_buf =
161- node::Buffer::Copy (env-> isolate () ,
162- reinterpret_cast < const char *>(ciphertext_ptr) ,
163- ciphertext_len);
164-
165- MaybeLocal<Object> shared_key_buf =
166- node::Buffer::Copy (env-> isolate (),
167- reinterpret_cast < const char *>(shared_key_ptr),
168- shared_key_len );
169-
170- Local<Object> ciphertext_obj ;
171- Local<Object> shared_key_obj;
172- if (!ciphertext_buf. ToLocal (&ciphertext_obj) ||
173- !shared_key_buf. ToLocal (&shared_key_obj)) {
174- return MaybeLocal<Value>( );
106+ void KEMEncapsulateJob::Initialize (Environment* env, Local<Object> target) {
107+ CryptoJob<KEMEncapsulateTraits>:: Initialize (New, env, target);
108+ }
109+
110+ void KEMEncapsulateJob::RegisterExternalReferences (
111+ ExternalReferenceRegistry* registry) {
112+ CryptoJob<KEMEncapsulateTraits>:: RegisterExternalReferences (New, registry );
113+ }
114+
115+ KEMEncapsulateJob::KEMEncapsulateJob (Environment* env,
116+ Local<Object> object,
117+ CryptoJobMode mode,
118+ AdditionalParams&& params)
119+ : CryptoJob<KEMEncapsulateTraits>(env,
120+ object ,
121+ KEMEncapsulateTraits::Provider ,
122+ mode,
123+ std::move (params)) {}
124+
125+ void KEMEncapsulateJob::DoThreadPoolWork () {
126+ ncrypto::ClearErrorOnReturn clear_error_on_return;
127+ AdditionalParams* params = CryptoJob<KEMEncapsulateTraits>:: params ( );
128+ Mutex::ScopedLock lock (params-> key . mutex ());
129+ out_ = ncrypto::KEM::Encapsulate (params-> key . GetAsymmetricKey ()) ;
130+ if (!out_) {
131+ CryptoErrorStore* errors = CryptoJob<KEMEncapsulateTraits>:: errors ();
132+ errors-> Insert (NodeCryptoError:: ENCAPSULATION_FAILED );
133+ errors-> SetNodeErrorCode ( " ERR_CRYPTO_OPERATION_FAILED " );
175134 }
135+ }
176136
177- if (params.job_mode == kCryptoJobWebCrypto ) {
178- Local<Object> result = Object::New (env->isolate ());
179- if (!result
137+ Maybe<void > KEMEncapsulateJob::ToResult (Local<Value>* err,
138+ Local<Value>* result) {
139+ Environment* env = AsyncWrap::env ();
140+ CryptoErrorStore* errors = CryptoJob<KEMEncapsulateTraits>::errors ();
141+ if (!out_) {
142+ if (errors->Empty ()) errors->Capture ();
143+ CHECK (!errors->Empty ());
144+ *result = v8::Undefined (env->isolate ());
145+ if (!errors->ToException (env).ToLocal (err)) return Nothing<void >();
146+ return v8::JustVoid ();
147+ }
148+
149+ CHECK (errors->Empty ());
150+ *err = v8::Undefined (env->isolate ());
151+
152+ ByteSource ciphertext = ByteSource::Allocated (out_->ciphertext .release ());
153+ ByteSource shared_key = ByteSource::Allocated (out_->shared_key .release ());
154+
155+ if (mode () == kCryptoJobWebCrypto ) {
156+ Local<Object> output = Object::New (env->isolate ());
157+ if (!output
180158 ->DefineOwnProperty (env->context (),
181159 OneByteString (env->isolate (), " sharedKey" ),
182- shared_key_obj. As <ArrayBufferView>()-> Buffer ( ))
160+ shared_key. ToArrayBuffer (env ))
183161 .FromMaybe (false ) ||
184- !result
162+ !output
185163 ->DefineOwnProperty (env->context (),
186164 OneByteString (env->isolate (), " ciphertext" ),
187- ciphertext_obj. As <ArrayBufferView>()-> Buffer ( ))
165+ ciphertext. ToArrayBuffer (env ))
188166 .FromMaybe (false )) {
189- return MaybeLocal<Value >();
167+ return Nothing< void >();
190168 }
191- return result;
169+ *result = output;
170+ return v8::JustVoid ();
192171 }
193172
194- // Return an array [sharedKey, ciphertext].
195- Local<Array> result = Array::New (env-> isolate (), 2 ) ;
196- if (result-> Set (env-> context (), 0 , shared_key_obj). IsNothing ( ) ||
197- result-> Set (env-> context (), 1 , ciphertext_obj). IsNothing ( )) {
198- return MaybeLocal<Value >();
173+ Local<Uint8Array> shared_key_buf;
174+ Local<Uint8Array> ciphertext_buf ;
175+ if (!shared_key. ToBuffer (env). ToLocal (&shared_key_buf ) ||
176+ !ciphertext. ToBuffer (env). ToLocal (&ciphertext_buf )) {
177+ return Nothing< void >();
199178 }
200179
201- return result;
180+ Local<Array> output = Array::New (env->isolate (), 2 );
181+ if (output->Set (env->context (), 0 , shared_key_buf).IsNothing () ||
182+ output->Set (env->context (), 1 , ciphertext_buf).IsNothing ()) {
183+ return Nothing<void >();
184+ }
185+ *result = output;
186+ return v8::JustVoid ();
187+ }
188+
189+ void KEMEncapsulateJob::MemoryInfo (MemoryTracker* tracker) const {
190+ if (out_) {
191+ tracker->TrackFieldWithSize (" ciphertext" , out_->ciphertext .size ());
192+ tracker->TrackFieldWithSize (" shared_key" , out_->shared_key .size ());
193+ }
194+ CryptoJob<KEMEncapsulateTraits>::MemoryInfo (tracker);
202195}
203196
204197// KEMDecapsulateTraits implementation
0 commit comments