asherah 1.3.12 → 1.3.14

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,17 +1,17 @@
1
1
  {
2
2
  "name": "asherah",
3
- "version": "1.3.12",
3
+ "version": "1.3.14",
4
4
  "description": "Asherah envelope encryption and key rotation library",
5
5
  "exports": {
6
6
  "node-addons": "./dist/asherah.node"
7
7
  },
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/jgowdy/asherah-cobhan.git"
10
+ "url": "https://github.com/godaddy/asherah-node.git"
11
11
  },
12
12
  "scripts": {
13
13
  "preinstall": "scripts/download-libraries.sh",
14
- "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",
14
+ "install": "scripts/build.sh",
15
15
  "test:mocha": "mocha",
16
16
  "test": "nyc npm run test:mocha",
17
17
  "posttest": "npm run lint",
@@ -23,6 +23,11 @@
23
23
  "files": [
24
24
  "binding.gyp",
25
25
  "src/asherah.cc",
26
+ "src/hints.h",
27
+ "src/logging.h",
28
+ "src/logging.cc",
29
+ "src/cobhan_napi_interop.h",
30
+ "src/cobhan_napi_interop.cc",
26
31
  "src/asherah.d.ts",
27
32
  "scripts/download-libraries.sh",
28
33
  "SHA256SUMS",
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,7 +38,7 @@ 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
 
@@ -290,7 +61,7 @@ void setup(const Napi::CallbackInfo &info) {
290
61
  size_t config_utf8_byte_length;
291
62
  config_utf8_byte_length = nstring_utf8_byte_length(env, config);
292
63
  if (unlikely(config_utf8_byte_length == (size_t)(-1))) {
293
- LogErrorAndThrow(env, "setup", "Failed to get config utf8 length");
64
+ log_error_and_throw(env, "setup", "Failed to get config utf8 length");
294
65
  return;
295
66
  }
296
67
 
@@ -301,8 +72,10 @@ void setup(const Napi::CallbackInfo &info) {
301
72
  // If the buffer is small enough, allocate it on the stack
302
73
  size_t config_cobhan_buffer_size_bytes =
303
74
  calculate_cobhan_buffer_size_bytes(config_utf8_byte_length);
304
- debug_log_alloca("setup", "config_cobhan_buffer", config_cobhan_buffer_size_bytes);
75
+ debug_log_alloca("setup", "config_cobhan_buffer",
76
+ config_cobhan_buffer_size_bytes);
305
77
  config_cobhan_buffer = (char *)alloca(config_cobhan_buffer_size_bytes);
78
+ configure_cbuffer(config_cobhan_buffer, config_utf8_byte_length);
306
79
  } else {
307
80
  // Otherwise, allocate it on the heap
308
81
  config_cobhan_buffer_unique_ptr =
@@ -310,7 +83,8 @@ void setup(const Napi::CallbackInfo &info) {
310
83
  config_cobhan_buffer = config_cobhan_buffer_unique_ptr.get();
311
84
  }
312
85
  if (unlikely(config_cobhan_buffer == nullptr)) {
313
- LogErrorAndThrow(env, "setup", "Failed to allocate config cobhan buffer");
86
+ log_error_and_throw(env, "setup",
87
+ "Failed to allocate config cobhan buffer");
314
88
  return;
315
89
  }
316
90
 
@@ -320,7 +94,7 @@ void setup(const Napi::CallbackInfo &info) {
320
94
  copy_nstring_to_cbuffer(env, config, config_utf8_byte_length,
321
95
  config_cobhan_buffer, &config_copied_bytes);
322
96
  if (unlikely(config_cobhan_buffer == nullptr)) {
323
- LogErrorAndThrow(env, "setup", "Failed to copy config to cobhan buffer");
97
+ log_error_and_throw(env, "setup", "Failed to copy config to cobhan buffer");
324
98
  return;
325
99
  }
326
100
 
@@ -337,7 +111,7 @@ void setup(const Napi::CallbackInfo &info) {
337
111
 
338
112
  if (unlikely(result < 0)) {
339
113
  // TODO: Convert this to a proper error message
340
- LogErrorAndThrow(env, "setup", std::to_string(result));
114
+ log_error_and_throw(env, "setup", std::to_string(result));
341
115
  return;
342
116
  }
343
117
  setup_state = 1;
@@ -364,8 +138,7 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
364
138
  debug_log_alloca("encrypt_to_json", "output_cobhan_buffer",
365
139
  output_cobhan_buffer_size_bytes);
366
140
  output_cobhan_buffer = (char *)alloca(output_cobhan_buffer_size_bytes);
367
- configure_cbuffer(output_cobhan_buffer,
368
- asherah_output_size_bytes + safety_padding_bytes);
141
+ configure_cbuffer(output_cobhan_buffer, asherah_output_size_bytes);
369
142
  } else {
370
143
  // Otherwise, allocate it on the heap
371
144
  output_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
@@ -373,8 +146,8 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
373
146
  output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
374
147
  }
375
148
  if (unlikely(output_cobhan_buffer == nullptr)) {
376
- return LogErrorAndThrow(env, "encrypt_to_json",
377
- "Failed to allocate cobhan output buffer");
149
+ return log_error_and_throw(env, "encrypt_to_json",
150
+ "Failed to allocate cobhan output buffer");
378
151
  }
379
152
 
380
153
  if (unlikely(verbose_flag)) {
@@ -392,7 +165,7 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
392
165
 
393
166
  if (unlikely(result < 0)) {
394
167
  // TODO: Convert this to a proper error message
395
- return LogErrorAndThrow(env, "encrypt_to_json", std::to_string(result));
168
+ return log_error_and_throw(env, "encrypt_to_json", std::to_string(result));
396
169
  }
397
170
 
398
171
  Napi::Value output = cbuffer_to_nstring(env, output_cobhan_buffer);
@@ -407,15 +180,15 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
407
180
  }
408
181
 
409
182
  if (unlikely(setup_state == 0)) {
410
- return LogErrorAndThrow(env, "encrypt", "setup() not called");
183
+ return log_error_and_throw(env, "encrypt", "setup() not called");
411
184
  }
412
185
 
413
186
  if (unlikely(info.Length() < 2)) {
414
- return LogErrorAndThrow(env, "encrypt", "Wrong number of arguments");
187
+ return log_error_and_throw(env, "encrypt", "Wrong number of arguments");
415
188
  }
416
189
 
417
190
  if (unlikely(!info[0].IsString() || !info[1].IsBuffer())) {
418
- return LogErrorAndThrow(env, "encrypt", "Wrong argument types");
191
+ return log_error_and_throw(env, "encrypt", "Wrong argument types");
419
192
  }
420
193
 
421
194
  // Determine size
@@ -423,11 +196,11 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
423
196
  Napi::String partition_id = info[0].As<Napi::String>();
424
197
  partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
425
198
  if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
426
- return LogErrorAndThrow(env, "encrypt",
427
- "Failed to get partition_id utf8 length");
199
+ return log_error_and_throw(env, "encrypt",
200
+ "Failed to get partition_id utf8 length");
428
201
  }
429
202
  if (unlikely(partition_utf8_byte_length == 0)) {
430
- return LogErrorAndThrow(env, "encrypt", "partition_id is empty");
203
+ return log_error_and_throw(env, "encrypt", "partition_id is empty");
431
204
  }
432
205
 
433
206
  // Allocate
@@ -437,8 +210,11 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
437
210
  // If the buffer is small enough, allocate it on the stack
438
211
  size_t partition_id_cobhan_buffer_size_bytes =
439
212
  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);
213
+ debug_log_alloca("encrypt", "partition_id_cobhan_buffer",
214
+ partition_id_cobhan_buffer_size_bytes);
215
+ partition_id_cobhan_buffer =
216
+ (char *)alloca(partition_id_cobhan_buffer_size_bytes);
217
+ configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
442
218
  } else {
443
219
  // Otherwise, allocate it on the heap
444
220
  partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
@@ -446,8 +222,8 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
446
222
  partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
447
223
  }
448
224
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
449
- return LogErrorAndThrow(env, "encrypt",
450
- "Failed to allocate partitionId cobhan buffer");
225
+ return log_error_and_throw(env, "encrypt",
226
+ "Failed to allocate partitionId cobhan buffer");
451
227
  }
452
228
 
453
229
  // Copy
@@ -456,8 +232,8 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
456
232
  env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
457
233
  &partition_copied_bytes);
