asherah 1.3.11 → 1.3.13

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/binding.gyp CHANGED
@@ -18,7 +18,12 @@
18
18
  'defines': [ 'NAPI_CPP_EXCEPTIONS', 'NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS' ],
19
19
  'sources': [
20
20
  'lib/libasherah.h',
21
- 'src/asherah.cc'
21
+ 'src/asherah.cc',
22
+ 'src/logging.cc',
23
+ 'src/logging.h',
24
+ 'src/cobhan_napi_interop.cc',
25
+ 'src/cobhan_napi_interop.h',
26
+ 'src/hints.h'
22
27
  ],
23
28
  'libraries': [ '../lib/libasherah.a' ]
24
29
  }
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "asherah",
3
- "version": "1.3.11",
3
+ "version": "1.3.13",
4
4
  "description": "Asherah envelope encryption and key rotation library",
5
- "main": "dist/main.js",
5
+ "exports": {
6
+ "node-addons": "./dist/asherah.node"
7
+ },
6
8
  "repository": {
7
9
  "type": "git",
8
- "url": "https://github.com/jgowdy/asherah-cobhan.git"
10
+ "url": "https://github.com/godaddy/asherah-node.git"
9
11
  },
10
12
  "scripts": {
11
13
  "preinstall": "scripts/download-libraries.sh",
12
- "install": "node-gyp configure && node-gyp build && mkdir -p dist/ && cp build/Release/asherah.node dist/asherah.node && cp src/asherah.d.ts dist/asherah.d.ts && cp src/main.js dist/main.js",
14
+ "install": "scripts/build.sh",
13
15
  "test:mocha": "mocha",
14
16
  "test": "nyc npm run test:mocha",
15
17
  "posttest": "npm run lint",
@@ -21,8 +23,12 @@
21
23
  "files": [
22
24
  "binding.gyp",
23
25
  "src/asherah.cc",
24
- "dist/asherah.d.ts",
25
- "dist/main.js",
26
+ "src/hints.h",
27
+ "src/logging.h",
28
+ "src/logging.cc",
29
+ "src/cobhan_napi_interop.h",
30
+ "src/cobhan_napi_interop.cc",
31
+ "src/asherah.d.ts",
26
32
  "scripts/download-libraries.sh",
27
33
  "SHA256SUMS",
28
34
  "SHA256SUMS-darwin",
package/src/asherah.cc CHANGED
@@ -1,242 +1,13 @@
1
1
  #include "../lib/libasherah.h"
2
2
  #include <iostream>
3
3
  #define NODE_ADDON_API_DISABLE_DEPRECATED
4
+ #include "cobhan_napi_interop.h"
5
+ #include "hints.h"
6
+ #include "logging.h"
4
7
  #include <napi.h>
5
8
 
6
- #define unlikely(expr) __builtin_expect(!!(expr), 0)
7
- #define likely(expr) __builtin_expect(!!(expr), 1)
8
-
9
- const size_t cobhan_header_size_bytes = 64 / 8;
10
- const size_t est_encryption_overhead = 48;
11
- const size_t est_envelope_overhead = 185;
12
- const double base64_overhead = 1.34;
13
-
14
- size_t est_intermediate_key_overhead = 0;
15
- size_t safety_padding_bytes = 0;
16
9
  size_t max_stack_alloc_size = 2048;
17
-
18
10
  int32_t setup_state = 0;
19
- int32_t verbose_flag = 0;
20
-
21
- __attribute__((always_inline)) inline void debug_log(const char *function_name,
22
- std::string message) {
23
- if (unlikely(verbose_flag)) {
24
- std::cerr << "asherah-node: [DEBUG] " << function_name << ": " << message
25
- << std::endl
26
- << std::flush;
27
- }
28
- }
29
-
30
- __attribute__((always_inline)) inline void
31
- debug_log_alloca(const char *function_name, const char *variable_name,
32
- size_t length) {
33
- if (unlikely(verbose_flag)) {
34
- std::cerr << "asherah-node: [DEBUG] " << function_name
35
- << ": Calling alloca(" << length << ") (stack) for "
36
- << variable_name << std::endl
37
- << std::flush;
38
- }
39
- }
40
-
41
- __attribute__((always_inline)) inline void error_log(const char *function_name,
42
- std::string message) {
43
- if (unlikely(verbose_flag)) {
44
- std::cerr << "asherah-node: [ERROR] " << function_name << ": " << message
45
- << std::endl
46
- << std::flush;
47
- }
48
- }
49
-
50
- std::string napi_status_to_string(napi_status status) {
51
- switch (status) {
52
- case napi_ok:
53
- return "napi_ok";
54
- case napi_invalid_arg:
55
- return "napi_invalid_arg";
56
- case napi_object_expected:
57
- return "napi_object_expected";
58
- case napi_string_expected:
59
- return "napi_string_expected";
60
- case napi_name_expected:
61
- return "napi_name_expected";
62
- case napi_function_expected:
63
- return "napi_function_expected";
64
- case napi_number_expected:
65
- return "napi_number_expected";
66
- case napi_boolean_expected:
67
- return "napi_boolean_expected";
68
- case napi_array_expected:
69
- return "napi_array_expected";
70
- case napi_generic_failure:
71
- return "napi_generic_failure";
72
- case napi_pending_exception:
73
- return "napi_pending_exception";
74
- case napi_cancelled:
75
- return "napi_cancelled";
76
- case napi_escape_called_twice:
77
- return "napi_escape_called_twice";
78
- case napi_handle_scope_mismatch:
79
- return "napi_handle_scope_mismatch";
80
- case napi_callback_scope_mismatch:
81
- return "napi_callback_scope_mismatch";
82
- case napi_queue_full:
83
- return "napi_queue_full";
84
- case napi_closing:
85
- return "napi_closing";
86
- case napi_bigint_expected:
87
- return "napi_bigint_expected";
88
- case napi_date_expected:
89
- return "napi_date_expected";
90
- case napi_arraybuffer_expected:
91
- return "napi_arraybuffer_expected";
92
- case napi_detachable_arraybuffer_expected:
93
- return "napi_detachable_arraybuffer_expected";
94
- case napi_would_deadlock:
95
- return "napi_would_deadlock";
96
- default:
97
- return "Unknown napi_status";
98
- }
99
- }
100
-
101
- __attribute__((always_inline)) inline Napi::Value
102
- LogErrorAndThrow(Napi::Env &env, const char *function_name,
103
- std::string error_msg) {
104
- error_log(function_name, error_msg);
105
- Napi::Error::New(env, function_name + (": " + error_msg))
106
- .ThrowAsJavaScriptException();
107
- return env.Null();
108
- }
109
-
110
- __attribute__((always_inline)) inline size_t
111
- calculate_cobhan_buffer_size_bytes(size_t data_len_bytes) {
112
- return data_len_bytes + cobhan_header_size_bytes + safety_padding_bytes +
113
- 1; // Add one for possible NULL delimiter due to Node string functions
114
- }
115
-
116
- __attribute__((always_inline)) inline size_t
117
- estimate_asherah_output_size_bytes(size_t data_byte_len,
118
- size_t partition_byte_len) {
119
- // Add one rather than using std::ceil to round up
120
- double est_data_byte_len =
121
- (double(data_byte_len + est_encryption_overhead) * base64_overhead) + 1;
122
-
123
- size_t asherah_output_size_bytes =
124
- size_t(est_envelope_overhead + est_intermediate_key_overhead +
125
- partition_byte_len + est_data_byte_len + safety_padding_bytes);
126
- if (unlikely(verbose_flag)) {
127
- std::string log_msg =
128
- "estimate_asherah_output_size(" + std::to_string(data_byte_len) + ", " +
129
- std::to_string(partition_byte_len) +
130
- ") est_data_byte_len: " + std::to_string(est_data_byte_len) +
131
- " asherah_output_size_bytes: " +
132
- std::to_string(asherah_output_size_bytes);
133
- debug_log("estimate_asherah_output_size", log_msg);
134
- }
135
- return asherah_output_size_bytes;
136
- }
137
-
138
- __attribute__((always_inline)) inline void configure_cbuffer(char *buffer,
139
- size_t length) {
140
- *((int32_t *)buffer) = length;
141
- // Reserved for future use
142
- *((int32_t *)(buffer + sizeof(int32_t))) = 0;
143
- }
144
-
145
- __attribute__((always_inline)) inline std::unique_ptr<char[]>
146
- heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
147
- size_t cobhan_buffer_size_bytes =
148
- calculate_cobhan_buffer_size_bytes(size_bytes);
149
- if (unlikely(verbose_flag)) {
150
- std::string log_msg =
151
- "heap_allocate_cbuffer(" + std::to_string(size_bytes) +
152
- ") (heap) cobhan_buffer_size_bytes: " +
153
- std::to_string(cobhan_buffer_size_bytes) + " for " + variable_name;
154
- debug_log("allocate_cbuffer", log_msg);
155
- }
156
-
157
- char *cobhan_buffer = new (std::nothrow) char[cobhan_buffer_size_bytes];
158
- if (unlikely(cobhan_buffer == nullptr)) {
159
- std::string error_msg =
160
- "new[" + std::to_string(cobhan_buffer_size_bytes) + " returned null";
161
- error_log("allocate_cbuffer", error_msg);
162
- return nullptr;
163
- }
164
- std::unique_ptr<char[]> cobhan_buffer_unique_ptr(cobhan_buffer);
165
- configure_cbuffer(cobhan_buffer, size_bytes + safety_padding_bytes);
166
- return cobhan_buffer_unique_ptr;
167
- }
168
-
169
- __attribute__((always_inline)) inline Napi::Value
170
- cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
171
- napi_value output;
172
-
173
- // Using C function because it allows length delimited input
174
- napi_status status = napi_create_string_utf8(
175
- env, ((const char *)cobhan_buffer) + cobhan_header_size_bytes,
176
- *((int *)cobhan_buffer), &output);
177
-
178
- if (unlikely(status != napi_ok)) {
179
- return LogErrorAndThrow(env, "cbuffer_to_nstring",
180
- "napi_create_string_utf8 failed: " +
181
- napi_status_to_string(status));
182
- }
183
-
184
- return Napi::String(env, output);
185
- }
186
-
187
- __attribute__((always_inline)) inline size_t
188
- nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
189
- napi_status status;
190
- size_t utf8_length;
191
-
192
- status = napi_get_value_string_utf8(env, str, nullptr, 0, &utf8_length);
193
- if (unlikely(status != napi_ok)) {
194
- LogErrorAndThrow(env, "nstring_utf8_length",
195
- "napi_get_value_string_utf8 length check failed: " +
196
- napi_status_to_string(status));
197
- return (size_t)(-1);
198
- }
199
-
200
- return utf8_length;
201
- }
202
-
203
- __attribute__((always_inline)) inline char *
204
- copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
205
- size_t utf8_byte_length, char *cobhan_buffer,
206
- size_t *byte_length = nullptr) {
207
- napi_status status;
208
- size_t copied_bytes;
209
- status = napi_get_value_string_utf8(env, str,
210
- cobhan_buffer + cobhan_header_size_bytes,
211
- utf8_byte_length + 1, &copied_bytes);
212
- if (unlikely(status != napi_ok)) {
213
- LogErrorAndThrow(env, "copy_nstring_to_cbuffer",
214
- "Napi utf8 string conversion failure: " +
215
- napi_status_to_string(status));
216
- return nullptr;
217
- }
218
-
219
- if (unlikely(copied_bytes != utf8_byte_length)) {
220
- LogErrorAndThrow(env, "copy_nstring_to_cbuffer",
221
- "Did not copy expected number of bytes " +
222
- std::to_string(utf8_byte_length) + " copied " +
223
- std::to_string(copied_bytes));
224
- return nullptr;
225
- }
226
-
227
- configure_cbuffer(cobhan_buffer, copied_bytes);
228
-
229
- if (byte_length != nullptr)
230
- *byte_length = copied_bytes;
231
- return cobhan_buffer;
232
- }
233
-
234
- __attribute__((always_inline)) inline Napi::Buffer<unsigned char>
235
- cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
236
- return Napi::Buffer<unsigned char>::Copy(
237
- env, ((unsigned char *)cobhan_buffer) + cobhan_header_size_bytes,
238
- *((int *)cobhan_buffer));
239
- }
240
11
 
