asherah 3.0.13 → 4.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/asherah.cc DELETED
@@ -1,792 +0,0 @@
1
- #pragma clang diagnostic push
2
- #pragma ide diagnostic ignored "readability-convert-member-functions-to-static"
3
-
4
- #include "asherah_async_worker.h"
5
- #include "cobhan_buffer_napi.h"
6
- #include "hints.h"
7
- #include "libasherah.h"
8
- #include "logging_napi.h"
9
- #include "napi_utils.h"
10
- #include "scoped_allocate.h"
11
- #include <atomic>
12
- #include <napi.h>
13
-
14
- static volatile std::atomic<int32_t> setup_state{0};
15
-
16
- class Asherah : public Napi::Addon<Asherah> {
17
- public:
18
- Asherah(Napi::Env env, Napi::Object exports) : logger(env, "asherah-node") {
19
- DefineAddon(
20
- exports,
21
- {
22
- InstanceMethod("setup", &Asherah::SetupAsherahSync),
23
- InstanceMethod("setup_async", &Asherah::SetupAsherahAsync),
24
- InstanceMethod("encrypt", &Asherah::EncryptSync),
25
- InstanceMethod("encrypt_async", &Asherah::EncryptAsync),
26
- InstanceMethod("encrypt_string", &Asherah::EncryptSync),
27
- InstanceMethod("encrypt_string_async", &Asherah::EncryptAsync),
28
- InstanceMethod("decrypt", &Asherah::DecryptSync),
29
- InstanceMethod("decrypt_async", &Asherah::DecryptAsync),
30
- InstanceMethod("decrypt_string", &Asherah::DecryptStringSync),
31
- InstanceMethod("decrypt_string_async",
32
- &Asherah::DecryptStringAsync),
33
- InstanceMethod("shutdown", &Asherah::ShutdownAsherahSync),
34
- InstanceMethod("shutdown_async", &Asherah::ShutdownAsherahAsync),
35
- InstanceMethod("set_max_stack_alloc_item_size",
36
- &Asherah::SetMaxStackAllocItemSize),
37
- InstanceMethod("set_safety_padding_overhead",
38
- &Asherah::SetSafetyPaddingOverhead),
39
- InstanceMethod("get_setup_status", &Asherah::GetSetupStatus),
40
- InstanceMethod("set_log_hook", &Asherah::SetLogHook),
41
- InstanceMethod("setenv", &Asherah::SetEnv),
42
- });
43
- }
44
-
45
- private:
46
- size_t est_intermediate_key_overhead = 0;
47
- size_t maximum_stack_alloc_size = 2048;
48
-
49
- int32_t verbose_flag = 0;
50
- Napi::FunctionReference log_hook;
51
- LoggerNapi logger;
52
-
53
- #pragma region Published Node Addon Methods
54
-
55
- void SetupAsherahSync(const Napi::CallbackInfo &info) {
56
- Napi::Env env = info.Env();
57
- Napi::HandleScope scope(env);
58
- try {
59
- Napi::String config_string;
60
- size_t product_id_length;
61
- size_t service_name_length;
62
-
63
- BeginSetupAsherah(env, __func__, info, config_string, product_id_length,
64
- service_name_length);
65
-
66
- #ifdef USE_SCOPED_ALLOCATE_BUFFER
67
- char *config_cbuffer;
68
- size_t config_cbuffer_size =
69
- CobhanBufferNapi::StringToAllocationSize(env, config_string);
70
- SCOPED_ALLOCATE_BUFFER(config_cbuffer, config_cbuffer_size,
71
- maximum_stack_alloc_size, __func__);
72
-
73
- CobhanBufferNapi config(env, config_string, config_cbuffer,
74
- config_cbuffer_size);
75
- #else
76
- CobhanBufferNapi config(env, config_string);
77
- #endif
78
-
79
- // extern GoInt32 SetupJson(void* configJson);
80
- GoInt32 result = SetupJson(config);
81
- EndSetupAsherah(env, result, product_id_length, service_name_length);
82
- } catch (Napi::Error &e) {
83
- e.ThrowAsJavaScriptException();
84
- return;
85
- } catch (const std::exception &e) {
86
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
87
- return;
88
- }
89
- }
90
-
91
- Napi::Value SetupAsherahAsync(const Napi::CallbackInfo &info) {
92
- Napi::Env env = info.Env();
93
- Napi::HandleScope scope(env);
94
- try {
95
- Napi::String config_string;
96
- size_t product_id_length;
97
- size_t service_name_length;
98
-
99
- BeginSetupAsherah(env, __func__, info, config_string, product_id_length,
100
- service_name_length);
101
-
102
- CobhanBufferNapi config(env, config_string);
103
-
104
- auto worker = new SetupAsherahWorker(env, this, config, product_id_length,
105
- service_name_length);
106
- worker->Queue();
107
- return worker->Promise();
108
- } catch (Napi::Error &e) {
109
- e.ThrowAsJavaScriptException();
110
- return env.Undefined();
111
- } catch (const std::exception &e) {
112
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
113
- return env.Undefined();
114
- }
115
- }
116
-
117
- void ShutdownAsherahSync(const Napi::CallbackInfo &info) {
118
- Napi::Env env = info.Env();
119
- Napi::HandleScope scope(env);
120
- try {
121
- BeginShutdownAsherah(env, __func__, info);
122
- Shutdown();
123
- EndShutdownAsherah(env);
124
- } catch (Napi::Error &e) {
125
- e.ThrowAsJavaScriptException();
126
- return;
127
- } catch (const std::exception &e) {
128
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
129
- return;
130
- }
131
- }
132
-
133
- Napi::Value ShutdownAsherahAsync(const Napi::CallbackInfo &info) {
134
- Napi::Env env = info.Env();
135
- Napi::HandleScope scope(env);
136
- try {
137
- BeginShutdownAsherah(env, __func__, info);
138
- auto worker = new ShutdownAsherahWorker(env, this);
139
- worker->Queue();
140
- return worker->Promise();
141
- } catch (Napi::Error &e) {
142
- e.ThrowAsJavaScriptException();
143
- return env.Undefined();
144
- } catch (const std::exception &e) {
145
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
146
- return env.Undefined();
147
- }
148
- }
149
-
150
- // This is the exported sync Encrypt function
151
- Napi::Value EncryptSync(const Napi::CallbackInfo &info) {
152
- Napi::Env env = info.Env();
153
- Napi::HandleScope scope(env);
154
- Napi::String output_string;
155
- try {
156
- Napi::String partition_id_string;
157
- Napi::Value input_value;
158
-
159
- BeginEncryptToJson(env, __func__, info, partition_id_string, input_value);
160
-
161
- #ifdef USE_SCOPED_ALLOCATE_BUFFER
162
- char *partition_id_cbuffer;
163
- size_t partition_id_cbuffer_size =
164
- CobhanBufferNapi::StringToAllocationSize(env, partition_id_string);
165
- SCOPED_ALLOCATE_BUFFER(partition_id_cbuffer, partition_id_cbuffer_size,
166
- maximum_stack_alloc_size, __func__);
167
-
168
- char *input_cbuffer;
169
- size_t input_cbuffer_size =
170
- CobhanBufferNapi::ValueToAllocationSize(env, input_value);
171
- SCOPED_ALLOCATE_BUFFER(input_cbuffer, input_cbuffer_size,
172
- maximum_stack_alloc_size, __func__);
173
-
174
- CobhanBufferNapi partition_id(env, partition_id_string,
175
- partition_id_cbuffer,
176
- partition_id_cbuffer_size);
177
- CobhanBufferNapi input(env, input_value, input_cbuffer,
178
- input_cbuffer_size);
179
- #else
180
- CobhanBufferNapi partition_id(env, partition_id_string);
181
- CobhanBufferNapi input(env, input_value);
182
- #endif
183
-
184
- size_t partition_id_data_len_bytes = partition_id.get_data_len_bytes();
185
- size_t input_data_len_bytes = input.get_data_len_bytes();
186
- size_t asherah_output_size_bytes = EstimateAsherahOutputSize(
187
- input_data_len_bytes, partition_id_data_len_bytes);
188
-
189
- #ifdef USE_SCOPED_ALLOCATE_BUFFER
190
- char *output_cobhan_buffer;
191
- size_t output_size_bytes =
192
- CobhanBuffer::DataSizeToAllocationSize(asherah_output_size_bytes);
193
- SCOPED_ALLOCATE_BUFFER(output_cobhan_buffer, output_size_bytes,
194
- maximum_stack_alloc_size, __func__);
195
- CobhanBufferNapi output(env, output_cobhan_buffer, output_size_bytes);
196
- #else
197
- CobhanBufferNapi output(env, asherah_output_size_bytes);
198
- #endif
199
-
200
- GoInt32 result = EncryptToJson(partition_id, input, output);
201
-
202
- EndEncryptToJson(env, output, result, output_string);
203
- } catch (Napi::Error &e) {
204
- e.ThrowAsJavaScriptException();
205
- return env.Undefined();
206
- } catch (const std::exception &e) {
207
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
208
- return env.Undefined();
209
- }
210
-
211
- return output_string;
212
- }
213
-
214
- // This is the exported async Encrypt function
215
- Napi::Value EncryptAsync(const Napi::CallbackInfo &info) {
216
- Napi::Env env = info.Env();
217
- Napi::HandleScope scope(env);
218
- try {
219
- Napi::String partition_id_string;
220
- Napi::Value input_value;
221
- BeginEncryptToJson(env, __func__, info, partition_id_string, input_value);
222
-
223
- CobhanBufferNapi partition_id(env, partition_id_string);
224
- CobhanBufferNapi input(env, input_value);
225
-
226
- size_t partition_id_data_len_bytes = partition_id.get_data_len_bytes();
227
- size_t input_data_len_bytes = input.get_data_len_bytes();
228
- size_t asherah_output_size_bytes = EstimateAsherahOutputSize(
229
- input_data_len_bytes, partition_id_data_len_bytes);
230
-
231
- CobhanBufferNapi output(env, asherah_output_size_bytes);
232
-
233
- auto worker =
234
- new EncryptAsherahWorker(env, this, partition_id, input, output);
235
- worker->Queue();
236
- return worker->Promise();
237
- } catch (Napi::Error &e) {
238
- e.ThrowAsJavaScriptException();
239
- return env.Undefined();
240
- } catch (const std::exception &e) {
241
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
242
- return env.Undefined();
243
- }
244
- }
245
-
246
- Napi::Value DecryptSync(const Napi::CallbackInfo &info) {
247
- Napi::Env env = info.Env();
248
- Napi::HandleScope scope(env);
249
- Napi::Object output_value;
250
- try {
251
- Napi::String partition_id_string;
252
- Napi::Value input_value;
253
-
254
- BeginDecryptFromJson(env, __func__, info, partition_id_string,
255
- input_value);
256
-
257
- #ifdef USE_SCOPED_ALLOCATE_BUFFER
258
- char *partition_id_cbuffer;
259
- size_t partition_id_cbuffer_size =
260
- CobhanBufferNapi::StringToAllocationSize(env, partition_id_string);
261
- SCOPED_ALLOCATE_BUFFER(partition_id_cbuffer, partition_id_cbuffer_size,
262
- maximum_stack_alloc_size, __func__);
263
-
264
- char *input_cbuffer;
265
- size_t input_cbuffer_size =
266
- CobhanBufferNapi::ValueToAllocationSize(env, input_value);
267
- SCOPED_ALLOCATE_BUFFER(input_cbuffer, input_cbuffer_size,
268
- maximum_stack_alloc_size, __func__);
269
-
270
- CobhanBufferNapi partition_id(env, partition_id_string,
271
- partition_id_cbuffer,
272
- partition_id_cbuffer_size);
273
- CobhanBufferNapi input(env, input_value, input_cbuffer,
274
- input_cbuffer_size);
275
-
276
- char *output_cobhan_buffer;
277
- size_t output_size_bytes =
278
- CobhanBuffer::DataSizeToAllocationSize(input.get_data_len_bytes());
279
- SCOPED_ALLOCATE_BUFFER(output_cobhan_buffer, output_size_bytes,
280
- maximum_stack_alloc_size, __func__);
281
- CobhanBufferNapi output(env, output_cobhan_buffer, output_size_bytes);
282
- #else
283
- CobhanBufferNapi partition_id(env, partition_id_string);
284
- CobhanBufferNapi input(env, input_value);
285
- CobhanBufferNapi output(env, input.get_data_len_bytes());
286
- #endif
287
-
288
- // extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr,
289
- // void* dataPtr);
290
- GoInt32 result = DecryptFromJson(partition_id, input, output);
291
-
292
- CheckResult(env, result);
293
-
294
- output_value = output.ToBuffer(); // NOLINT(*-slicing)
295
- } catch (Napi::Error &e) {
296
- e.ThrowAsJavaScriptException();
297
- return env.Undefined();
298
- } catch (const std::exception &e) {
299
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
300
- return env.Undefined();
301
- }
302
-
303
- return output_value;
304
- }
305
-
306
- Napi::Value DecryptAsync(const Napi::CallbackInfo &info) {
307
- Napi::Env env = info.Env();
308
- Napi::HandleScope scope(env);
309
- try {
310
- Napi::String partition_id_string;
311
- Napi::Value input_value;
312
- BeginDecryptFromJson(env, __func__, info, partition_id_string,
313
- input_value);
314
-
315
- CobhanBufferNapi partition_id(env, partition_id_string);
316
- CobhanBufferNapi input(env, input_value);
317
-
318
- CobhanBufferNapi output(env, input.get_data_len_bytes());
319
- auto worker = new DecryptFromJsonWorker<Napi::Buffer<unsigned char>>(
320
- env, this, partition_id, input, output);
321
- worker->Queue();
322
- return worker->Promise();
323
- } catch (Napi::Error &e) {
324
- e.ThrowAsJavaScriptException();
325
- return env.Undefined();
326
- } catch (const std::exception &e) {
327
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
328
- return env.Undefined();
329
- }
330
- }
331
-
332
- Napi::Value DecryptStringSync(const Napi::CallbackInfo &info) {
333
- Napi::Env env = info.Env();
334
- Napi::HandleScope scope(env);
335
- Napi::String output_string;
336
- try {
337
- NapiUtils::RequireParameterCount(info, 2);
338
-
339
- Napi::String partition_id_string;
340
- Napi::Value input_value;
341
- BeginDecryptFromJson(env, __func__, info, partition_id_string,
342
- input_value);
343
-
344
- #ifdef USE_SCOPED_ALLOCATE_BUFFER
345
- char *partition_id_cbuffer;
346
- size_t partition_id_cbuffer_size =
347
- CobhanBufferNapi::StringToAllocationSize(env, partition_id_string);
348
- SCOPED_ALLOCATE_BUFFER(partition_id_cbuffer, partition_id_cbuffer_size,
349
- maximum_stack_alloc_size, __func__);
350
-
351
- char *input_cbuffer;
352
- size_t input_cbuffer_size =
353
- CobhanBufferNapi::ValueToAllocationSize(env, input_value);
354
- SCOPED_ALLOCATE_BUFFER(input_cbuffer, input_cbuffer_size,
355
- maximum_stack_alloc_size, __func__);
356
-
357
- CobhanBufferNapi partition_id(env, partition_id_string,
358
- partition_id_cbuffer,
359
- partition_id_cbuffer_size);
360
- CobhanBufferNapi input(env, input_value, input_cbuffer,
361
- input_cbuffer_size);
362
-
363
- CobhanBufferNapi output(env, input.get_data_len_bytes());
364
- #else
365
- CobhanBufferNapi partition_id(env, partition_id_string);
366
- CobhanBufferNapi input(env, input_value);
367
- CobhanBufferNapi output(env, input.get_data_len_bytes());
368
- #endif
369
-
370
- GoInt32 result = DecryptFromJson(partition_id, input, output);
371
-
372
- EndDecryptFromJson(env, output, result, output_string);
373
- } catch (Napi::Error &e) {
374
- e.ThrowAsJavaScriptException();
375
- return env.Undefined();
376
- } catch (const std::exception &e) {
377
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
378
- return env.Undefined();
379
- }
380
- return output_string;
381
- }
382
-
383
- Napi::Value DecryptStringAsync(const Napi::CallbackInfo &info) {
384
- Napi::Env env = info.Env();
385
- Napi::HandleScope scope(env);
386
- try {
387
- NapiUtils::RequireParameterCount(info, 2);
388
-
389
- Napi::String partition_id_string;
390
- Napi::Value input_value;
391
- BeginDecryptFromJson(env, __func__, info, partition_id_string,
392
- input_value);
393
-
394
- CobhanBufferNapi partition_id(env, partition_id_string);
395
- CobhanBufferNapi input(env, input_value);
396
-
397
- CobhanBufferNapi output(env, input.get_data_len_bytes());
398
-
399
- auto worker = new DecryptFromJsonWorker<Napi::String>(
400
- env, this, partition_id, input, output);
401
- worker->Queue();
402
-
403
- return worker->Promise();
404
- } catch (Napi::Error &e) {
405
- e.ThrowAsJavaScriptException();
406
- return env.Undefined();
407
- } catch (const std::exception &e) {
408
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
409
- return env.Undefined();
410
- }
411
- }
412
-
413
- void SetEnv(const Napi::CallbackInfo &info) {
414
- Napi::Env env = info.Env();
415
- Napi::HandleScope scope(env);
416
- try {
417
- NapiUtils::RequireParameterCount(info, 1);
418
- CobhanBufferNapi env_json(env, info[0]);
419
- ::SetEnv(env_json);
420
- } catch (Napi::Error &e) {
421
- e.ThrowAsJavaScriptException();
422
- return;
423
- } catch (const std::exception &e) {
424
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
425
- return;
426
- }
427
- }
428
-
429
- void SetMaxStackAllocItemSize(const Napi::CallbackInfo &info) {
430
- Napi::Env env = info.Env();
431
- Napi::HandleScope scope(env);
432
- try {
433
- NapiUtils::RequireParameterCount(info, 1);
434
-
435
- Napi::Number item_size = info[0].ToNumber();
436
- auto new_size = (size_t)item_size.Int32Value();
437
-
438
- maximum_stack_alloc_size = new_size;
439
- } catch (Napi::Error &e) {
440
- e.ThrowAsJavaScriptException();
441
- return;
442
- } catch (const std::exception &e) {
443
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
444
- return;
445
- }
446
- }
447
-
448
- void SetSafetyPaddingOverhead(const Napi::CallbackInfo &info) {
449
- Napi::Env env = info.Env();
450
- Napi::HandleScope scope(env);
451
- try {
452
- NapiUtils::RequireParameterCount(info, 1);
453
-
454
- // Napi::Number safety_padding_number = info[0].ToNumber();
455
- // auto new_safety_padding_bytes = (size_t)
456
- // safety_padding_number.Int32Value(); Safety padding size is now fixed -
457
- // ignore the input set_safety_padding_bytes(new_safety_padding_bytes);
458
- } catch (Napi::Error &e) {
459
- e.ThrowAsJavaScriptException();
460
- return;
461
- } catch (const std::exception &e) {
462
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
463
- return;
464
- }
465
- }
466
-
467
- Napi::Value
468
- GetSetupStatus(const Napi::CallbackInfo
469
- &info) { // NOLINT(*-convert-member-functions-to-static)
470
- Napi::Env env = info.Env();
471
- Napi::HandleScope scope(env);
472
- try {
473
- int32_t setup_status = setup_state.load(std::memory_order_acquire);
474
- return Napi::Boolean::New(info.Env(), setup_status != 0);
475
- } catch (Napi::Error &e) {
476
- e.ThrowAsJavaScriptException();
477
- return env.Undefined();
478
- } catch (const std::exception &e) {
479
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
480
- return env.Undefined();
481
- }
482
- }
483
-
484
- void SetLogHook(const Napi::CallbackInfo &info) {
485
-
486
- Napi::Env env = info.Env();
487
- Napi::HandleScope scope(env);
488
- try {
489
- NapiUtils::RequireParameterCount(info, 1);
490
-
491
- if (unlikely(!info[0].IsFunction())) {
492
- NapiUtils::ThrowException(info.Env(), "Expected a function");
493
- }
494
-
495
- logger.set_log_hook(info[0].As<Napi::Function>());
496
- } catch (Napi::Error &e) {
497
- e.ThrowAsJavaScriptException();
498
- return;
499
- } catch (const std::exception &e) {
500
- Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
501
- return;
502
- }
503
- }
504
-
505
- void BeginSetupAsherah(const Napi::Env &env, const char *func_name,
506
- const Napi::CallbackInfo &info,
507
- Napi::String &config_string, size_t &product_id_length,
508
- size_t &service_name_length) {
509
- RequireAsherahNotSetup(env, func_name);
510
-
511
- NapiUtils::RequireParameterCount(info, 1);
512
-
513
- Napi::Object config_json;
514
- NapiUtils::AsJsonObjectAndString(env, info[0], config_string, config_json);
515
-
516
- Napi::String product_id;
517
- NapiUtils::GetStringProperty(config_json, "ProductID", product_id);
518
- product_id_length = NapiUtils::GetUtf8StringLength(env, product_id);
519
-
520
- Napi::String service_name;
521
- NapiUtils::GetStringProperty(config_json, "ServiceName", service_name);
522
- service_name_length = NapiUtils::GetUtf8StringLength(env, service_name);
523
-
524
- bool verbose;
525
- NapiUtils::GetBooleanProperty(config_json, "Verbose", verbose, false);
526
- verbose_flag = verbose;
527
- }
528
-
529
- void EndSetupAsherah(const Napi::Env &env, GoInt32 result,
530
- size_t product_id_length, size_t service_name_length) {
531
- CheckResult(env, result);
532
-
533
- est_intermediate_key_overhead = product_id_length + service_name_length;
534
-
535
- auto old_setup_state = setup_state.exchange(1, std::memory_order_acq_rel);
536
- if (unlikely(old_setup_state != 0)) {
537
- NapiUtils::ThrowException(
538
- env, "EndSetupAsherah: lost race to mark setup_state?!");
539
- }
540
- }
541
-
542
- void BeginEncryptToJson(const Napi::Env &env, const char *func_name,
543
- const Napi::CallbackInfo &info,
544
- Napi::String &partition_id, Napi::Value &input) {
545
- RequireAsherahSetup(env, func_name);
546
-
547
- NapiUtils::RequireParameterCount(info, 2);
548
-
549
- partition_id = NapiUtils::RequireParameterString(env, func_name, info[0]);
550
- input = NapiUtils::RequireParameterStringOrBuffer(env, func_name, info[1]);
551
- }
552
-
553
- void EndEncryptToJson(Napi::Env env, CobhanBufferNapi &output, GoInt32 result,
554
- Napi::String &output_string) {
555
- CheckResult(env, result);
556
-
557
- output_string = output.ToString();
558
- }
559
-
560
- [[maybe_unused]] void
561
- EndEncryptToJson(Napi::Env env, CobhanBufferNapi &output, GoInt32 result,
562
- Napi::Buffer<unsigned char> &output_buffer) {
563
- CheckResult(env, result);
564
-
565
- output_buffer = output.ToBuffer();
566
- }
567
-
568
- void BeginDecryptFromJson(const Napi::Env &env, const char *func_name,
569
- const Napi::CallbackInfo &info,
570
- Napi::String &partition_id, Napi::Value &input) {
571
- RequireAsherahSetup(env, func_name);
572
-
573
- NapiUtils::RequireParameterCount(info, 2);
574
-
575
- partition_id = NapiUtils::RequireParameterString(env, func_name, info[0]);
576
- input = NapiUtils::RequireParameterStringOrBuffer(env, func_name, info[1]);
577
- }
578
-
579
- void EndDecryptFromJson(Napi::Env &env, CobhanBufferNapi &output,
580
- GoInt32 result,
581
- Napi::Buffer<unsigned char> &output_buffer) {
582
- CheckResult(env, result);
583
-
584
- output_buffer = output.ToBuffer();
585
- }
586
-
587
- void EndDecryptFromJson(Napi::Env &env, CobhanBufferNapi &output,
588
- GoInt32 result, Napi::String &output_string) {
589
- CheckResult(env, result);
590
-
591
- output_string = output.ToString();
592
- }
593
-
594
- void BeginShutdownAsherah(const Napi::Env &env, const char *func_name,
595
- const Napi::CallbackInfo &info) {
596
- RequireAsherahSetup(env, func_name);
597
- NapiUtils::RequireParameterCount(info, 0);
598
- }
599
-
600
- void EndShutdownAsherah(Napi::Env &env) {
601
- auto old_setup_state = setup_state.exchange(0, std::memory_order_acq_rel);
602
- if (unlikely(old_setup_state == 0)) {
603
- NapiUtils::ThrowException(
604
- env, "EndSetupAsherah: lost race to mark setup_state?!");
605
- }
606
- }
607
-
608
- #pragma endregion Begin / End Methods
609
-
610
- #pragma region AsyncWorkers
611
-
612
- class SetupAsherahWorker : public AsherahAsyncWorker<GoInt32> {
613
- public:
614
- SetupAsherahWorker(Napi::Env env, Asherah *instance,
615
- CobhanBufferNapi &config, size_t product_id_length,
616
- size_t service_name_length)
617
- : AsherahAsyncWorker<GoInt32>(env, instance), config(std::move(config)),
618
- product_id_length(product_id_length),
619
- service_name_length(service_name_length) {}
620
-
621
- GoInt32 ExecuteTask() override { return SetupJson(config); }
622
-
623
- Napi::Value OnOKTask(Napi::Env &env) override {
624
- asherah->EndSetupAsherah(env, result, product_id_length,
625
- service_name_length);
626
- return env.Undefined();
627
- }
628
-
629
- private:
630
- CobhanBufferNapi config;
631
- size_t product_id_length;
632
- size_t service_name_length;
633
- };
634
-
635
- class EncryptAsherahWorker : public AsherahAsyncWorker<GoInt32> {
636
- public:
637
- EncryptAsherahWorker(const Napi::Env &env, Asherah *instance,
638
- CobhanBufferNapi &partition_id,
639
- CobhanBufferNapi &input, CobhanBufferNapi &output)
640
- : AsherahAsyncWorker(env, instance),
641
- partition_id(std::move(partition_id)), input(std::move(input)),
642
- output(std::move(output)) {}
643
-
644
- // extern GoInt32 EncryptToJson(void* partitionIdPtr, void* dataPtr,
645
- // void* jsonPtr);
646
- GoInt32 ExecuteTask() override {
647
- return EncryptToJson(partition_id, input, output);
648
- }
649
-
650
- Napi::Value OnOKTask(Napi::Env &env) override {
651
- Napi::String output_string;
652
- asherah->EndEncryptToJson(env, output, result, output_string);
653
- return output_string;
654
- }
655
-
656
- private:
657
- CobhanBufferNapi partition_id;
658
- CobhanBufferNapi input;
659
- CobhanBufferNapi output;
660
- };
661
-
662
- template <typename T>
663
- class DecryptFromJsonWorker : public AsherahAsyncWorker<GoInt32> {
664
- public:
665
- DecryptFromJsonWorker(const Napi::Env &env, Asherah *instance,
666
- CobhanBufferNapi &partition_id,
667
- CobhanBufferNapi &input, CobhanBufferNapi &output)
668
- : AsherahAsyncWorker(env, instance),
669
- partition_id(std::move(partition_id)), input(std::move(input)),
670
- output(std::move(output)) {}
671
-
672
- GoInt32 ExecuteTask() override {
673
- return DecryptFromJson(partition_id, input, output);
674
- }
675
-
676
- Napi::Value OnOKTask(Napi::Env &env) override {
677
- T output_result;
678
- asherah->EndDecryptFromJson(env, output, result, output_result);
679
- return output_result; // NOLINT(*-slicing)
680
- }
681
-
682
- private:
683
- CobhanBufferNapi partition_id;
684
- CobhanBufferNapi input;
685
- CobhanBufferNapi output;
686
- };
687
-
688
- class ShutdownAsherahWorker : public AsherahAsyncWorker<GoInt32> {
689
- public:
690
- using AsherahAsyncWorker::AsherahAsyncWorker;
691
-
692
- // extern void Shutdown();
693
- GoInt32 ExecuteTask() override {
694
- Shutdown();
695
- return 0;
696
- }
697
-
698
- Napi::Value OnOKTask(Napi::Env &env) override {
699
- asherah->EndShutdownAsherah(env);
700
- return env.Undefined();
701
- }
702
- };
703
-
704
- #pragma endregion AsyncWorkers
705
-
706
- #pragma region Helpers
707
-
708
- void CheckResult(const Napi::Env &env, GoInt32 result) {
709
- if (unlikely(result < 0)) {
710
- NapiUtils::ThrowException(env, AsherahCobhanErrorToString(result));
711
- }
712
- }
713
-
714
- void RequireAsherahSetup(const Napi::Env &env, const char *func_name) {
715
- if (unlikely(setup_state.load(std::memory_order_acquire) == 0)) {
716
- NapiUtils::ThrowException(
717
- env,
718
- std::string(func_name) + ": RequireAsherahSetup: setup() not called");
719
- }
720
- }
721
-
722
- void RequireAsherahNotSetup(const Napi::Env &env, const char *func_name) {
723
- if (unlikely(setup_state.load(std::memory_order_acquire) != 0)) {
724
- NapiUtils::ThrowException(
725
- env, std::string(func_name) +
726
- ": RequireAsherahNotSetup: setup() already called");
727
- }
728
- }
729
-
730
- [[nodiscard]] __attribute__((always_inline)) inline size_t
731
- EstimateAsherahOutputSize(size_t data_byte_len,
732
- size_t partition_byte_len) const {
733
- const size_t est_encryption_overhead = 48;
734
- const size_t est_envelope_overhead = 185;
735
- const double base64_overhead = 1.34;
736
-
737
- // Add one rather than using std::ceil to round up
738
- size_t est_data_byte_len =
739
- size_t(double(data_byte_len + est_encryption_overhead) *
740
- base64_overhead) +
741
- 1;
742
-
743
- return est_envelope_overhead + est_intermediate_key_overhead +
744
- partition_byte_len + est_data_byte_len;
745
- }
746
-
747
- __attribute__((always_inline)) static inline const char *
748
- AsherahCobhanErrorToString(int32_t error) {
749
- switch (error) {
750
- case 0:
751
- return "Success";
752
- case -1:
753
- return "Cobhan error: NULL pointer";
754
- case -2:
755
- return "Cobhan error: Buffer too large";
756
- case -3:
757
- return "Cobhan error: Buffer too small";
758
- case -4:
759
- return "Cobhan error: Copy failed";
760
- case -5:
761
- return "Cobhan error: JSON decode failed";
762
- case -6:
763
- return "Cobhan error: JSON encode failed";
764
- case -7:
765
- return "Cobhan error: Invalid UTF-8";
766
- case -8:
767
- return "Cobhan error: Read temp file failed";
768
- case -9:
769
- return "Cobhan error: Write temp file failed";
770
- case -100:
771
- return "Asherah error: Not initialized";
772
- case -101:
773
- return "Asherah error: Already initialized";
774
- case -102:
775
- return "Asherah error: Failed to get session";
776
- case -103:
777
- return "Asherah error: Encrypt operation failed";
778
- case -104:
779
- return "Asherah error: Decrypt operation failed";
780
- case -105:
781
- return "Asherah error: Invalid configuration";
782
- default:
783
- return "Unknown error";
784
- }
785
- }
786
-
787
- #pragma endregion Helpers
788
- };
789
-
790
- NODE_API_NAMED_ADDON(asherah, Asherah)
791
-
792
- #pragma clang diagnostic pop