458
234
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
459
- return LogErrorAndThrow(env, "encrypt",
460
- "Failed to copy partitionId to cobhan buffer");
235
+ return log_error_and_throw(env, "encrypt",
236
+ "Failed to copy partitionId to cobhan buffer");
461
237
  }
462
238
 
463
239
  // Determine size
@@ -465,7 +241,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
465
241
  info[1].As<Napi::Buffer<unsigned char>>();
466
242
  size_t input_byte_length = input_napi_buffer.ByteLength();
467
243
  if (unlikely(input_byte_length == 0)) {
468
- return LogErrorAndThrow(env, "encrypt", "input is empty");
244
+ return log_error_and_throw(env, "encrypt", "input is empty");
469
245
  }
470
246
 
471
247
  // Allocate
@@ -478,6 +254,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
478
254
  debug_log_alloca("encrypt", "input_cobhan_buffer",
479
255
  input_cobhan_buffer_size_bytes);
480
256
  input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
257
+ configure_cbuffer(input_cobhan_buffer, input_byte_length);
481
258
  } else {
482
259
  // Otherwise, allocate it on the heap
483
260
  input_buffer_unique_ptr =
@@ -485,17 +262,27 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
485
262
  input_cobhan_buffer = input_buffer_unique_ptr.get();
486
263
  }