241
12
  void setup(const Napi::CallbackInfo &info) {
242
13
  Napi::Env env = info.Env();
@@ -246,12 +17,12 @@ void setup(const Napi::CallbackInfo &info) {
246
17
  }
247
18
 
248
19
  if (unlikely(setup_state == 1)) {
249
- LogErrorAndThrow(env, "setup", "setup called twice");
20
+ log_error_and_throw(env, "setup", "setup called twice");
250
21
  return;
251
22
  }
252
23
 
253
24
  if (unlikely(info.Length() < 1)) {
254
- LogErrorAndThrow(env, "setup", "Wrong number of arguments");
25
+ log_error_and_throw(env, "setup", "Wrong number of arguments");
255
26
  return;
256
27
  }
257
28
 
@@ -267,15 +38,14 @@ void setup(const Napi::CallbackInfo &info) {
267
38
  Napi::Function parse = json.Get("parse").As<Napi::Function>();
268
39
  config_json = parse.Call(json, {config}).As<Napi::Object>();
269
40
  } else {
270
- LogErrorAndThrow(env, "setup", "Wrong argument type");
41
+ log_error_and_throw(env, "setup", "Wrong argument type");
271
42
  return;
272
43
  }
273
44
 
274
45
  Napi::String product_id = config_json.Get("ProductID").As<Napi::String>();
275
46
  Napi::String service_name = config_json.Get("ServiceName").As<Napi::String>();
276
47
 
277
- est_intermediate_key_overhead =
278
- product_id.Utf8Value().length() + service_name.Utf8Value().length();
48
+ est_intermediate_key_overhead = product_id.Utf8Value().length() + service_name.Utf8Value().length();
279
49
 
280
50
  Napi::Value verbose = config_json.Get("Verbose");
281
51
  if (likely(verbose.IsBoolean())) {
@@ -290,7 +60,7 @@ void setup(const Napi::CallbackInfo &info) {
290
60
  size_t config_utf8_byte_length;
291
61
  config_utf8_byte_length = nstring_utf8_byte_length(env, config);
292
62
  if (unlikely(config_utf8_byte_length == (size_t)(-1))) {
293
- LogErrorAndThrow(env, "setup", "Failed to get config utf8 length");
63
+ log_error_and_throw(env, "setup", "Failed to get config utf8 length");
294
64
  return;
295
65
  }
296
66
 
@@ -301,8 +71,10 @@ void setup(const Napi::CallbackInfo &info) {
301
71
  // If the buffer is small enough, allocate it on the stack
302
72
  size_t config_cobhan_buffer_size_bytes =
303
73
  calculate_cobhan_buffer_size_bytes(config_utf8_byte_length);
304
- debug_log_alloca("setup", "config_cobhan_buffer", config_cobhan_buffer_size_bytes);
74
+ debug_log_alloca("setup", "config_cobhan_buffer",
75
+ config_cobhan_buffer_size_bytes);
305
76
  config_cobhan_buffer = (char *)alloca(config_cobhan_buffer_size_bytes);
77
+ configure_cbuffer(config_cobhan_buffer, config_utf8_byte_length);
306
78
  } else {
307
79
  // Otherwise, allocate it on the heap
308
80
  config_cobhan_buffer_unique_ptr =
@@ -310,7 +82,7 @@ void setup(const Napi::CallbackInfo &info) {
310
82
  config_cobhan_buffer = config_cobhan_buffer_unique_ptr.get();
311
83
  }
312
84
  if (unlikely(config_cobhan_buffer == nullptr)) {
313
- LogErrorAndThrow(env, "setup", "Failed to allocate config cobhan buffer");
85
+ log_error_and_throw(env, "setup", "Failed to allocate config cobhan buffer");
314
86
  return;
315
87
  }
316
88
 
@@ -320,7 +92,7 @@ void setup(const Napi::CallbackInfo &info) {
320
92
  copy_nstring_to_cbuffer(env, config, config_utf8_byte_length,
321
93
  config_cobhan_buffer, &config_copied_bytes);
322
94
  if (unlikely(config_cobhan_buffer == nullptr)) {
323
- LogErrorAndThrow(env, "setup", "Failed to copy config to cobhan buffer");
95
+ log_error_and_throw(env, "setup", "Failed to copy config to cobhan buffer");
324
96
  return;
325
97
  }
326
98
 
@@ -337,7 +109,7 @@ void setup(const Napi::CallbackInfo &info) {
337
109
 
338
110
  if (unlikely(result < 0)) {
339
111
  // TODO: Convert this to a proper error message
340
- LogErrorAndThrow(env, "setup", std::to_string(result));
112
+ log_error_and_throw(env, "setup", std::to_string(result));
341
113
  return;
342
114
  }
343
115
  setup_state = 1;
@@ -364,8 +136,7 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
364
136
  debug_log_alloca("encrypt_to_json", "output_cobhan_buffer",
365
137
  output_cobhan_buffer_size_bytes);
366
138
  output_cobhan_buffer = (char *)alloca(output_cobhan_buffer_size_bytes);
367
- configure_cbuffer(output_cobhan_buffer,
368
- asherah_output_size_bytes + safety_padding_bytes);
139
+ configure_cbuffer(output_cobhan_buffer, asherah_output_size_bytes);
369
140
  } else {
370
141
  // Otherwise, allocate it on the heap
371
142
  output_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
@@ -373,7 +144,7 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
373
144
  output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
374
145
  }
375
146
  if (unlikely(output_cobhan_buffer == nullptr)) {
376
- return LogErrorAndThrow(env, "encrypt_to_json",
147
+ return log_error_and_throw(env, "encrypt_to_json",
377
148
  "Failed to allocate cobhan output buffer");
378
149
  }
379
150
 
@@ -392,7 +163,7 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
392
163
 
393
164
  if (unlikely(result < 0)) {
394
165
  // TODO: Convert this to a proper error message
395
- return LogErrorAndThrow(env, "encrypt_to_json", std::to_string(result));
166
+ return log_error_and_throw(env, "encrypt_to_json", std::to_string(result));
396
167
  }
397
168
 
398
169
  Napi::Value output = cbuffer_to_nstring(env, output_cobhan_buffer);
@@ -407,15 +178,15 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
407
178
  }
408
179
 
409
180
  if (unlikely(setup_state == 0)) {
410
- return LogErrorAndThrow(env, "encrypt", "setup() not called");
181
+ return log_error_and_throw(env, "encrypt", "setup() not called");
411
182
  }
412
183
 
413
184
  if (unlikely(info.Length() < 2)) {
414
- return LogErrorAndThrow(env, "encrypt", "Wrong number of arguments");
185
+ return log_error_and_throw(env, "encrypt", "Wrong number of arguments");
415
186
  }
416
187
 
417
188
  if (unlikely(!info[0].IsString() || !info[1].IsBuffer())) {
418
- return LogErrorAndThrow(env, "encrypt", "Wrong argument types");
189
+ return log_error_and_throw(env, "encrypt", "Wrong argument types");
419
190
  }
420
191
 
421
192
  // Determine size
@@ -423,11 +194,11 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
423
194
  Napi::String partition_id = info[0].As<Napi::String>();
424
195
  partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
425
196
  if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
426
- return LogErrorAndThrow(env, "encrypt",
197
+ return log_error_and_throw(env, "encrypt",
427
198
  "Failed to get partition_id utf8 length");
428
199
  }
429
200
  if (unlikely(partition_utf8_byte_length == 0)) {
430
- return LogErrorAndThrow(env, "encrypt", "partition_id is empty");
201
+ return log_error_and_throw(env, "encrypt", "partition_id is empty");
431
202
  }
432
203
 
433
204
  // Allocate
@@ -437,8 +208,11 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
437
208
  // If the buffer is small enough, allocate it on the stack
438
209
  size_t partition_id_cobhan_buffer_size_bytes =
439
210
  calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
440
- debug_log_alloca("encrypt", "partition_id_cobhan_buffer", partition_id_cobhan_buffer_size_bytes);
441
- partition_id_cobhan_buffer = (char *)alloca(partition_id_cobhan_buffer_size_bytes);
211
+ debug_log_alloca("encrypt", "partition_id_cobhan_buffer",
212
+ partition_id_cobhan_buffer_size_bytes);
213
+ partition_id_cobhan_buffer =
214
+ (char *)alloca(partition_id_cobhan_buffer_size_bytes);
215
+ configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
442
216
  } else {
443
217
  // Otherwise, allocate it on the heap
444
218
  partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
@@ -446,7 +220,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
446
220
  partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
447
221
  }
448
222
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
449
- return LogErrorAndThrow(env, "encrypt",
223
+ return log_error_and_throw(env, "encrypt",
450
224
  "Failed to allocate partitionId cobhan buffer");
451
225
  }
452
226
 
@@ -456,7 +230,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
456
230
  env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
457
231
  &partition_copied_bytes);
458
232
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
459
- return LogErrorAndThrow(env, "encrypt",
233
+ return log_error_and_throw(env, "encrypt",
460
234
  "Failed to copy partitionId to cobhan buffer");
461
235
  }
462
236
 
@@ -465,7 +239,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
465
239
  info[1].As<Napi::Buffer<unsigned char>>();
466
240
  size_t input_byte_length = input_napi_buffer.ByteLength();
467
241
  if (unlikely(input_byte_length == 0)) {
468
- return LogErrorAndThrow(env, "encrypt", "input is empty");
242
+ return log_error_and_throw(env, "encrypt", "input is empty");
469
243
  }
470
244
 
471
245
  // Allocate
@@ -478,6 +252,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
478
252
  debug_log_alloca("encrypt", "input_cobhan_buffer",
479
253
  input_cobhan_buffer_size_bytes);
480
254
  input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
255
+ configure_cbuffer(input_cobhan_buffer, input_byte_length);
481
256
  } else {
482
257
  // Otherwise, allocate it on the heap
483
258
  input_buffer_unique_ptr =
@@ -485,14 +260,17 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
485
260
  input_cobhan_buffer = input_buffer_unique_ptr.get();
486
261
  }
487
262
  if (unlikely(input_cobhan_buffer == nullptr)) {
488
- return LogErrorAndThrow(
263
+ return log_error_and_throw(
489
264
  env, "encrypt", "Failed to allocate cobhan buffer for input buffer");
490
265
  }
491
266
 
492
267
  // Copy
493
- memcpy(input_cobhan_buffer + cobhan_header_size_bytes,
494
- input_napi_buffer.Data(), input_byte_length);
495
- configure_cbuffer(input_cobhan_buffer, input_byte_length);
268
+ input_cobhan_buffer =
269
+ copy_nbuffer_to_cbuffer(env, input_napi_buffer, input_cobhan_buffer);
270
+ if (unlikely(input_cobhan_buffer == nullptr)) {
271
+ return log_error_and_throw(env, "encrypt",
272
+ "Failed to copy input buffer to cobhan buffer");
273
+ }
496
274
 
497
275
  return encrypt_to_json(env, partition_copied_bytes, input_byte_length,
498
276
  partition_id_cobhan_buffer, input_cobhan_buffer);
@@ -506,15 +284,15 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
506
284
  }
507
285
 
508
286
  if (unlikely(setup_state == 0)) {
509
- return LogErrorAndThrow(env, "encrypt_string", "setup() not called");
287
+ return log_error_and_throw(env, "encrypt_string", "setup() not called");
510
288
  }
511
289
 
512
290
  if (unlikely(info.Length() < 2)) {
513
- return LogErrorAndThrow(env, "encrypt_string", "Wrong number of arguments");
291
+ return log_error_and_throw(env, "encrypt_string", "Wrong number of arguments");
514
292
  }
515
293
 
516
294
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
517
- return LogErrorAndThrow(env, "encrypt_string", "Wrong argument types");
295
+ return log_error_and_throw(env, "encrypt_string", "Wrong argument types");
518
296
  }
519
297
 
520
298
  // Determine size
@@ -522,11 +300,11 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
522
300
  Napi::String partition_id = info[0].As<Napi::String>();
523
301
  partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
524
302
  if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
525
- return LogErrorAndThrow(env, "encrypt_string",
303
+ return log_error_and_throw(env, "encrypt_string",
526
304
  "Failed to get partition_id utf8 length");
527
305
  }
528
306
  if (unlikely(partition_utf8_byte_length == 0)) {
529
- return LogErrorAndThrow(env, "encrypt_string", "partition_id is empty");
307
+ return log_error_and_throw(env, "encrypt_string", "partition_id is empty");
530
308
  }
531
309
 
532
310
  // Allocate
@@ -538,7 +316,9 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
538
316
  calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
539
317
  debug_log_alloca("encrypt_string", "partition_id_cobhan_buffer",
540
318
  partition_id_cobhan_buffer_size_bytes);
541
- partition_id_cobhan_buffer = (char *)alloca(partition_id_cobhan_buffer_size_bytes);
319
+ partition_id_cobhan_buffer =
320
+ (char *)alloca(partition_id_cobhan_buffer_size_bytes);
321
+ configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
542
322
  } else {
543
323
  // Otherwise, allocate it on the heap
544
324
  partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
@@ -546,7 +326,7 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
546
326
  partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
547
327
  }