487
264
  if (unlikely(input_cobhan_buffer == nullptr)) {
488
- return LogErrorAndThrow(
265
+ return log_error_and_throw(
489
266
  env, "encrypt", "Failed to allocate cobhan buffer for input buffer");
490
267
  }
491
268
 
492
269
  // 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);
270
+ input_cobhan_buffer =
271
+ copy_nbuffer_to_cbuffer(env, input_napi_buffer, input_cobhan_buffer);
272
+ if (unlikely(input_cobhan_buffer == nullptr)) {
273
+ return log_error_and_throw(env, "encrypt",
274
+ "Failed to copy input buffer to cobhan buffer");
275
+ }
276
+
277
+ Napi::Value output =
278
+ encrypt_to_json(env, partition_copied_bytes, input_byte_length,
279
+ partition_id_cobhan_buffer, input_cobhan_buffer);
280
+
281
+ if (unlikely(verbose_flag)) {
282
+ debug_log("encrypt", "finished");
283
+ }
496
284
 
497
- return encrypt_to_json(env, partition_copied_bytes, input_byte_length,
498
- partition_id_cobhan_buffer, input_cobhan_buffer);
285
+ return output;
499
286
  }
500
287
 
501
288
  Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
@@ -506,15 +293,16 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
506
293
  }
507
294
 
508
295
  if (unlikely(setup_state == 0)) {
509
- return LogErrorAndThrow(env, "encrypt_string", "setup() not called");
296
+ return log_error_and_throw(env, "encrypt_string", "setup() not called");
510
297
  }
511
298
 
512
299
  if (unlikely(info.Length() < 2)) {
513
- return LogErrorAndThrow(env, "encrypt_string", "Wrong number of arguments");
300
+ return log_error_and_throw(env, "encrypt_string",
301
+ "Wrong number of arguments");
514
302
  }
515
303
 
516
304
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
517
- return LogErrorAndThrow(env, "encrypt_string", "Wrong argument types");
305
+ return log_error_and_throw(env, "encrypt_string", "Wrong argument types");
518
306
  }
519
307
 
520
308
  // Determine size
@@ -522,11 +310,11 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
522
310
  Napi::String partition_id = info[0].As<Napi::String>();
523
311
  partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
524
312
  if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
525
- return LogErrorAndThrow(env, "encrypt_string",
526
- "Failed to get partition_id utf8 length");
313
+ return log_error_and_throw(env, "encrypt_string",
314
+ "Failed to get partition_id utf8 length");
527
315
  }
528
316
  if (unlikely(partition_utf8_byte_length == 0)) {
529
- return LogErrorAndThrow(env, "encrypt_string", "partition_id is empty");
317
+ return log_error_and_throw(env, "encrypt_string", "partition_id is empty");
530
318
  }
531
319
 
532
320
  // Allocate
@@ -538,7 +326,9 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
538
326
  calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
539
327
  debug_log_alloca("encrypt_string", "partition_id_cobhan_buffer",
540
328
  partition_id_cobhan_buffer_size_bytes);
541
- partition_id_cobhan_buffer = (char *)alloca(partition_id_cobhan_buffer_size_bytes);
329
+ partition_id_cobhan_buffer =
330
+ (char *)alloca(partition_id_cobhan_buffer_size_bytes);
331
+ configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
542
332
  } else {
543
333
  // Otherwise, allocate it on the heap
544
334
  partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
@@ -546,8 +336,8 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
546
336
  partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
547
337
  }
548
338
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
549
- return LogErrorAndThrow(env, "encrypt_string",
550
- "Failed to allocate partitionId cobhan buffer");
339
+ return log_error_and_throw(env, "encrypt_string",
340
+ "Failed to allocate partitionId cobhan buffer");
551
341
  }
552
342
 
553
343
  // Copy
@@ -556,8 +346,8 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
556
346
  env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
557
347
  &partition_copied_bytes);