548
328
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
549
- return LogErrorAndThrow(env, "encrypt_string",
329
+ return log_error_and_throw(env, "encrypt_string",
550
330
  "Failed to allocate partitionId cobhan buffer");
551
331
  }
552
332
 
@@ -556,7 +336,7 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
556
336
  env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
557
337
  &partition_copied_bytes);
558
338
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
559
- return LogErrorAndThrow(env, "encrypt_string",
339
+ return log_error_and_throw(env, "encrypt_string",
560
340
  "Failed to copy partitionId to cobhan buffer");
561
341
  }
562
342
 
@@ -565,11 +345,11 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
565
345
  Napi::String input = info[1].As<Napi::String>();
566
346
  input_utf8_byte_length = nstring_utf8_byte_length(env, input);
567
347
  if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
568
- return LogErrorAndThrow(env, "encrypt_string",
348
+ return log_error_and_throw(env, "encrypt_string",
569
349
  "Failed to get input utf8 length");
570
350
  }
571
351
  if (unlikely(input_utf8_byte_length == 0)) {
572
- return LogErrorAndThrow(env, "encrypt_string", "input is empty");
352
+ return log_error_and_throw(env, "encrypt_string", "input is empty");
573
353
  }
574
354
 
575
355
  // Allocate
@@ -579,8 +359,10 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
579
359
  // If the buffer is small enough, allocate it on the stack