558
348
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
559
- return LogErrorAndThrow(env, "encrypt_string",
560
- "Failed to copy partitionId to cobhan buffer");
349
+ return log_error_and_throw(env, "encrypt_string",
350
+ "Failed to copy partitionId to cobhan buffer");
561
351
  }
562
352
 
563
353
  // Determine size
@@ -565,11 +355,11 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
565
355
  Napi::String input = info[1].As<Napi::String>();
566
356
  input_utf8_byte_length = nstring_utf8_byte_length(env, input);
567
357
  if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
568
- return LogErrorAndThrow(env, "encrypt_string",
569
- "Failed to get input utf8 length");
358
+ return log_error_and_throw(env, "encrypt_string",
359
+ "Failed to get input utf8 length");
570
360
  }
571
361
  if (unlikely(input_utf8_byte_length == 0)) {
572
- return LogErrorAndThrow(env, "encrypt_string", "input is empty");
362
+ return log_error_and_throw(env, "encrypt_string", "input is empty");
573
363
  }
574
364
 
575
365
  // Allocate
@@ -579,8 +369,10 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
579
369
  // If the buffer is small enough, allocate it on the stack
580
370
  size_t input_cobhan_buffer_size_bytes =
581
371
  calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
582
- debug_log_alloca("encrypt_string", "input_cobhan_buffer", input_cobhan_buffer_size_bytes);
372
+ debug_log_alloca("encrypt_string", "input_cobhan_buffer",
373
+ input_cobhan_buffer_size_bytes);
583
374
  input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
375
+ configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
584
376
  } else {
585
377
  // Otherwise, allocate it on the heap
586
378
  input_cobhan_buffer_unique_ptr =
@@ -588,8 +380,8 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
588
380
  input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
589
381
  }
590
382
  if (unlikely(input_cobhan_buffer == nullptr)) {
591
- return LogErrorAndThrow(env, "encrypt_string",
592
- "Failed to allocate input cobhan buffer");
383
+ return log_error_and_throw(env, "encrypt_string",
384
+ "Failed to allocate input cobhan buffer");
593
385
  }
594
386
 
595
387
  // Copy
@@ -598,12 +390,19 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
598
390
  copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
599
391
  input_cobhan_buffer, &input_copied_bytes);
600
392
  if (unlikely(input_cobhan_buffer == nullptr)) {
601
- return LogErrorAndThrow(env, "encrypt_string",
602
- "Failed to copy input to cobhan buffer");
393
+ return log_error_and_throw(env, "encrypt_string",
394
+ "Failed to copy input to cobhan buffer");
603
395
  }
604
396
 
605
- return encrypt_to_json(env, partition_copied_bytes, input_utf8_byte_length,
606
- partition_id_cobhan_buffer, input_cobhan_buffer);
397
+ Napi::Value output =
398
+ encrypt_to_json(env, partition_copied_bytes, input_utf8_byte_length,
399
+ partition_id_cobhan_buffer, input_cobhan_buffer);
400
+
401
+ if (unlikely(verbose_flag)) {
402
+ debug_log("encrypt_string", "finished");
403
+ }
404
+
405
+ return output;
607
406
  }
608
407
 
609
408
  Napi::Value decrypt(const Napi::CallbackInfo &info) {
@@ -614,15 +413,15 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
614
413
  }
615
414
 
616
415
  if (unlikely(setup_state == 0)) {
617
- return LogErrorAndThrow(env, "decrypt", "setup() not called");
416
+ return log_error_and_throw(env, "decrypt", "setup() not called");
618
417
  }
619
418
 
620
419
  if (unlikely(info.Length() < 2)) {
621
- return LogErrorAndThrow(env, "decrypt", "Wrong number of arguments");
420
+ return log_error_and_throw(env, "decrypt", "Wrong number of arguments");
622
421
  }
623
422
 
624
423
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
625
- return LogErrorAndThrow(env, "decrypt", "Wrong argument types");
424
+ return log_error_and_throw(env, "decrypt", "Wrong argument types");
626
425
  }
627
426
 
628
427
  // Determine size
@@ -630,11 +429,11 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
630
429
  Napi::String partition_id = info[0].As<Napi::String>();
631
430
  partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
632
431
  if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
633
- return LogErrorAndThrow(env, "decrypt",
634
- "Failed to get partition_id utf8 length");
432
+ return log_error_and_throw(env, "decrypt",
433
+ "Failed to get partition_id utf8 length");
635
434
  }