580
360
  size_t input_cobhan_buffer_size_bytes =
581
361
  calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
582
- debug_log_alloca("encrypt_string", "input_cobhan_buffer", input_cobhan_buffer_size_bytes);
362
+ debug_log_alloca("encrypt_string", "input_cobhan_buffer",
363
+ input_cobhan_buffer_size_bytes);
583
364
  input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
365
+ configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
584
366
  } else {
585
367
  // Otherwise, allocate it on the heap
586
368
  input_cobhan_buffer_unique_ptr =
@@ -588,7 +370,7 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
588
370
  input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
589
371
  }
590
372
  if (unlikely(input_cobhan_buffer == nullptr)) {
591
- return LogErrorAndThrow(env, "encrypt_string",
373
+ return log_error_and_throw(env, "encrypt_string",
592
374
  "Failed to allocate input cobhan buffer");
593
375
  }
594
376
 
@@ -598,7 +380,7 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
598
380
  copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
599
381
  input_cobhan_buffer, &input_copied_bytes);
600
382
  if (unlikely(input_cobhan_buffer == nullptr)) {
601
- return LogErrorAndThrow(env, "encrypt_string",
383
+ return log_error_and_throw(env, "encrypt_string",
602
384
  "Failed to copy input to cobhan buffer");
603
385
  }
604
386
 
@@ -614,15 +396,15 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
614
396
  }