636
435
  if (unlikely(partition_utf8_byte_length == 0)) {
637
- return LogErrorAndThrow(env, "decrypt", "partition_id is empty");
436
+ return log_error_and_throw(env, "decrypt", "partition_id is empty");
638
437
  }
639
438
 
640
439
  // Allocate
@@ -648,6 +447,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
648
447
  partition_id_cobhan_buffer_size_bytes);
649
448
  partition_id_cobhan_buffer =
650
449
  (char *)alloca(partition_id_cobhan_buffer_size_bytes);
450
+ configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
651
451
  } else {
652
452
  // Otherwise, allocate it on the heap
653
453
  partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
@@ -655,8 +455,8 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
655
455
  partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
656
456
  }
657
457
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
658
- return LogErrorAndThrow(env, "decrypt",
659
- "Failed to allocate partition_id cobhan buffer");
458
+ return log_error_and_throw(env, "decrypt",
459
+ "Failed to allocate partition_id cobhan buffer");
660
460
  }
661
461
 
662
462
  // Copy
@@ -664,8 +464,8 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
664
464
  env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
665
465
  &partition_copied_bytes);
666
466
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
667
- return LogErrorAndThrow(env, "decrypt",
668
- "Failed to copy partition_id to cobhan buffer");
467
+ return log_error_and_throw(env, "decrypt",
468
+ "Failed to copy partition_id to cobhan buffer");
669
469
  }
670
470
 
671
471
  // Determine size
@@ -673,10 +473,11 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
673
473
  Napi::String input = info[1].As<Napi::String>();
674
474
  input_utf8_byte_length = nstring_utf8_byte_length(env, input);
675
475
  if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
676
- return LogErrorAndThrow(env, "decrypt", "Failed to get input utf8 length");
476
+ return log_error_and_throw(env, "decrypt",
477
+ "Failed to get input utf8 length");
677
478
  }
678
479
  if (unlikely(input_utf8_byte_length == 0)) {
679
- return LogErrorAndThrow(env, "decrypt", "input is empty");
480
+ return log_error_and_throw(env, "decrypt", "input is empty");
680
481
  }
681
482
 
682
483
  if (unlikely(verbose_flag)) {
@@ -694,6 +495,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
694
495
  debug_log_alloca("decrypt", "input_cobhan_buffer",
695
496
  input_cobhan_buffer_size_bytes);
696
497
  input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
498
+ configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
697
499
  } else {
698
500
  // Otherwise, allocate it on the heap
699
501
  input_cobhan_buffer_unique_ptr =
@@ -701,8 +503,8 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
701
503
  input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
702
504
  }
703
505
  if (unlikely(input_cobhan_buffer == nullptr)) {
704
- return LogErrorAndThrow(env, "decrypt",
705
- "Failed to allocate input cobhan buffer");
506
+ return log_error_and_throw(env, "decrypt",
507
+ "Failed to allocate input cobhan buffer");
706
508
  }
707
509
 
708
510
  // Copy
@@ -711,8 +513,8 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
711
513
  copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
712
514
  input_cobhan_buffer, &input_copied_bytes);
713
515
  if (unlikely(input_cobhan_buffer == nullptr)) {
714
- return LogErrorAndThrow(env, "decrypt",
715
- "Failed to copy input to cobhan buffer");
516
+ return log_error_and_throw(env, "decrypt",
517
+ "Failed to copy input to cobhan buffer");
716
518
  }
717
519
 
718
520
  char *output_cobhan_buffer;
@@ -732,8 +534,8 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
732
534
  output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
733
535
  }
734
536
  if (unlikely(output_cobhan_buffer == nullptr)) {
735
- return LogErrorAndThrow(env, "decrypt",
736
- "Failed to allocate cobhan output buffer");
537
+ return log_error_and_throw(env, "decrypt",
538
+ "Failed to allocate cobhan output buffer");
737
539
  }
738
540
 
739
541
  if (unlikely(verbose_flag)) {
@@ -751,10 +553,16 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
751
553
 
752
554
  if (unlikely(result < 0)) {
753
555
  // TODO: Convert this to a proper error message
754
- return LogErrorAndThrow(env, "decrypt", std::to_string(result));
556
+ return log_error_and_throw(env, "decrypt", std::to_string(result));
755
557
  }
756
558
 
757
- return cbuffer_to_nbuffer(env, output_cobhan_buffer);
559
+ Napi::Value output = cbuffer_to_nbuffer(env, output_cobhan_buffer);
560
+
561
+ if (unlikely(verbose_flag)) {
562
+ debug_log("decrypt", "finished");
563
+ }
564
+
565
+ return output;
758
566
  }
759
567
 