615
397
 
616
398
  if (unlikely(setup_state == 0)) {
617
- return LogErrorAndThrow(env, "decrypt", "setup() not called");
399
+ return log_error_and_throw(env, "decrypt", "setup() not called");
618
400
  }
619
401
 
620
402
  if (unlikely(info.Length() < 2)) {
621
- return LogErrorAndThrow(env, "decrypt", "Wrong number of arguments");
403
+ return log_error_and_throw(env, "decrypt", "Wrong number of arguments");
622
404
  }
623
405
 
624
406
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
625
- return LogErrorAndThrow(env, "decrypt", "Wrong argument types");
407
+ return log_error_and_throw(env, "decrypt", "Wrong argument types");
626
408
  }
627
409
 
628
410
  // Determine size
@@ -630,11 +412,11 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
630
412
  Napi::String partition_id = info[0].As<Napi::String>();
631
413
  partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
632
414
  if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
633
- return LogErrorAndThrow(env, "decrypt",
415
+ return log_error_and_throw(env, "decrypt",
634
416
  "Failed to get partition_id utf8 length");
635
417
  }
636
418
  if (unlikely(partition_utf8_byte_length == 0)) {
637
- return LogErrorAndThrow(env, "decrypt", "partition_id is empty");
419
+ return log_error_and_throw(env, "decrypt", "partition_id is empty");
638
420
  }
639
421
 
640
422
  // Allocate
@@ -648,6 +430,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
648
430
  partition_id_cobhan_buffer_size_bytes);
649
431
  partition_id_cobhan_buffer =
650
432
  (char *)alloca(partition_id_cobhan_buffer_size_bytes);
433
+ configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
651
434
  } else {
652
435
  // Otherwise, allocate it on the heap
653
436
  partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
@@ -655,7 +438,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
655
438
  partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
656
439
  }
657
440
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
658
- return LogErrorAndThrow(env, "decrypt",
441
+ return log_error_and_throw(env, "decrypt",
659
442
  "Failed to allocate partition_id cobhan buffer");
660
443
  }
661
444
 
@@ -664,7 +447,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
664
447
  env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
665
448
  &partition_copied_bytes);
666
449
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
667
- return LogErrorAndThrow(env, "decrypt",
450
+ return log_error_and_throw(env, "decrypt",
668
451
  "Failed to copy partition_id to cobhan buffer");
669
452
  }
670
453
 
@@ -673,10 +456,10 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
673
456
  Napi::String input = info[1].As<Napi::String>();
674
457
  input_utf8_byte_length = nstring_utf8_byte_length(env, input);
675
458
  if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
676
- return LogErrorAndThrow(env, "decrypt", "Failed to get input utf8 length");
459
+ return log_error_and_throw(env, "decrypt", "Failed to get input utf8 length");
677
460
  }
678
461
  if (unlikely(input_utf8_byte_length == 0)) {
679
- return LogErrorAndThrow(env, "decrypt", "input is empty");
462
+ return log_error_and_throw(env, "decrypt", "input is empty");
680
463
  }
681
464
 
682
465
  if (unlikely(verbose_flag)) {
@@ -694,6 +477,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
694
477
  debug_log_alloca("decrypt", "input_cobhan_buffer",
695
478
  input_cobhan_buffer_size_bytes);
696
479
  input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
480
+ configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
697
481
  } else {
698
482
  // Otherwise, allocate it on the heap
699
483
  input_cobhan_buffer_unique_ptr =
@@ -701,7 +485,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
701
485
  input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
702
486
  }
703
487
  if (unlikely(input_cobhan_buffer == nullptr)) {
704
- return LogErrorAndThrow(env, "decrypt",
488
+ return log_error_and_throw(env, "decrypt",
705
489
  "Failed to allocate input cobhan buffer");
706
490
  }
707
491
 
@@ -711,7 +495,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
711
495
  copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
712
496
  input_cobhan_buffer, &input_copied_bytes);
713
497
  if (unlikely(input_cobhan_buffer == nullptr)) {
714
- return LogErrorAndThrow(env, "decrypt",
498
+ return log_error_and_throw(env, "decrypt",
715
499
  "Failed to copy input to cobhan buffer");
716
500
  }
717
501
 
@@ -732,7 +516,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
732
516
  output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
733
517
  }
734
518
  if (unlikely(output_cobhan_buffer == nullptr)) {
735
- return LogErrorAndThrow(env, "decrypt",
519
+ return log_error_and_throw(env, "decrypt",
736
520
  "Failed to allocate cobhan output buffer");
737
521
  }
738
522
 
@@ -751,7 +535,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
751
535
 
752
536
  if (unlikely(result < 0)) {
753
537
  // TODO: Convert this to a proper error message
754
- return LogErrorAndThrow(env, "decrypt", std::to_string(result));
538
+ return log_error_and_throw(env, "decrypt", std::to_string(result));
755
539
  }
756
540
 
757
541
  return cbuffer_to_nbuffer(env, output_cobhan_buffer);
@@ -765,15 +549,15 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
765
549
  }
766
550
 
767
551
  if (unlikely(setup_state == 0)) {
768
- return LogErrorAndThrow(env, "decrypt_string", "setup() not called");
552
+ return log_error_and_throw(env, "decrypt_string", "setup() not called");
769
553
  }
770
554
 
771
555
  if (unlikely(info.Length() < 2)) {
772
- return LogErrorAndThrow(env, "decrypt_string", "Wrong number of arguments");
556
+ return log_error_and_throw(env, "decrypt_string", "Wrong number of arguments");
773
557
  }
774
558
 
775
559
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
776
- return LogErrorAndThrow(env, "decrypt_string", "Wrong argument types");
560
+ return log_error_and_throw(env, "decrypt_string", "Wrong argument types");
777
561
  }
778
562
 
779
563
  // Determine size
@@ -781,11 +565,11 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
781
565
  Napi::String partition_id = info[0].As<Napi::String>();
782
566
  partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
783
567
  if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
784
- return LogErrorAndThrow(env, "decrypt_string",
568
+ return log_error_and_throw(env, "decrypt_string",
785
569
  "Failed to get partition_id utf8 length");
786
570
  }
787
571
  if (unlikely(partition_utf8_byte_length == 0)) {
788
- return LogErrorAndThrow(env, "decrypt_string", "partition_id is empty");
572
+ return log_error_and_throw(env, "decrypt_string", "partition_id is empty");
789
573
  }
790
574
 
791
575
  // Allocate
@@ -799,6 +583,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
799
583
  partition_id_cobhan_buffer_size_bytes);
800
584
  partition_id_cobhan_buffer =
801
585
  (char *)alloca(partition_id_cobhan_buffer_size_bytes);
586
+ configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
802
587
  } else {
803
588
  // Otherwise, allocate it on the heap
804
589
  partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
@@ -806,7 +591,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
806
591
  partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
807
592
  }
808
593
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
809
- return LogErrorAndThrow(env, "decrypt_string",
594
+ return log_error_and_throw(env, "decrypt_string",
810
595
  "Failed to allocate partitionId cobhan buffer");
811
596
  }
812
597
 
@@ -816,7 +601,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
816
601
  env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
817
602
  &partition_copied_bytes);
818
603
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
819
- return LogErrorAndThrow(env, "decrypt_string",
604
+ return log_error_and_throw(env, "decrypt_string",
820
605
  "Failed to copy partitionId to cobhan buffer");
821
606
  }
822
607
 
@@ -825,11 +610,11 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
825
610
  Napi::String input = info[1].As<Napi::String>();
826
611
  input_utf8_byte_length = nstring_utf8_byte_length(env, input);
827
612
  if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
828
- return LogErrorAndThrow(env, "decrypt_string",
613
+ return log_error_and_throw(env, "decrypt_string",
829
614
  "Failed to get input utf8 length");
830
615
  }
831
616
  if (unlikely(input_utf8_byte_length == 0)) {
832
- return LogErrorAndThrow(env, "decrypt_string", "input is empty");
617
+ return log_error_and_throw(env, "decrypt_string", "input is empty");
833
618
  }
834
619
 
835
620
  // Allocate
@@ -842,6 +627,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
842
627
  debug_log_alloca("decrypt_string", "input_cobhan_buffer",
843
628
  input_cobhan_buffer_size_bytes);
844
629
  input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
630
+ configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
845
631
  } else {
846
632
  // Otherwise, allocate it on the heap
847
633
  input_cobhan_buffer_unique_ptr =
@@ -849,7 +635,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
849
635
  input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
850
636
  }
851
637
  if (unlikely(input_cobhan_buffer == nullptr)) {
852
- return LogErrorAndThrow(env, "decrypt_string",
638
+ return log_error_and_throw(env, "decrypt_string",
853
639
  "Failed to allocate input cobhan buffer");
854
640
  }
855
641
 
@@ -859,7 +645,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
859
645
  copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
860
646
  input_cobhan_buffer, &input_copied_bytes);
861
647
  if (unlikely(input_cobhan_buffer == nullptr)) {
862
- return LogErrorAndThrow(env, "decrypt_string",
648
+ return log_error_and_throw(env, "decrypt_string",
863
649
  "Failed to copy input to cobhan buffer");
864
650
  }
865
651
 
@@ -880,7 +666,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
880
666
  output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
881
667
  }