760
568
  Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
@@ -765,15 +573,16 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
765
573
  }
766
574
 
767
575
  if (unlikely(setup_state == 0)) {
768
- return LogErrorAndThrow(env, "decrypt_string", "setup() not called");
576
+ return log_error_and_throw(env, "decrypt_string", "setup() not called");
769
577
  }
770
578
 
771
579
  if (unlikely(info.Length() < 2)) {
772
- return LogErrorAndThrow(env, "decrypt_string", "Wrong number of arguments");
580
+ return log_error_and_throw(env, "decrypt_string",
581
+ "Wrong number of arguments");
773
582
  }
774
583
 
775
584
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
776
- return LogErrorAndThrow(env, "decrypt_string", "Wrong argument types");
585
+ return log_error_and_throw(env, "decrypt_string", "Wrong argument types");
777
586
  }
778
587
 
779
588
  // Determine size
@@ -781,11 +590,11 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
781
590
  Napi::String partition_id = info[0].As<Napi::String>();
782
591
  partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
783
592
  if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
784
- return LogErrorAndThrow(env, "decrypt_string",
785
- "Failed to get partition_id utf8 length");
593
+ return log_error_and_throw(env, "decrypt_string",
594
+ "Failed to get partition_id utf8 length");
786
595
  }
787
596
  if (unlikely(partition_utf8_byte_length == 0)) {
788
- return LogErrorAndThrow(env, "decrypt_string", "partition_id is empty");
597
+ return log_error_and_throw(env, "decrypt_string", "partition_id is empty");
789
598
  }
790
599
 
791
600
  // Allocate
@@ -799,6 +608,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
799
608
  partition_id_cobhan_buffer_size_bytes);
800
609
  partition_id_cobhan_buffer =
801
610
  (char *)alloca(partition_id_cobhan_buffer_size_bytes);
611
+ configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
802
612
  } else {
803
613
  // Otherwise, allocate it on the heap
804
614
  partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
@@ -806,8 +616,8 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
806
616
  partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
807
617
  }
808
618
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
809
- return LogErrorAndThrow(env, "decrypt_string",
810
- "Failed to allocate partitionId cobhan buffer");
619
+ return log_error_and_throw(env, "decrypt_string",
620
+ "Failed to allocate partitionId cobhan buffer");
811
621
  }
812
622
 
813
623
  // Copy
@@ -816,8 +626,8 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
816
626
  env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
817
627
  &partition_copied_bytes);
818
628
  if (unlikely(partition_id_cobhan_buffer == nullptr)) {
819
- return LogErrorAndThrow(env, "decrypt_string",
820
- "Failed to copy partitionId to cobhan buffer");
629
+ return log_error_and_throw(env, "decrypt_string",
630
+ "Failed to copy partitionId to cobhan buffer");
821
631
  }
822
632
 
823
633
  // Determine size
@@ -825,11 +635,11 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
825
635
  Napi::String input = info[1].As<Napi::String>();
826
636
  input_utf8_byte_length = nstring_utf8_byte_length(env, input);
827
637
  if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
828
- return LogErrorAndThrow(env, "decrypt_string",
829
- "Failed to get input utf8 length");
638
+ return log_error_and_throw(env, "decrypt_string",
639
+ "Failed to get input utf8 length");
830
640
  }
831
641
  if (unlikely(input_utf8_byte_length == 0)) {
832
- return LogErrorAndThrow(env, "decrypt_string", "input is empty");
642
+ return log_error_and_throw(env, "decrypt_string", "input is empty");
833
643
  }
834
644
 
835
645
  // Allocate
@@ -842,6 +652,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
842
652
  debug_log_alloca("decrypt_string", "input_cobhan_buffer",
843
653
  input_cobhan_buffer_size_bytes);
844
654
  input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
655
+ configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
845
656
  } else {
846
657
  // Otherwise, allocate it on the heap
847
658
  input_cobhan_buffer_unique_ptr =
@@ -849,8 +660,8 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
849
660
  input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
850
661
  }
851
662
  if (unlikely(input_cobhan_buffer == nullptr)) {
852
- return LogErrorAndThrow(env, "decrypt_string",
853
- "Failed to allocate input cobhan buffer");
663
+ return log_error_and_throw(env, "decrypt_string",
664
+ "Failed to allocate input cobhan buffer");
854
665
  }
855
666
 
856
667
  // Copy
@@ -859,8 +670,8 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
859
670
  copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
860
671
  input_cobhan_buffer, &input_copied_bytes);