882
668
  if (unlikely(output_cobhan_buffer == nullptr)) {
883
- return LogErrorAndThrow(env, "decrypt_string",
669
+ return log_error_and_throw(env, "decrypt_string",
884
670
  "Failed to allocate cobhan output buffer");
885
671
  }
886
672
 
@@ -899,7 +685,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
899
685
 
900
686
  if (unlikely(result < 0)) {
901
687
  // TODO: Convert this to a proper error message
902
- return LogErrorAndThrow(env, "decrypt_string", std::to_string(result));
688
+ return log_error_and_throw(env, "decrypt_string", std::to_string(result));
903
689
  }
904
690
 
905
691
  Napi::Value output = cbuffer_to_nstring(env, output_cobhan_buffer);
@@ -933,7 +719,7 @@ void set_max_stack_alloc_item_size(const Napi::CallbackInfo &info) {
933
719
  }
934
720
 
935
721
  if (unlikely(info.Length() < 1)) {
936
- LogErrorAndThrow(env, "set_max_stack_alloc_item_size",
722
+ log_error_and_throw(env, "set_max_stack_alloc_item_size",
937
723
  "Wrong number of arguments");
938
724
  return;
939
725
  }
@@ -951,7 +737,7 @@ void set_safety_padding_overhead(const Napi::CallbackInfo &info) {
951
737
  }
952
738
 
953
739
  if (unlikely(info.Length() < 1)) {
954
- LogErrorAndThrow(env, "set_safety_padding_overhead",
740
+ log_error_and_throw(env, "set_safety_padding_overhead",
955
741
  "Wrong number of arguments");
956
742
  return;
957
743
  }
@@ -0,0 +1,3 @@
1
+ #include <stddef.h>
2
+ size_t est_intermediate_key_overhead = 0;
3
+ size_t safety_padding_bytes = 0;
@@ -0,0 +1,240 @@
1
+ #ifndef COBHAN_NAPI_INTEROP_H
2
+ #define COBHAN_NAPI_INTEROP_H
3
+ #include <string>
4
+ #define NODE_ADDON_API_DISABLE_DEPRECATED
5
+ #include <napi.h>
6
+ #include "logging.h"
7
+ #include "hints.h"
8
+
9
+ extern size_t est_intermediate_key_overhead;
10
+ extern size_t safety_padding_bytes;
11
+
12
+ const size_t est_encryption_overhead = 48;
13
+ const size_t est_envelope_overhead = 185;
14
+ const double base64_overhead = 1.34;
15
+
16
+ const size_t cobhan_header_size_bytes = 64 / 8;
17
+
18
+ std::string napi_status_to_string(napi_status status) {
19
+ switch (status) {
20
+ case napi_ok:
21
+ return "napi_ok";
22
+ case napi_invalid_arg:
23
+ return "napi_invalid_arg";
24
+ case napi_object_expected:
25
+ return "napi_object_expected";
26
+ case napi_string_expected:
27
+ return "napi_string_expected";
28
+ case napi_name_expected:
29
+ return "napi_name_expected";
30
+ case napi_function_expected:
31
+ return "napi_function_expected";
32
+ case napi_number_expected:
33
+ return "napi_number_expected";
34
+ case napi_boolean_expected:
35
+ return "napi_boolean_expected";
36
+ case napi_array_expected:
37
+ return "napi_array_expected";
38
+ case napi_generic_failure:
39
+ return "napi_generic_failure";
40
+ case napi_pending_exception:
41
+ return "napi_pending_exception";
42
+ case napi_cancelled:
43
+ return "napi_cancelled";
44
+ case napi_escape_called_twice:
45
+ return "napi_escape_called_twice";
46
+ case napi_handle_scope_mismatch:
47
+ return "napi_handle_scope_mismatch";
48
+ case napi_callback_scope_mismatch:
49
+ return "napi_callback_scope_mismatch";
50
+ case napi_queue_full:
51
+ return "napi_queue_full";
52
+ case napi_closing:
53
+ return "napi_closing";
54
+ case napi_bigint_expected:
55
+ return "napi_bigint_expected";
56
+ case napi_date_expected:
57
+ return "napi_date_expected";
58
+ case napi_arraybuffer_expected:
59
+ return "napi_arraybuffer_expected";
60
+ case napi_detachable_arraybuffer_expected:
61
+ return "napi_detachable_arraybuffer_expected";
62
+ case napi_would_deadlock:
63
+ return "napi_would_deadlock";
64
+ default:
65
+ return "Unknown napi_status";
66
+ }
67
+ }
68
+
69
+ __attribute__((always_inline)) inline size_t
70
+ cbuffer_byte_length(char *cobhan_buffer) {
71
+ return *((int *)cobhan_buffer);
72
+ }
73
+
74
+ __attribute__((always_inline)) inline Napi::Value
75
+ log_error_and_throw(Napi::Env &env, const char *function_name,
76
+ std::string error_msg) {
77
+ error_log(function_name, error_msg);
78
+ Napi::Error::New(env, function_name + (": " + error_msg))
79
+ .ThrowAsJavaScriptException();
80
+ return env.Null();
81
+ }
82
+
83
+ __attribute__((always_inline)) inline size_t
84
+ calculate_cobhan_buffer_size_bytes(size_t data_len_bytes) {
85
+ return data_len_bytes + cobhan_header_size_bytes + safety_padding_bytes +
86
+ 1; // Add one for possible NULL delimiter due to Node string functions
87
+ }
88
+
89
+ __attribute__((always_inline)) inline size_t
90
+ estimate_asherah_output_size_bytes(size_t data_byte_len,
91
+ size_t partition_byte_len) {
92
+ // Add one rather than using std::ceil to round up
93
+ double est_data_byte_len =
94
+ (double(data_byte_len + est_encryption_overhead) * base64_overhead) + 1;
95
+
96
+ size_t asherah_output_size_bytes =
97
+ size_t(est_envelope_overhead + est_intermediate_key_overhead +
98
+ partition_byte_len + est_data_byte_len + safety_padding_bytes);
99
+ if (unlikely(verbose_flag)) {
100
+ std::string log_msg =
101
+ "estimate_asherah_output_size(" + std::to_string(data_byte_len) + ", " +
102
+ std::to_string(partition_byte_len) +
103
+ ") est_data_byte_len: " + std::to_string(est_data_byte_len) +
104
+ " asherah_output_size_bytes: " +
105
+ std::to_string(asherah_output_size_bytes);
106
+ debug_log("estimate_asherah_output_size", log_msg);
107
+ }
108
+ return asherah_output_size_bytes;
109
+ }
110
+
111
+ __attribute__((always_inline)) inline void configure_cbuffer(char *buffer,
112
+ size_t length) {
113
+ *((int32_t *)buffer) = length;
114
+ // Reserved for future use
115
+ *((int32_t *)(buffer + sizeof(int32_t))) = 0;
116
+ }
117
+
118
+ __attribute__((always_inline)) inline std::unique_ptr<char[]>
119
+ heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
120
+ size_t cobhan_buffer_size_bytes =
121
+ calculate_cobhan_buffer_size_bytes(size_bytes);
122
+ if (unlikely(verbose_flag)) {
123
+ std::string log_msg =
124
+ "heap_allocate_cbuffer(" + std::to_string(size_bytes) +
125
+ ") (heap) cobhan_buffer_size_bytes: " +
126
+ std::to_string(cobhan_buffer_size_bytes) + " for " + variable_name;
127
+ debug_log("allocate_cbuffer", log_msg);
128
+ }
129
+
130
+ char *cobhan_buffer = new (std::nothrow) char[cobhan_buffer_size_bytes];
131
+ if (unlikely(cobhan_buffer == nullptr)) {
132
+ std::string error_msg =
133
+ "new[" + std::to_string(cobhan_buffer_size_bytes) + " returned null";
134
+ error_log("allocate_cbuffer", error_msg);
135
+ return nullptr;
136
+ }
137
+ std::unique_ptr<char[]> cobhan_buffer_unique_ptr(cobhan_buffer);
138
+ configure_cbuffer(cobhan_buffer, size_bytes + safety_padding_bytes);
139
+ return cobhan_buffer_unique_ptr;
140
+ }
141
+
142
+ __attribute__((always_inline)) inline Napi::Value
143
+ cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
144
+ napi_value output;
145
+
146
+ // Using C function because it allows length delimited input
147
+ napi_status status = napi_create_string_utf8(
148
+ env, ((const char *)cobhan_buffer) + cobhan_header_size_bytes,
149
+ cbuffer_byte_length(cobhan_buffer), &output);
150
+
151
+ if (unlikely(status != napi_ok)) {
152
+ return log_error_and_throw(env, "cbuffer_to_nstring",
153
+ "napi_create_string_utf8 failed: " +
154
+ napi_status_to_string(status));
155
+ }
156
+
157
+ return Napi::String(env, output);
158
+ }
159
+
160
+ __attribute__((always_inline)) inline size_t
161
+ nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
162
+ napi_status status;
163
+ size_t utf8_length;
164
+
165
+ status = napi_get_value_string_utf8(env, str, nullptr, 0, &utf8_length);
166
+ if (unlikely(status != napi_ok)) {
167
+ log_error_and_throw(env, "nstring_utf8_length",
168
+ "napi_get_value_string_utf8 length check failed: " +
169
+ napi_status_to_string(status));
170
+ return (size_t)(-1);
171
+ }
172
+
173
+ return utf8_length;
174
+ }
175
+
176
+ __attribute__((always_inline)) inline char *
177
+ copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
178
+ size_t str_utf8_byte_length, char *cobhan_buffer,
179
+ size_t *byte_length = nullptr) {
180
+
181
+ size_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
182
+ if (cobhan_buffer_size_bytes < str_utf8_byte_length) {
183
+ log_error_and_throw(env, "copy_nstring_to_cbuffer",
184
+ "String too large for cobhan buffer");
185
+ return nullptr;
186
+ }
187
+
188
+ napi_status status;
189
+ size_t copied_bytes;
190
+ // NOTE: This implementation relies on the additional byte that is reserved
191
+ // upon allocation for a NULL delimiter as methods like
192
+ // napi_get_value_string_utf8 append a NULL delimiter
193
+ status = napi_get_value_string_utf8(
194
+ env, str, cobhan_buffer + cobhan_header_size_bytes,
195
+ str_utf8_byte_length + 1, &copied_bytes);
196
+ if (unlikely(status != napi_ok)) {
197
+ log_error_and_throw(env, "copy_nstring_to_cbuffer",
198
+ "Napi utf8 string conversion failure: " +
199
+ napi_status_to_string(status));
200
+ return nullptr;
201
+ }
202
+
203
+ if (unlikely(copied_bytes != str_utf8_byte_length)) {
204
+ log_error_and_throw(env, "copy_nstring_to_cbuffer",
205
+ "Did not copy expected number of bytes " +
206
+ std::to_string(str_utf8_byte_length) + " copied " +
207
+ std::to_string(copied_bytes));
208
+ return nullptr;
209
+ }
210
+
211
+ configure_cbuffer(cobhan_buffer, copied_bytes);
212
+
213
+ if (byte_length != nullptr)
214
+ *byte_length = copied_bytes;
215
+ return cobhan_buffer;
216
+ }
217
+
218
+ __attribute__((always_inline)) inline char *
219
+ copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
220
+ char *cobhan_buffer) {
221
+ size_t nbuffer_byte_length = nbuffer.ByteLength();
222
+ if (cbuffer_byte_length(cobhan_buffer) < nbuffer_byte_length) {
223
+ log_error_and_throw(env, "copy_nbuffer_to_cbuffer",
224
+ "Buffer too large for cobhan buffer");
225
+ return nullptr;
226
+ }
227
+ memcpy(cobhan_buffer + cobhan_header_size_bytes, nbuffer.Data(),
228
+ nbuffer_byte_length);
229
+ configure_cbuffer(cobhan_buffer, nbuffer_byte_length);
230
+ return cobhan_buffer;
231
+ }
232
+
233
+ __attribute__((always_inline)) inline Napi::Buffer<unsigned char>
234
+ cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
235
+ return Napi::Buffer<unsigned char>::Copy(
236
+ env, ((unsigned char *)cobhan_buffer) + cobhan_header_size_bytes,
237
+ cbuffer_byte_length(cobhan_buffer));
238
+ }
239
+
240
+ #endif
package/src/hints.h ADDED
@@ -0,0 +1,7 @@
1
+ #ifndef HINTS_H
2
+ #define HINTS_H
3
+
4
+ #define unlikely(expr) __builtin_expect(!!(expr), 0)
5
+ #define likely(expr) __builtin_expect(!!(expr), 1)
6
+
7
+ #endif
package/src/logging.cc ADDED
@@ -0,0 +1,2 @@
1
+ #include <cstdint>
2
+ int32_t verbose_flag = 0;
package/src/logging.h ADDED
@@ -0,0 +1,38 @@
1
+ #ifndef LOGGING_H
2
+ #define LOGGING_H
3
+ #include <cstdint>
4
+ #include <string>
5
+ #include "hints.h"
6
+
7
+ extern int32_t verbose_flag;
8
+
9
+ __attribute__((always_inline)) inline void debug_log(const char *function_name,
10
+ std::string message) {
11
+ if (unlikely(verbose_flag)) {
12
+ std::cerr << "asherah-node: [DEBUG] " << function_name << ": " << message
13
+ << std::endl
14
+ << std::flush;
15
+ }
16
+ }
17
+
18
+ __attribute__((always_inline)) inline void
19
+ debug_log_alloca(const char *function_name, const char *variable_name,
20
+ size_t length) {
21
+ if (unlikely(verbose_flag)) {
22
+ std::cerr << "asherah-node: [DEBUG] " << function_name
23
+ << ": Calling alloca(" << length << ") (stack) for "
24
+ << variable_name << std::endl
25
+ << std::flush;
26
+ }
27
+ }
28
+
29
+ __attribute__((always_inline)) inline void error_log(const char *function_name,
30
+ std::string message) {
31
+ if (unlikely(verbose_flag)) {
32
+ std::cerr << "asherah-node: [ERROR] " << function_name << ": " << message
33
+ << std::endl
34
+ << std::flush;
35
+ }
36
+ }
37
+
38
+ #endif
package/dist/main.js DELETED
File without changes
File without changes