861
672
  if (unlikely(input_cobhan_buffer == nullptr)) {
862
- return LogErrorAndThrow(env, "decrypt_string",
863
- "Failed to copy input to cobhan buffer");
673
+ return log_error_and_throw(env, "decrypt_string",
674
+ "Failed to copy input to cobhan buffer");
864
675
  }
865
676
 
866
677
  char *output_cobhan_buffer;
@@ -880,8 +691,8 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
880
691
  output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
881
692
  }
882
693
  if (unlikely(output_cobhan_buffer == nullptr)) {
883
- return LogErrorAndThrow(env, "decrypt_string",
884
- "Failed to allocate cobhan output buffer");
694
+ return log_error_and_throw(env, "decrypt_string",
695
+ "Failed to allocate cobhan output buffer");
885
696
  }
886
697
 
887
698
  if (unlikely(verbose_flag)) {
@@ -899,10 +710,15 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
899
710
 
900
711
  if (unlikely(result < 0)) {
901
712
  // TODO: Convert this to a proper error message
902
- return LogErrorAndThrow(env, "decrypt_string", std::to_string(result));
713
+ return log_error_and_throw(env, "decrypt_string", std::to_string(result));
903
714
  }
904
715
 
905
716
  Napi::Value output = cbuffer_to_nstring(env, output_cobhan_buffer);
717
+
718
+ if (unlikely(verbose_flag)) {
719
+ debug_log("decrypt_string", "finished");
720
+ }
721
+
906
722
  return output;
907
723
  }
908
724
 
@@ -933,8 +749,8 @@ void set_max_stack_alloc_item_size(const Napi::CallbackInfo &info) {
933
749
  }
934
750
 
935
751
  if (unlikely(info.Length() < 1)) {
936
- LogErrorAndThrow(env, "set_max_stack_alloc_item_size",
937
- "Wrong number of arguments");
752
+ log_error_and_throw(env, "set_max_stack_alloc_item_size",
753
+ "Wrong number of arguments");
938
754
  return;
939
755
  }
940
756
 
@@ -951,8 +767,8 @@ void set_safety_padding_overhead(const Napi::CallbackInfo &info) {
951
767
  }
952
768
 
953
769
  if (unlikely(info.Length() < 1)) {
954
- LogErrorAndThrow(env, "set_safety_padding_overhead",
955
- "Wrong number of arguments");
770
+ log_error_and_throw(env, "set_safety_padding_overhead",
771
+ "Wrong number of arguments");
956
772
  return;
957
773
  }
958
774
 
@@ -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,285 @@
1
+ #ifndef COBHAN_NAPI_INTEROP_H
2
+ #define COBHAN_NAPI_INTEROP_H
3
+ #include <string>
4
+ #define NODE_ADDON_API_DISABLE_DEPRECATED
5
+ #include "hints.h"
6
+ #include "logging.h"
7
+ #include <napi.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 int32_t
70
+ cbuffer_byte_length(char *cobhan_buffer) {
71
+ return *((int32_t *)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
+ int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
147
+ if (cobhan_buffer_size_bytes <= 0) {
148
+ return log_error_and_throw(env, "cbuffer_to_nstring",
149
+ "Invalid cobhan buffer byte length");
150
+ }
151
+
152
+ // Using C function because it allows length delimited input
153
+ napi_status status = napi_create_string_utf8(
154
+ env, ((const char *)cobhan_buffer) + cobhan_header_size_bytes,
155
+ cobhan_buffer_size_bytes, &output);
156
+
157
+ if (unlikely(status != napi_ok)) {
158
+ return log_error_and_throw(env, "cbuffer_to_nstring",
159
+ "napi_create_string_utf8 failed: " +
160
+ napi_status_to_string(status));
161
+ }
162
+
163
+ return Napi::String(env, output);
164
+ }
165
+
166
+ __attribute__((always_inline)) inline size_t
167
+ nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
168
+ napi_status status;
169
+ size_t utf8_length;
170
+
171
+ status = napi_get_value_string_utf8(env, str, nullptr, 0, &utf8_length);
172
+ if (unlikely(status != napi_ok)) {
173
+ log_error_and_throw(env, "nstring_utf8_length",
174
+ "napi_get_value_string_utf8 length check failed: " +
175
+ napi_status_to_string(status));
176
+ return (size_t)(-1);
177
+ }
178
+
179
+ return utf8_length;
180
+ }
181
+
182
+ __attribute__((always_inline)) inline char *
183
+ copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
184
+ size_t str_utf8_byte_length, char *cobhan_buffer,
185
+ size_t *byte_length = nullptr) {
186
+
187
+ size_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
188
+ if (unlikely(cobhan_buffer_size_bytes <= 0)) {
189
+ log_error_and_throw(env, "copy_nstring_to_cbuffer",
190
+ "Invalid cobhan buffer byte length");
191
+ return nullptr;
192
+ }
193
+
194
+ if (cobhan_buffer_size_bytes < str_utf8_byte_length) {
195
+ log_error_and_throw(env, "copy_nstring_to_cbuffer",
196
+ "String too large for cobhan buffer");
197
+ return nullptr;
198
+ }
199
+
200
+ napi_status status;
201
+ size_t copied_bytes;
202
+ // NOTE: This implementation relies on the additional byte that is reserved
203
+ // upon allocation for a NULL delimiter as methods like
204
+ // napi_get_value_string_utf8 append a NULL delimiter
205
+ status = napi_get_value_string_utf8(env, str,
206
+ cobhan_buffer + cobhan_header_size_bytes,
207
+ str_utf8_byte_length + 1, &copied_bytes);
208
+ if (unlikely(status != napi_ok)) {
209
+ log_error_and_throw(env, "copy_nstring_to_cbuffer",
210
+ "Napi utf8 string conversion failure: " +
211
+ napi_status_to_string(status));
212
+ return nullptr;
213
+ }
214
+
215
+ if (unlikely(copied_bytes != str_utf8_byte_length)) {
216
+ log_error_and_throw(env, "copy_nstring_to_cbuffer",
217
+ "Did not copy expected number of bytes " +
218
+ std::to_string(str_utf8_byte_length) + " copied " +
219
+ std::to_string(copied_bytes));
220
+ return nullptr;
221
+ }
222
+
223
+ configure_cbuffer(cobhan_buffer, copied_bytes);
224
+
225
+ if (byte_length != nullptr)
226
+ *byte_length = copied_bytes;
227
+ return cobhan_buffer;
228
+ }
229
+
230
+ __attribute__((always_inline)) inline char *
231
+ copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
232
+ char *cobhan_buffer) {
233
+
234
+ int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
235
+ if (unlikely(cobhan_buffer_size_bytes <= 0)) {
236
+ log_error_and_throw(env, "copy_nbuffer_to_cbuffer",
237
+ "Invalid cobhan buffer byte length");
238
+ return nullptr;
239
+ }
240
+
241
+ size_t nbuffer_byte_length = nbuffer.ByteLength();
242
+ if (nbuffer_byte_length > INT32_MAX ||
243
+ cobhan_buffer_size_bytes < (int32_t)nbuffer_byte_length) {
244
+ log_error_and_throw(env, "copy_nbuffer_to_cbuffer",
245
+ "Buffer too large for cobhan buffer");
246
+ return nullptr;
247
+ }
248
+ memcpy(cobhan_buffer + cobhan_header_size_bytes, nbuffer.Data(),
249
+ nbuffer_byte_length);
250
+ configure_cbuffer(cobhan_buffer, nbuffer_byte_length);
251
+ return cobhan_buffer;
252
+ }
253
+
254
+ __attribute__((always_inline)) inline Napi::Value
255
+ cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
256
+ int32_t cobhan_buffer_byte_length = cbuffer_byte_length(cobhan_buffer);
257
+ if (unlikely(cobhan_buffer_byte_length <= 0)) {
258
+ return log_error_and_throw(env, "cbuffer_to_nbuffer",
259
+ "Invalid cobhan buffer byte length");
260
+ }
261
+
262
+ if (unlikely(verbose_flag)) {
263
+ debug_log("cbuffer_to_nbuffer",
264
+ "cbuffer_byte_length: " +
265
+ std::to_string(cobhan_buffer_byte_length));
266
+ }
267
+
268
+ if (unlikely(cobhan_buffer_byte_length <= 0)) {
269
+ log_error_and_throw(env, "cbuffer_to_nbuffer",
270
+ "Invalid cobhan buffer byte length");
271
+ }
272
+
273
+ Napi::Buffer nbuffer = Napi::Buffer<unsigned char>::Copy(
274
+ env, ((unsigned char *)cobhan_buffer) + cobhan_header_size_bytes,
275
+ cobhan_buffer_byte_length);
276
+
277
+ if (unlikely(verbose_flag)) {
278
+ debug_log("cbuffer_to_nbuffer",
279
+ "nbuffer.ByteLength(): " + std::to_string(nbuffer.ByteLength()));
280
+ }
281
+
282
+ return nbuffer;
283
+ }
284
+
285
+ #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 "hints.h"
4
+ #include <cstdint>
5
+ #include <string>
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