asherah 1.3.19 → 1.3.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asherah",
3
- "version": "1.3.19",
3
+ "version": "1.3.20",
4
4
  "description": "Asherah envelope encryption and key rotation library",
5
5
  "exports": {
6
6
  "node-addons": "./dist/asherah.node"
@@ -4,8 +4,8 @@ echo "Downloading Asherah libraries"
4
4
 
5
5
  source .asherah-version
6
6
 
7
- rm -rf lib
8
- mkdir lib
7
+ #rm -rf lib
8
+ mkdir -p lib
9
9
  cd lib || exit 1
10
10
 
11
11
  OS=$(uname)
@@ -51,5 +51,5 @@ curl -s -L --fail -O --retry 999 --retry-max-time 0 "https://github.com/godaddy/
51
51
  grep -e "${ARCHIVE}" -e "${HEADER}" "${SUMS}" > ./SHA256SUM
52
52
  #shasum -a 256 -c ./SHA256SUM || (echo 'SHA256 mismatch!' ; rm -f ./*.a ./*.h ; exit 1)
53
53
 
54
- mv "${ARCHIVE}" libasherah.a
55
- mv "${HEADER}" libasherah.h
54
+ mv -f "${ARCHIVE}" libasherah.a
55
+ mv -f "${HEADER}" libasherah.h
package/src/asherah.cc CHANGED
@@ -17,12 +17,10 @@ void setup(const Napi::CallbackInfo &info) {
17
17
 
18
18
  if (unlikely(setup_state == 1)) {
19
19
  log_error_and_throw(env, "setup", "setup called twice");
20
- return;
21
20
  }
22
21
 
23
22
  if (unlikely(info.Length() < 1)) {
24
23
  log_error_and_throw(env, "setup", "Wrong number of arguments");
25
- return;
26
24
  }
27
25
 
28
26
  Napi::String config;
@@ -38,7 +36,6 @@ void setup(const Napi::CallbackInfo &info) {
38
36
  config_json = parse.Call(json, {config}).As<Napi::Object>();
39
37
  } else {
40
38
  log_error_and_throw(env, "setup", "Wrong argument type");
41
- return;
42
39
  }
43
40
 
44
41
  Napi::String product_id = config_json.Get("ProductID").As<Napi::String>();
@@ -56,49 +53,15 @@ void setup(const Napi::CallbackInfo &info) {
56
53
  debug_log("setup", "verbose_flag: defaulting to false");
57
54
  }
58
55
 
59
- // Determine size
60
- size_t config_utf8_byte_length;
61
- config_utf8_byte_length = nstring_utf8_byte_length(env, config);
62
- if (unlikely(config_utf8_byte_length == (size_t)(-1))) {
63
- log_error_and_throw(env, "setup", "Failed to get config utf8 length");
64
- return;
65
- }
66
-
67
- // Allocate
68
56
  char *config_cobhan_buffer;
69
- std::unique_ptr<char[]> config_cobhan_buffer_unique_ptr;
70
- if (config_utf8_byte_length < max_stack_alloc_size) {
71
- // If the buffer is small enough, allocate it on the stack
72
- size_t config_cobhan_buffer_size_bytes =
73
- calculate_cobhan_buffer_size_bytes(config_utf8_byte_length);
74
- debug_log_alloca("setup", "config_cobhan_buffer",
75
- config_cobhan_buffer_size_bytes);
76
- config_cobhan_buffer = (char *)alloca(config_cobhan_buffer_size_bytes);
77
- configure_cbuffer(config_cobhan_buffer, config_utf8_byte_length);
78
- } else {
79
- // Otherwise, allocate it on the heap
80
- config_cobhan_buffer_unique_ptr =
81
- heap_allocate_cbuffer("config_cobhan_buffer", config_utf8_byte_length);
82
- config_cobhan_buffer = config_cobhan_buffer_unique_ptr.get();
83
- }
84
- if (unlikely(config_cobhan_buffer == nullptr)) {
85
- log_error_and_throw(env, "setup",
86
- "Failed to allocate config cobhan buffer");
87
- return;
88
- }
57
+ size_t config_copied_bytes = 0;
58
+ NAPI_STRING_TO_CBUFFER(config, config_cobhan_buffer, config_copied_bytes,
59
+ "setup");
89
60
 
90
- // Copy
91
- size_t config_copied_bytes;
92
- config_cobhan_buffer =
93
- copy_nstring_to_cbuffer(env, config, config_utf8_byte_length,
94
- config_cobhan_buffer, &config_copied_bytes);
95
- if (unlikely(config_cobhan_buffer == nullptr)) {
96
- log_error_and_throw(env, "setup", "Failed to copy config to cobhan buffer");
97
- return;
98
- }
99
-
100
- if (unlikely(verbose_flag)) {
101
- debug_log("setup", "Calling asherah-cobhan SetupJson");
61
+ char *config_canary_ptr = get_canary_ptr(config_cobhan_buffer);
62
+ if (unlikely(!check_canary_ptr(config_canary_ptr))) {
63
+ log_error_and_throw(env, "encrypt_to_json",
64
+ "Failed initial canary check for config_cobhan_buffer");
102
65
  }
103
66
 
104
67
  // extern GoInt32 SetupJson(void* configJson);
@@ -108,17 +71,23 @@ void setup(const Napi::CallbackInfo &info) {
108
71
  debug_log("setup", "Returned from asherah-cobhan SetupJson");
109
72
  }
110
73
 
74
+ if (unlikely(!check_canary_ptr(config_canary_ptr))) {
75
+ log_error_and_throw(
76
+ env, "encrypt_to_json",
77
+ "Failed post-call canary check for config_cobhan_buffer");
78
+ }
79
+
111
80
  if (unlikely(result < 0)) {
112
81
  // TODO: Convert this to a proper error message
113
82
  log_error_and_throw(env, "setup", std::to_string(result));
114
- return;
115
83
  }
116
84
  setup_state = 1;
117
85
  }
118
86
 
119
- Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
120
- size_t data_bytes, char *partition_id_cobhan_buffer,
121
- char *input_cobhan_buffer) {
87
+ Napi::String encrypt_to_json(Napi::Env &env, size_t partition_bytes,
88
+ size_t data_bytes,
89
+ char *partition_id_cobhan_buffer,
90
+ char *input_cobhan_buffer) {
122
91
 
123
92
  size_t asherah_output_size_bytes =
124
93
  estimate_asherah_output_size_bytes(data_bytes, partition_bytes);
@@ -129,40 +98,24 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
129
98
  }
130
99
 
131
100
  char *output_cobhan_buffer;
132
- std::unique_ptr<char[]> output_cobhan_buffer_unique_ptr;
133
- if (asherah_output_size_bytes < max_stack_alloc_size) {
134
- // If the buffer is small enough, allocate it on the stack
135
- size_t output_cobhan_buffer_size_bytes =
136
- calculate_cobhan_buffer_size_bytes(asherah_output_size_bytes);
137
- debug_log_alloca("encrypt_to_json", "output_cobhan_buffer",
138
- output_cobhan_buffer_size_bytes);
139
- output_cobhan_buffer = (char *)alloca(output_cobhan_buffer_size_bytes);
140
- configure_cbuffer(output_cobhan_buffer, asherah_output_size_bytes);
141
- } else {
142
- // Otherwise, allocate it on the heap
143
- output_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
144
- "output_cobhan_buffer", asherah_output_size_bytes);
145
- output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
146
- }
147
- if (unlikely(output_cobhan_buffer == nullptr)) {
148
- return log_error_and_throw(env, "encrypt_to_json",
149
- "Failed to allocate cobhan output buffer");
150
- }
101
+ ALLOCATE_OUTPUT_CBUFFER(output_cobhan_buffer, asherah_output_size_bytes,
102
+ "encrypt_to_json");
151
103
 
152
104
  char *partition_id_canary_ptr = get_canary_ptr(partition_id_cobhan_buffer);
153
- if(!check_canary_ptr(partition_id_canary_ptr)) {
154
- return log_error_and_throw(env, "encrypt_to_json",
155
- "Failed initial canary check for partition_id_cobhan_buffer");
105
+ if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
106
+ log_error_and_throw(
107
+ env, "encrypt_to_json",
108
+ "Failed initial canary check for partition_id_cobhan_buffer");
156
109
  }
157
110
  char *input_canary_ptr = get_canary_ptr(input_cobhan_buffer);
158
- if(!check_canary_ptr(input_canary_ptr)) {
159
- return log_error_and_throw(env, "encrypt_to_json",
160
- "Failed initial canary check for input_cobhan_buffer");
111
+ if (unlikely(!check_canary_ptr(input_canary_ptr))) {
112
+ log_error_and_throw(env, "encrypt_to_json",
113
+ "Failed initial canary check for input_cobhan_buffer");
161
114
  }
162
115
  char *output_canary_ptr = get_canary_ptr(output_cobhan_buffer);
163
- if(!check_canary_ptr(output_canary_ptr)) {
164
- return log_error_and_throw(env, "encrypt_to_json",
165
- "Failed initial canary check for output_cobhan_buffer");
116
+ if (unlikely(!check_canary_ptr(output_canary_ptr))) {
117
+ log_error_and_throw(env, "encrypt_to_json",
118
+ "Failed initial canary check for output_cobhan_buffer");
166
119
  }
167
120
 
168
121
  if (unlikely(verbose_flag)) {
@@ -178,29 +131,32 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
178
131
  debug_log("encrypt_to_json", "Returning from asherah-cobhan EncryptToJson");
179
132
  }
180
133
 
181
- if(!check_canary_ptr(partition_id_canary_ptr)) {
182
- return log_error_and_throw(env, "encrypt_to_json",
183
- "Failed post-call canary check for partition_id_cobhan_buffer");
134
+ if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
135
+ log_error_and_throw(
136
+ env, "encrypt_to_json",
137
+ "Failed post-call canary check for partition_id_cobhan_buffer");
184
138
  }
185
- if(!check_canary_ptr(input_canary_ptr)) {
186
- return log_error_and_throw(env, "encrypt_to_json",
187
- "Failed post-call canary check for input_cobhan_buffer");
139
+ if (unlikely(!check_canary_ptr(input_canary_ptr))) {
140
+ log_error_and_throw(
141
+ env, "encrypt_to_json",
142
+ "Failed post-call canary check for input_cobhan_buffer");
188
143
  }
189
- if(!check_canary_ptr(output_canary_ptr)) {
190
- return log_error_and_throw(env, "encrypt_to_json",
191
- "Failed post-call canary check for output_cobhan_buffer");
144
+ if (unlikely(!check_canary_ptr(output_canary_ptr))) {
145
+ log_error_and_throw(
146
+ env, "encrypt_to_json",
147
+ "Failed post-call canary check for output_cobhan_buffer");
192
148
  }
193
149
 
194
150
  if (unlikely(result < 0)) {
195
151
  // TODO: Convert this to a proper error message
196
- return log_error_and_throw(env, "encrypt_to_json", std::to_string(result));
152
+ log_error_and_throw(env, "encrypt_to_json", std::to_string(result));
197
153
  }
198
154
 
199
- Napi::Value output = cbuffer_to_nstring(env, output_cobhan_buffer);
155
+ Napi::String output = cbuffer_to_nstring(env, output_cobhan_buffer);
200
156
  return output;
201
157
  }
202
158
 
203
- Napi::Value encrypt(const Napi::CallbackInfo &info) {
159
+ Napi::String encrypt(const Napi::CallbackInfo &info) {
204
160
  Napi::Env env = info.Env();
205
161
 
206
162
  if (unlikely(verbose_flag)) {
@@ -208,102 +164,32 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
208
164
  }
209
165
 
210
166
  if (unlikely(setup_state == 0)) {
211
- return log_error_and_throw(env, "encrypt", "setup() not called");
167
+ log_error_and_throw(env, "encrypt", "setup() not called");
212
168
  }
213
169
 
214
170
  if (unlikely(info.Length() < 2)) {
215
- return log_error_and_throw(env, "encrypt", "Wrong number of arguments");
171
+ log_error_and_throw(env, "encrypt", "Wrong number of arguments");
216
172
  }
217
173
 
218
174
  if (unlikely(!info[0].IsString() || !info[1].IsBuffer())) {
219
- return log_error_and_throw(env, "encrypt", "Wrong argument types");
175
+ log_error_and_throw(env, "encrypt", "Wrong argument types");
220
176
  }
221
177
 
222
- // Determine size
223
- size_t partition_utf8_byte_length;
224
178
  Napi::String partition_id = info[0].As<Napi::String>();
225
- partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
226
- if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
227
- return log_error_and_throw(env, "encrypt",
228
- "Failed to get partition_id utf8 length");
229
- }
230
- if (unlikely(partition_utf8_byte_length == 0)) {
231
- return log_error_and_throw(env, "encrypt", "partition_id is empty");
232
- }
233
-
234
- // Allocate
235
179
  char *partition_id_cobhan_buffer;
236
- std::unique_ptr<char[]> partition_id_cobhan_buffer_unique_ptr;
237
- if (partition_utf8_byte_length < max_stack_alloc_size) {
238
- // If the buffer is small enough, allocate it on the stack
239
- size_t partition_id_cobhan_buffer_size_bytes =
240
- calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
241
- debug_log_alloca("encrypt", "partition_id_cobhan_buffer",
242
- partition_id_cobhan_buffer_size_bytes);
243
- partition_id_cobhan_buffer =
244
- (char *)alloca(partition_id_cobhan_buffer_size_bytes);
245
- configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
246
- } else {
247
- // Otherwise, allocate it on the heap
248
- partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
249
- "partition_id_cobhan_buffer", partition_utf8_byte_length);
250
- partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
251
- }
252
- if (unlikely(partition_id_cobhan_buffer == nullptr)) {
253
- return log_error_and_throw(env, "encrypt",
254
- "Failed to allocate partitionId cobhan buffer");
255
- }
180
+ size_t partition_id_copied_bytes = 0;
181
+ NAPI_STRING_TO_CBUFFER(partition_id, partition_id_cobhan_buffer,
182
+ partition_id_copied_bytes, "encrypt");
256
183
 
257
- // Copy
258
- size_t partition_copied_bytes;
259
- partition_id_cobhan_buffer = copy_nstring_to_cbuffer(
260
- env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
261
- &partition_copied_bytes);
262
- if (unlikely(partition_id_cobhan_buffer == nullptr)) {
263
- return log_error_and_throw(env, "encrypt",
264
- "Failed to copy partitionId to cobhan buffer");
265
- }
266
-
267
- // Determine size
268
184
  Napi::Buffer<unsigned char> input_napi_buffer =
269
185
  info[1].As<Napi::Buffer<unsigned char>>();
270
- size_t input_byte_length = input_napi_buffer.ByteLength();
271
- if (unlikely(input_byte_length == 0)) {
272
- return log_error_and_throw(env, "encrypt", "input is empty");
273
- }
274
-
275
- // Allocate
276
186
  char *input_cobhan_buffer;
277
- std::unique_ptr<char[]> input_buffer_unique_ptr;
278
- if (input_byte_length < max_stack_alloc_size) {
279
- // If the buffer is small enough, allocate it on the stack
280
- size_t input_cobhan_buffer_size_bytes =
281
- calculate_cobhan_buffer_size_bytes(input_byte_length);
282
- debug_log_alloca("encrypt", "input_cobhan_buffer",
283
- input_cobhan_buffer_size_bytes);
284
- input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
285
- configure_cbuffer(input_cobhan_buffer, input_byte_length);
286
- } else {
287
- // Otherwise, allocate it on the heap
288
- input_buffer_unique_ptr =
289
- heap_allocate_cbuffer("input_cobhan_buffer", input_byte_length);
290
- input_cobhan_buffer = input_buffer_unique_ptr.get();
291
- }
292
- if (unlikely(input_cobhan_buffer == nullptr)) {
293
- return log_error_and_throw(
294
- env, "encrypt", "Failed to allocate cobhan buffer for input buffer");
295
- }
296
-
297
- // Copy
298
- input_cobhan_buffer =
299
- copy_nbuffer_to_cbuffer(env, input_napi_buffer, input_cobhan_buffer);
300
- if (unlikely(input_cobhan_buffer == nullptr)) {
301
- return log_error_and_throw(env, "encrypt",
302
- "Failed to copy input buffer to cobhan buffer");
303
- }
187
+ size_t input_copied_bytes = 0;
188
+ NAPI_BUFFER_TO_CBUFFER(input_napi_buffer, input_cobhan_buffer,
189
+ input_copied_bytes, "encrypt");
304
190
 
305
- Napi::Value output =
306
- encrypt_to_json(env, partition_copied_bytes, input_byte_length,
191
+ Napi::String output =
192
+ encrypt_to_json(env, partition_id_copied_bytes, input_copied_bytes,
307
193
  partition_id_cobhan_buffer, input_cobhan_buffer);
308
194
 
309
195
  if (unlikely(verbose_flag)) {
@@ -313,7 +199,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
313
199
  return output;
314
200
  }
315
201
 
316
- Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
202
+ Napi::String encrypt_string(const Napi::CallbackInfo &info) {
317
203
  Napi::Env env = info.Env();
318
204
 
319
205
  if (unlikely(verbose_flag)) {
@@ -321,109 +207,31 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
321
207
  }
322
208
 
323
209
  if (unlikely(setup_state == 0)) {
324
- return log_error_and_throw(env, "encrypt_string", "setup() not called");
210
+ log_error_and_throw(env, "encrypt_string", "setup() not called");
325
211
  }
326
212
 
327
213
  if (unlikely(info.Length() < 2)) {
328
- return log_error_and_throw(env, "encrypt_string",
329
- "Wrong number of arguments");
214
+ log_error_and_throw(env, "encrypt_string", "Wrong number of arguments");
330
215
  }
331
216
 
332
217
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
333
- return log_error_and_throw(env, "encrypt_string", "Wrong argument types");
218
+ log_error_and_throw(env, "encrypt_string", "Wrong argument types");
334
219
  }
335
220
 
336
- // Determine size
337
- size_t partition_utf8_byte_length;
338
221
  Napi::String partition_id = info[0].As<Napi::String>();
339
- partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
340
- if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
341
- return log_error_and_throw(env, "encrypt_string",
342
- "Failed to get partition_id utf8 length");
343
- }
344
- if (unlikely(partition_utf8_byte_length == 0)) {
345
- return log_error_and_throw(env, "encrypt_string", "partition_id is empty");
346
- }
347
-
348
- // Allocate
349
222
  char *partition_id_cobhan_buffer;
350
- std::unique_ptr<char[]> partition_id_cobhan_buffer_unique_ptr;
351
- if (partition_utf8_byte_length < max_stack_alloc_size) {
352
- // If the buffer is small enough, allocate it on the stack
353
- size_t partition_id_cobhan_buffer_size_bytes =
354
- calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
355
- debug_log_alloca("encrypt_string", "partition_id_cobhan_buffer",
356
- partition_id_cobhan_buffer_size_bytes);
357
- partition_id_cobhan_buffer =
358
- (char *)alloca(partition_id_cobhan_buffer_size_bytes);
359
- configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
360
- } else {
361
- // Otherwise, allocate it on the heap
362
- partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
363
- "partition_id_cobhan_buffer", partition_utf8_byte_length);
364
- partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
365
- }
366
- if (unlikely(partition_id_cobhan_buffer == nullptr)) {
367
- return log_error_and_throw(env, "encrypt_string",
368
- "Failed to allocate partitionId cobhan buffer");
369
- }
370
-
371
- // Copy
372
- size_t partition_copied_bytes;
373
- partition_id_cobhan_buffer = copy_nstring_to_cbuffer(
374
- env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
375
- &partition_copied_bytes);
376
- if (unlikely(partition_id_cobhan_buffer == nullptr)) {
377
- return log_error_and_throw(env, "encrypt_string",
378
- "Failed to copy partitionId to cobhan buffer");
379
- }
223
+ size_t partition_id_copied_bytes = 0;
224
+ NAPI_STRING_TO_CBUFFER(partition_id, partition_id_cobhan_buffer,
225
+ partition_id_copied_bytes, "encrypt_string");
380
226
 
381
- // Determine size
382
- size_t input_utf8_byte_length;
383
227
  Napi::String input = info[1].As<Napi::String>();
384
- input_utf8_byte_length = nstring_utf8_byte_length(env, input);
385
- if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
386
- return log_error_and_throw(env, "encrypt_string",
387
- "Failed to get input utf8 length");
388
- }
389
- if (unlikely(input_utf8_byte_length == 0)) {
390
- return log_error_and_throw(env, "encrypt_string", "input is empty");
391
- }
392
-
393
- // Allocate
394
228
  char *input_cobhan_buffer;
395
- std::unique_ptr<char[]> input_cobhan_buffer_unique_ptr;
396
- if (input_utf8_byte_length < max_stack_alloc_size) {
397
- // If the buffer is small enough, allocate it on the stack
398
- size_t input_cobhan_buffer_size_bytes =
399
- calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
400
- debug_log_alloca("encrypt_string", "input_cobhan_buffer",
401
- input_cobhan_buffer_size_bytes);
402
- input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
403
- configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
404
- } else {
405
- // Otherwise, allocate it on the heap
406
- input_cobhan_buffer_unique_ptr =
407
- heap_allocate_cbuffer("input_cobhan_buffer", input_utf8_byte_length);
408
- input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
409
- }
410
- if (unlikely(input_cobhan_buffer == nullptr)) {
411
- return log_error_and_throw(env, "encrypt_string",
412
- "Failed to allocate input cobhan buffer");
413
- }
229
+ size_t input_copied_bytes = 0;
230
+ NAPI_STRING_TO_CBUFFER(input, input_cobhan_buffer, input_copied_bytes,
231
+ "encrypt_string");
414
232
 
415
- // Copy
416
- size_t input_copied_bytes;
417
- input_cobhan_buffer =
418
- copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
419
- input_cobhan_buffer, &input_copied_bytes);
420
- if (unlikely(input_cobhan_buffer == nullptr)) {
421
- return log_error_and_throw(env, "encrypt_string",
422
- "Failed to copy input to cobhan buffer");
423
- }
424
-
425
- Napi::Value output =
426
- encrypt_to_json(env, partition_copied_bytes, input_utf8_byte_length,
233
+ Napi::String output =
234
+ encrypt_to_json(env, partition_id_copied_bytes, input_copied_bytes,
427
235
  partition_id_cobhan_buffer, input_cobhan_buffer);
428
236
 
429
237
  if (unlikely(verbose_flag)) {
@@ -433,7 +241,7 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
433
241
  return output;
434
242
  }
435
243
 
436
- Napi::Value decrypt(const Napi::CallbackInfo &info) {
244
+ Napi::Buffer<unsigned char> decrypt(const Napi::CallbackInfo &info) {
437
245
  Napi::Env env = info.Env();
438
246
 
439
247
  if (unlikely(verbose_flag)) {
@@ -441,145 +249,47 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
441
249
  }
442
250
 
443
251
  if (unlikely(setup_state == 0)) {
444
- return log_error_and_throw(env, "decrypt", "setup() not called");
252
+ log_error_and_throw(env, "decrypt", "setup() not called");
445
253
  }
446
254
 
447
255
  if (unlikely(info.Length() < 2)) {
448
- return log_error_and_throw(env, "decrypt", "Wrong number of arguments");
256
+ log_error_and_throw(env, "decrypt", "Wrong number of arguments");
449
257
  }
450
258
 
451
259
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
452
- return log_error_and_throw(env, "decrypt", "Wrong argument types");
260
+ log_error_and_throw(env, "decrypt", "Wrong argument types");
453
261
  }
454
262
 
455
- // Determine size
456
- size_t partition_utf8_byte_length, partition_copied_bytes;
457
263
  Napi::String partition_id = info[0].As<Napi::String>();
458
- partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
459
- if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
460
- return log_error_and_throw(env, "decrypt",
461
- "Failed to get partition_id utf8 length");
462
- }
463
- if (unlikely(partition_utf8_byte_length == 0)) {
464
- return log_error_and_throw(env, "decrypt", "partition_id is empty");
465
- }
466
-
467
- // Allocate
468
264
  char *partition_id_cobhan_buffer;
469
- std::unique_ptr<char[]> partition_id_cobhan_buffer_unique_ptr;
470
- if (partition_utf8_byte_length < max_stack_alloc_size) {
471
- // If the buffer is small enough, allocate it on the stack
472
- size_t partition_id_cobhan_buffer_size_bytes =
473
- calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
474
- debug_log_alloca("decrypt", "partition_id_cobhan_buffer",
475
- partition_id_cobhan_buffer_size_bytes);
476
- partition_id_cobhan_buffer =
477
- (char *)alloca(partition_id_cobhan_buffer_size_bytes);
478
- configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
479
- } else {
480
- // Otherwise, allocate it on the heap
481
- partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
482
- "partition_id_cobhan_buffer", partition_utf8_byte_length);
483
- partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
484
- }
485
- if (unlikely(partition_id_cobhan_buffer == nullptr)) {
486
- return log_error_and_throw(env, "decrypt",
487
- "Failed to allocate partition_id cobhan buffer");
488
- }
489
-
490
- // Copy
491
- partition_id_cobhan_buffer = copy_nstring_to_cbuffer(
492
- env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
493
- &partition_copied_bytes);
494
- if (unlikely(partition_id_cobhan_buffer == nullptr)) {
495
- return log_error_and_throw(env, "decrypt",
496
- "Failed to copy partition_id to cobhan buffer");
497
- }
265
+ size_t partition_id_copied_bytes = 0;
266
+ NAPI_STRING_TO_CBUFFER(partition_id, partition_id_cobhan_buffer,
267
+ partition_id_copied_bytes, "decrypt");
498
268
 
499
- // Determine size
500
- size_t input_utf8_byte_length;
501
269
  Napi::String input = info[1].As<Napi::String>();
502
- input_utf8_byte_length = nstring_utf8_byte_length(env, input);
503
- if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
504
- return log_error_and_throw(env, "decrypt",
505
- "Failed to get input utf8 length");
506
- }
507
- if (unlikely(input_utf8_byte_length == 0)) {
508
- return log_error_and_throw(env, "decrypt", "input is empty");
509
- }
510
-
511
- if (unlikely(verbose_flag)) {
512
- debug_log("decrypt",
513
- "input size " + std::to_string(input_utf8_byte_length));
514
- }
515
-
516
- // Allocate
517
270
  char *input_cobhan_buffer;
518
- std::unique_ptr<char[]> input_cobhan_buffer_unique_ptr;
519
- if (input_utf8_byte_length < max_stack_alloc_size) {
520
- // If the buffer is small enough, allocate it on the stack
521
- size_t input_cobhan_buffer_size_bytes =
522
- calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
523
- debug_log_alloca("decrypt", "input_cobhan_buffer",
524
- input_cobhan_buffer_size_bytes);
525
- input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
526
- configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
527
- } else {
528
- // Otherwise, allocate it on the heap
529
- input_cobhan_buffer_unique_ptr =
530
- heap_allocate_cbuffer("input_cobhan_buffer", input_utf8_byte_length);
531
- input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
532
- }
533
- if (unlikely(input_cobhan_buffer == nullptr)) {
534
- return log_error_and_throw(env, "decrypt",
535
- "Failed to allocate input cobhan buffer");
536
- }
537
-
538
- // Copy
539
- size_t input_copied_bytes;
540
- input_cobhan_buffer =
541
- copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
542
- input_cobhan_buffer, &input_copied_bytes);
543
- if (unlikely(input_cobhan_buffer == nullptr)) {
544
- return log_error_and_throw(env, "decrypt",
545
- "Failed to copy input to cobhan buffer");
546
- }
271
+ size_t input_copied_bytes = 0;
272
+ NAPI_STRING_TO_CBUFFER(input, input_cobhan_buffer, input_copied_bytes,
273
+ "decrypt");
547
274
 
548
275
  char *output_cobhan_buffer;
549
- std::unique_ptr<char[]> output_cobhan_buffer_unique_ptr;
550
- if (input_utf8_byte_length < max_stack_alloc_size) {
551
- // If the buffer is small enough, allocate it on the stack
552
- size_t output_cobhan_buffer_size_bytes =
553
- calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
554
- debug_log_alloca("decrypt", "output_cobhan_buffer",
555
- output_cobhan_buffer_size_bytes);
556
- output_cobhan_buffer = (char *)alloca(output_cobhan_buffer_size_bytes);
557
- configure_cbuffer(output_cobhan_buffer, input_utf8_byte_length);
558
- } else {
559
- // Otherwise, allocate it on the heap
560
- output_cobhan_buffer_unique_ptr =
561
- heap_allocate_cbuffer("output_cobhan_buffer", input_utf8_byte_length);
562
- output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
563
- }
564
- if (unlikely(output_cobhan_buffer == nullptr)) {
565
- return log_error_and_throw(env, "decrypt",
566
- "Failed to allocate cobhan output buffer");
567
- }
276
+ ALLOCATE_OUTPUT_CBUFFER(output_cobhan_buffer, input_copied_bytes, "decrypt");
568
277
 
569
278
  char *partition_id_canary_ptr = get_canary_ptr(partition_id_cobhan_buffer);
570
- if(!check_canary_ptr(partition_id_canary_ptr)) {
571
- return log_error_and_throw(env, "encrypt_to_json",
572
- "Failed initial canary check for partition_id_cobhan_buffer");
279
+ if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
280
+ log_error_and_throw(
281
+ env, "encrypt_to_json",
282
+ "Failed initial canary check for partition_id_cobhan_buffer");
573
283
  }
574
284
  char *input_canary_ptr = get_canary_ptr(input_cobhan_buffer);
575
- if(!check_canary_ptr(input_canary_ptr)) {
576
- return log_error_and_throw(env, "encrypt_to_json",
577
- "Failed initial canary check for input_cobhan_buffer");
285
+ if (unlikely(!check_canary_ptr(input_canary_ptr))) {
286
+ log_error_and_throw(env, "encrypt_to_json",
287
+ "Failed initial canary check for input_cobhan_buffer");
578
288
  }
579
289
  char *output_canary_ptr = get_canary_ptr(output_cobhan_buffer);
580
- if(!check_canary_ptr(output_canary_ptr)) {
581
- return log_error_and_throw(env, "encrypt_to_json",
582
- "Failed initial canary check for output_cobhan_buffer");
290
+ if (unlikely(!check_canary_ptr(output_canary_ptr))) {
291
+ log_error_and_throw(env, "encrypt_to_json",
292
+ "Failed initial canary check for output_cobhan_buffer");
583
293
  }
584
294
 
585
295
  if (unlikely(verbose_flag)) {
@@ -595,25 +305,29 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
595
305
  debug_log("decrypt", "Returned from asherah-cobhan DecryptFromJson");
596
306
  }
597
307
 
598
- if(!check_canary_ptr(partition_id_canary_ptr)) {
599
- return log_error_and_throw(env, "encrypt_to_json",
600
- "Failed post-call canary check for partition_id_cobhan_buffer");
308
+ if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
309
+ log_error_and_throw(
310
+ env, "encrypt_to_json",
311
+ "Failed post-call canary check for partition_id_cobhan_buffer");
601
312
  }
602
- if(!check_canary_ptr(input_canary_ptr)) {
603
- return log_error_and_throw(env, "encrypt_to_json",
604
- "Failed post-call canary check for input_cobhan_buffer");
313
+ if (unlikely(!check_canary_ptr(input_canary_ptr))) {
314
+ log_error_and_throw(
315
+ env, "encrypt_to_json",
316
+ "Failed post-call canary check for input_cobhan_buffer");
605
317
  }
606
- if(!check_canary_ptr(output_canary_ptr)) {
607
- return log_error_and_throw(env, "encrypt_to_json",
608
- "Failed post-call canary check for output_cobhan_buffer");
318
+ if (unlikely(!check_canary_ptr(output_canary_ptr))) {
319
+ log_error_and_throw(
320
+ env, "encrypt_to_json",
321
+ "Failed post-call canary check for output_cobhan_buffer");
609
322
  }
610
323
 
611
324
  if (unlikely(result < 0)) {
612
325
  // TODO: Convert this to a proper error message
613
- return log_error_and_throw(env, "decrypt", std::to_string(result));
326
+ log_error_and_throw(env, "decrypt", std::to_string(result));
614
327
  }
615
328
 
616
- Napi::Value output = cbuffer_to_nbuffer(env, output_cobhan_buffer);
329
+ Napi::Buffer<unsigned char> output =
330
+ cbuffer_to_nbuffer(env, output_cobhan_buffer);
617
331
 
618
332
  if (unlikely(verbose_flag)) {
619
333
  debug_log("decrypt", "finished");
@@ -622,7 +336,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
622
336
  return output;
623
337
  }
624
338
 
625
- Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
339
+ Napi::String decrypt_string(const Napi::CallbackInfo &info) {
626
340
  Napi::Env env = info.Env();
627
341
 
628
342
  if (unlikely(verbose_flag)) {
@@ -630,142 +344,48 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
630
344
  }
631
345
 
632
346
  if (unlikely(setup_state == 0)) {
633
- return log_error_and_throw(env, "decrypt_string", "setup() not called");
347
+ log_error_and_throw(env, "decrypt_string", "setup() not called");
634
348
  }
635
349
 
636
350
  if (unlikely(info.Length() < 2)) {
637
- return log_error_and_throw(env, "decrypt_string",
638
- "Wrong number of arguments");
351
+ log_error_and_throw(env, "decrypt_string", "Wrong number of arguments");
639
352
  }
640
353
 
641
354
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
642
- return log_error_and_throw(env, "decrypt_string", "Wrong argument types");
355
+ log_error_and_throw(env, "decrypt_string", "Wrong argument types");
643
356
  }
644
357
 
645
- // Determine size
646
- size_t partition_utf8_byte_length;
647
358
  Napi::String partition_id = info[0].As<Napi::String>();
648
- partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
649
- if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
650
- return log_error_and_throw(env, "decrypt_string",
651
- "Failed to get partition_id utf8 length");
652
- }
653
- if (unlikely(partition_utf8_byte_length == 0)) {
654
- return log_error_and_throw(env, "decrypt_string", "partition_id is empty");
655
- }
656
-
657
- // Allocate
658
359
  char *partition_id_cobhan_buffer;
659
- std::unique_ptr<char[]> partition_id_cobhan_buffer_unique_ptr;
660
- if (partition_utf8_byte_length < max_stack_alloc_size) {
661
- // If the buffer is small enough, allocate it on the stack
662
- size_t partition_id_cobhan_buffer_size_bytes =
663
- calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
664
- debug_log_alloca("decrypt_string", "partition_id_cobhan_buffer",
665
- partition_id_cobhan_buffer_size_bytes);
666
- partition_id_cobhan_buffer =
667
- (char *)alloca(partition_id_cobhan_buffer_size_bytes);
668
- configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
669
- } else {
670
- // Otherwise, allocate it on the heap
671
- partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
672
- "partition_id_cobhan_buffer", partition_utf8_byte_length);
673
- partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
674
- }
675
- if (unlikely(partition_id_cobhan_buffer == nullptr)) {
676
- return log_error_and_throw(env, "decrypt_string",
677
- "Failed to allocate partitionId cobhan buffer");
678
- }
360
+ size_t partition_id_copied_bytes = 0;
361
+ NAPI_STRING_TO_CBUFFER(partition_id, partition_id_cobhan_buffer,
362
+ partition_id_copied_bytes, "decrypt_string");
679
363
 
680
- // Copy
681
- size_t partition_copied_bytes;
682
- partition_id_cobhan_buffer = copy_nstring_to_cbuffer(
683
- env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
684
- &partition_copied_bytes);
685
- if (unlikely(partition_id_cobhan_buffer == nullptr)) {
686
- return log_error_and_throw(env, "decrypt_string",
687
- "Failed to copy partitionId to cobhan buffer");
688
- }
689
-
690
- // Determine size
691
- size_t input_utf8_byte_length;
692
364
  Napi::String input = info[1].As<Napi::String>();
693
- input_utf8_byte_length = nstring_utf8_byte_length(env, input);
694
- if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
695
- return log_error_and_throw(env, "decrypt_string",
696
- "Failed to get input utf8 length");
697
- }
698
- if (unlikely(input_utf8_byte_length == 0)) {
699
- return log_error_and_throw(env, "decrypt_string", "input is empty");
700
- }
701
-
702
- // Allocate
703
365
  char *input_cobhan_buffer;
704
- std::unique_ptr<char[]> input_cobhan_buffer_unique_ptr;
705
- if (input_utf8_byte_length < max_stack_alloc_size) {
706
- // If the buffer is small enough, allocate it on the stack
707
- size_t input_cobhan_buffer_size_bytes =
708
- calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
709
- debug_log_alloca("decrypt_string", "input_cobhan_buffer",
710
- input_cobhan_buffer_size_bytes);
711
- input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
712
- configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
713
- } else {
714
- // Otherwise, allocate it on the heap
715
- input_cobhan_buffer_unique_ptr =
716
- heap_allocate_cbuffer("input_cobhan_buffer", input_utf8_byte_length);
717
- input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
718
- }
719
- if (unlikely(input_cobhan_buffer == nullptr)) {
720
- return log_error_and_throw(env, "decrypt_string",
721
- "Failed to allocate input cobhan buffer");
722
- }
723
-
724
- // Copy
725
- size_t input_copied_bytes;
726
- input_cobhan_buffer =
727
- copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
728
- input_cobhan_buffer, &input_copied_bytes);
729
- if (unlikely(input_cobhan_buffer == nullptr)) {
730
- return log_error_and_throw(env, "decrypt_string",
731
- "Failed to copy input to cobhan buffer");
732
- }
366
+ size_t input_copied_bytes = 0;
367
+ NAPI_STRING_TO_CBUFFER(input, input_cobhan_buffer, input_copied_bytes,
368
+ "decrypt_string");
733
369
 
734
370
  char *output_cobhan_buffer;
735
- std::unique_ptr<char[]> output_cobhan_buffer_unique_ptr;
736
- if (input_utf8_byte_length < max_stack_alloc_size) {
737
- // If the buffer is small enough, allocate it on the stack
738
- size_t output_cobhan_buffer_size_bytes =
739
- calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
740
- debug_log_alloca("decrypt_string", "output_cobhan_buffer",
741
- output_cobhan_buffer_size_bytes);
742
- output_cobhan_buffer = (char *)alloca(output_cobhan_buffer_size_bytes);
743
- configure_cbuffer(output_cobhan_buffer, input_utf8_byte_length);
744
- } else {
745
- // Otherwise, allocate it on the heap
746
- output_cobhan_buffer_unique_ptr =
747
- heap_allocate_cbuffer("output_cobhan_buffer", input_utf8_byte_length);
748
- output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
749
- }
750
- if (unlikely(output_cobhan_buffer == nullptr)) {
751
- return log_error_and_throw(env, "decrypt_string",
752
- "Failed to allocate cobhan output buffer");
753
- }
371
+ ALLOCATE_OUTPUT_CBUFFER(output_cobhan_buffer, input_copied_bytes,
372
+ "decrypt_string");
754
373
 
755
374
  char *partition_id_canary_ptr = get_canary_ptr(partition_id_cobhan_buffer);
756
- if(!check_canary_ptr(partition_id_canary_ptr)) {
757
- return log_error_and_throw(env, "encrypt_to_json",
758
- "Failed initial canary check for partition_id_cobhan_buffer");
375
+ if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
376
+ log_error_and_throw(
377
+ env, "encrypt_to_json",
378
+ "Failed initial canary check for partition_id_cobhan_buffer");
759
379
  }
760
380
  char *input_canary_ptr = get_canary_ptr(input_cobhan_buffer);
761
- if(!check_canary_ptr(input_canary_ptr)) {
762
- return log_error_and_throw(env, "encrypt_to_json",
763
- "Failed initial canary check for input_cobhan_buffer");
381
+ if (unlikely(!check_canary_ptr(input_canary_ptr))) {
382
+ log_error_and_throw(env, "encrypt_to_json",
383
+ "Failed initial canary check for input_cobhan_buffer");
764
384
  }
765
385
  char *output_canary_ptr = get_canary_ptr(output_cobhan_buffer);
766
- if(!check_canary_ptr(output_canary_ptr)) {
767
- return log_error_and_throw(env, "encrypt_to_json",
768
- "Failed initial canary check for output_cobhan_buffer");
386
+ if (unlikely(!check_canary_ptr(output_canary_ptr))) {
387
+ log_error_and_throw(env, "encrypt_to_json",
388
+ "Failed initial canary check for output_cobhan_buffer");
769
389
  }
770
390
 
771
391
  if (unlikely(verbose_flag)) {
@@ -781,25 +401,28 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
781
401
  debug_log("decrypt_string", "Returned from asherah-cobhan DecryptFromJson");
782
402
  }
783
403
 
784
- if(!check_canary_ptr(partition_id_canary_ptr)) {
785
- return log_error_and_throw(env, "encrypt_to_json",
786
- "Failed post-call canary check for partition_id_cobhan_buffer");
404
+ if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
405
+ log_error_and_throw(
406
+ env, "encrypt_to_json",
407
+ "Failed post-call canary check for partition_id_cobhan_buffer");
787
408
  }
788
- if(!check_canary_ptr(input_canary_ptr)) {
789
- return log_error_and_throw(env, "encrypt_to_json",
790
- "Failed post-call canary check for input_cobhan_buffer");
409
+ if (unlikely(!check_canary_ptr(input_canary_ptr))) {
410
+ log_error_and_throw(
411
+ env, "encrypt_to_json",
412
+ "Failed post-call canary check for input_cobhan_buffer");
791
413
  }
792
- if(!check_canary_ptr(output_canary_ptr)) {
793
- return log_error_and_throw(env, "encrypt_to_json",
794
- "Failed post-call canary check for output_cobhan_buffer");
414
+ if (unlikely(!check_canary_ptr(output_canary_ptr))) {
415
+ log_error_and_throw(
416
+ env, "encrypt_to_json",
417
+ "Failed post-call canary check for output_cobhan_buffer");
795
418
  }
796
419
 
797
420
  if (unlikely(result < 0)) {
798
421
  // TODO: Convert this to a proper error message
799
- return log_error_and_throw(env, "decrypt_string", std::to_string(result));
422
+ log_error_and_throw(env, "decrypt_string", std::to_string(result));
800
423
  }
801
424
 
802
- Napi::Value output = cbuffer_to_nstring(env, output_cobhan_buffer);
425
+ Napi::String output = cbuffer_to_nstring(env, output_cobhan_buffer);
803
426
 
804
427
  if (unlikely(verbose_flag)) {
805
428
  debug_log("decrypt_string", "finished");
@@ -837,7 +460,6 @@ void set_max_stack_alloc_item_size(const Napi::CallbackInfo &info) {
837
460
  if (unlikely(info.Length() < 1)) {
838
461
  log_error_and_throw(env, "set_max_stack_alloc_item_size",
839
462
  "Wrong number of arguments");
840
- return;
841
463
  }
842
464
 
843
465
  Napi::Number item_size = info[0].ToNumber();
@@ -855,7 +477,6 @@ void set_safety_padding_overhead(const Napi::CallbackInfo &info) {
855
477
  if (unlikely(info.Length() < 1)) {
856
478
  log_error_and_throw(env, "set_safety_padding_overhead",
857
479
  "Wrong number of arguments");
858
- return;
859
480
  }
860
481
 
861
482
  Napi::Number safety_padding_number = info[0].ToNumber();
@@ -77,17 +77,16 @@ cbuffer_byte_length(char *cobhan_buffer) {
77
77
  return *((int32_t *)cobhan_buffer);
78
78
  }
79
79
 
80
- __attribute__((always_inline)) inline Napi::Value
80
+ __attribute__((always_inline)) inline void
81
81
  log_error_and_throw(Napi::Env &env, const char *function_name,
82
82
  std::string error_msg) {
83
83
  error_log(function_name, error_msg);
84
84
  Napi::Error::New(env, function_name + (": " + error_msg))
85
85
  .ThrowAsJavaScriptException();
86
- return env.Null();
87
86
  }
88
87
 
89
88
  __attribute__((always_inline)) inline size_t
90
- calculate_cobhan_buffer_size_bytes(size_t data_len_bytes) {
89
+ calculate_cobhan_buffer_allocation_size(size_t data_len_bytes) {
91
90
  return data_len_bytes + cobhan_header_size_bytes +
92
91
  1 + // Add one for possible NULL delimiter due to Node string functions
93
92
  canary_size // Add space for canary value
@@ -116,7 +115,8 @@ estimate_asherah_output_size_bytes(size_t data_byte_len,
116
115
  return asherah_output_size_bytes;
117
116
  }
118
117
 
119
- __attribute__((always_inline)) inline char* cbuffer_data_ptr(char *cobhan_buffer) {
118
+ __attribute__((always_inline)) inline char *
119
+ cbuffer_data_ptr(char *cobhan_buffer) {
120
120
  return cobhan_buffer + cobhan_header_size_bytes;
121
121
  }
122
122
 
@@ -144,10 +144,10 @@ __attribute__((always_inline)) inline void configure_cbuffer(char *buffer,
144
144
  *((int32_t *)(data_ptr + length + 1)) = 0;
145
145
 
146
146
  if (verbose_flag) {
147
- debug_log(
148
- "configure_cbuffer",
149
- "Writing second canary at " +
150
- std::to_string((intptr_t)(data_ptr + length + 1 + sizeof(int32_t))));
147
+ debug_log("configure_cbuffer",
148
+ "Writing second canary at " +
149
+ std::to_string(
150
+ (intptr_t)(data_ptr + length + 1 + sizeof(int32_t))));
151
151
  }
152
152
 
153
153
  // Second canary value is a int32_t 0xdeadbeef
@@ -160,8 +160,7 @@ get_canary_ptr(char *cobhan_buffer) {
160
160
  return cbuffer_data_ptr(cobhan_buffer) + cobhan_buffer_size_bytes + 1;
161
161
  }
162
162
 
163
- __attribute__((always_inline)) inline bool
164
- check_canary_ptr(char *canary_ptr) {
163
+ __attribute__((always_inline)) inline bool check_canary_ptr(char *canary_ptr) {
165
164
  int32_t zero_value = *((int32_t *)(canary_ptr));
166
165
  if (zero_value != 0) {
167
166
  std::string error_msg =
@@ -182,20 +181,21 @@ check_canary_ptr(char *canary_ptr) {
182
181
 
183
182
  __attribute__((always_inline)) inline std::unique_ptr<char[]>
184
183
  heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
185
- size_t cobhan_buffer_size_bytes =
186
- calculate_cobhan_buffer_size_bytes(size_bytes);
184
+ size_t cobhan_buffer_allocation_size =
185
+ calculate_cobhan_buffer_allocation_size(size_bytes);
187
186
  if (unlikely(verbose_flag)) {
188
187
  std::string log_msg =
189
188
  "heap_allocate_cbuffer(" + std::to_string(size_bytes) +
190
- ") (heap) cobhan_buffer_size_bytes: " +
191
- std::to_string(cobhan_buffer_size_bytes) + " for " + variable_name;
189
+ ") (heap) cobhan_buffer_allocation_size: " +
190
+ std::to_string(cobhan_buffer_allocation_size) + " for " + variable_name;
192
191
  debug_log("allocate_cbuffer", log_msg);
193
192
  }
194
193
 
195
- char *cobhan_buffer = new (std::nothrow) char[cobhan_buffer_size_bytes];
194
+ char *cobhan_buffer = new (std::nothrow) char[cobhan_buffer_allocation_size];
196
195
  if (unlikely(cobhan_buffer == nullptr)) {
197
- std::string error_msg =
198
- "new[" + std::to_string(cobhan_buffer_size_bytes) + " returned null";
196
+ std::string error_msg = "new[" +
197
+ std::to_string(cobhan_buffer_allocation_size) +
198
+ "] returned null";
199
199
  error_log("allocate_cbuffer", error_msg);
200
200
  return nullptr;
201
201
  }
@@ -204,25 +204,24 @@ heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
204
204
  return cobhan_buffer_unique_ptr;
205
205
  }
206
206
 
207
- __attribute__((always_inline)) inline Napi::Value
207
+ __attribute__((always_inline)) inline Napi::String
208
208
  cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
209
209
  napi_value output;
210
210
 
211
211
  int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
212
212
  if (cobhan_buffer_size_bytes <= 0) {
213
- return log_error_and_throw(env, "cbuffer_to_nstring",
214
- "Invalid cobhan buffer byte length");
213
+ log_error_and_throw(env, "cbuffer_to_nstring",
214
+ "Invalid cobhan buffer byte length");
215
215
  }
216
216
 
217
217
  // Using C function because it allows length delimited input
218
218
  napi_status status = napi_create_string_utf8(
219
- env, ((const char *)cobhan_buffer) + cobhan_header_size_bytes,
220
- cobhan_buffer_size_bytes, &output);
219
+ env, cbuffer_data_ptr(cobhan_buffer), cobhan_buffer_size_bytes, &output);
221
220
 
222
221
  if (unlikely(status != napi_ok)) {
223
- return log_error_and_throw(env, "cbuffer_to_nstring",
224
- "napi_create_string_utf8 failed: " +
225
- napi_status_to_string(status));
222
+ log_error_and_throw(env, "cbuffer_to_nstring",
223
+ "napi_create_string_utf8 failed: " +
224
+ napi_status_to_string(status));
226
225
  }
227
226
 
228
227
  return Napi::String(env, output);
@@ -265,12 +264,10 @@ copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
265
264
  if (unlikely(verbose_flag)) {
266
265
  debug_log("copy_nstring_to_cbuffer",
267
266
  "Copying " + std::to_string(str_utf8_byte_length) + " bytes to " +
268
- std::to_string(
269
- (intptr_t)(cobhan_buffer + cobhan_header_size_bytes)) +
270
- "-" +
271
- std::to_string((intptr_t)(cobhan_buffer +
272
- cobhan_header_size_bytes +
273
- str_utf8_byte_length)));
267
+ std::to_string((intptr_t)cbuffer_data_ptr(cobhan_buffer)) +
268
+ "-" +
269
+ std::to_string((intptr_t)(cbuffer_data_ptr(cobhan_buffer) +
270
+ str_utf8_byte_length)));
274
271
  }
275
272
 
276
273
  napi_status status;
@@ -278,8 +275,7 @@ copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
278
275
  // NOTE: This implementation relies on the additional byte that is reserved
279
276
  // upon allocation for a NULL delimiter as methods like
280
277
  // napi_get_value_string_utf8 append a NULL delimiter
281
- status = napi_get_value_string_utf8(env, str,
282
- cobhan_buffer + cobhan_header_size_bytes,
278
+ status = napi_get_value_string_utf8(env, str, cbuffer_data_ptr(cobhan_buffer),
283
279
  str_utf8_byte_length + 1, &copied_bytes);
284
280
  if (unlikely(status != napi_ok)) {
285
281
  log_error_and_throw(env, "copy_nstring_to_cbuffer",
@@ -321,18 +317,17 @@ copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
321
317
  "Buffer too large for cobhan buffer");
322
318
  return nullptr;
323
319
  }
324
- memcpy(cobhan_buffer + cobhan_header_size_bytes, nbuffer.Data(),
325
- nbuffer_byte_length);
320
+ memcpy(cbuffer_data_ptr(cobhan_buffer), nbuffer.Data(), nbuffer_byte_length);
326
321
  configure_cbuffer(cobhan_buffer, nbuffer_byte_length);
327
322
  return cobhan_buffer;
328
323
  }
329
324
 
330
- __attribute__((always_inline)) inline Napi::Value
325
+ __attribute__((always_inline)) inline Napi::Buffer<unsigned char>
331
326
  cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
332
327
  int32_t cobhan_buffer_byte_length = cbuffer_byte_length(cobhan_buffer);
333
328
  if (unlikely(cobhan_buffer_byte_length <= 0)) {
334
- return log_error_and_throw(env, "cbuffer_to_nbuffer",
335
- "Invalid cobhan buffer byte length");
329
+ log_error_and_throw(env, "cbuffer_to_nbuffer",
330
+ "Invalid cobhan buffer byte length");
336
331
  }
337
332
 
338
333
  if (unlikely(verbose_flag)) {
@@ -346,8 +341,8 @@ cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
346
341
  "Invalid cobhan buffer byte length");
347
342
  }
348
343
 
349
- Napi::Buffer nbuffer = Napi::Buffer<unsigned char>::Copy(
350
- env, ((unsigned char *)cobhan_buffer) + cobhan_header_size_bytes,
344
+ Napi::Buffer<unsigned char> nbuffer = Napi::Buffer<unsigned char>::Copy(
345
+ env, (const unsigned char *)cbuffer_data_ptr(cobhan_buffer),
351
346
  cobhan_buffer_byte_length);
352
347
 
353
348
  if (unlikely(verbose_flag)) {
@@ -358,4 +353,115 @@ cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
358
353
  return nbuffer;
359
354
  }
360
355
 
356
+ // These are macros due to the use of alloca()
357
+
358
+ #define NAPI_STRING_TO_CBUFFER(napi_string, cobhan_buffer, bytes_copied, \
359
+ function_name) \
360
+ std::unique_ptr<char[]> napi_string##_cobhan_buffer_unique_ptr; \
361
+ do { \
362
+ /* Determine size */ \
363
+ size_t napi_string##_utf8_byte_length = \
364
+ nstring_utf8_byte_length(env, napi_string); \
365
+ if (unlikely(napi_string##_utf8_byte_length == (size_t)(-1))) { \
366
+ log_error_and_throw(env, function_name, \
367
+ "Failed to get " #napi_string " utf8 length"); \
368
+ } \
369
+ if (unlikely(napi_string##_utf8_byte_length == 0)) { \
370
+ log_error_and_throw(env, function_name, #napi_string " is empty"); \
371
+ } \
372
+ /* Allocate */ \
373
+ if (napi_string##_utf8_byte_length < max_stack_alloc_size) { \
374
+ /* If the buffer is small enough, allocate it on the stack */ \
375
+ size_t napi_string##_cobhan_buffer_allocation_size = \
376
+ calculate_cobhan_buffer_allocation_size( \
377
+ napi_string##_utf8_byte_length); \
378
+ debug_log_alloca(function_name, #napi_string "_cobhan_buffer", \
379
+ napi_string##_cobhan_buffer_allocation_size); \
380
+ cobhan_buffer = \
381
+ (char *)alloca(napi_string##_cobhan_buffer_allocation_size); \
382
+ configure_cbuffer(cobhan_buffer, napi_string##_utf8_byte_length); \
383
+ } else { \
384
+ /* Otherwise, allocate it on the heap */ \
385
+ napi_string##_cobhan_buffer_unique_ptr = heap_allocate_cbuffer( \
386
+ #cobhan_buffer, napi_string##_utf8_byte_length); \
387
+ cobhan_buffer = napi_string##_cobhan_buffer_unique_ptr.get(); \
388
+ } \
389
+ if (unlikely(cobhan_buffer == nullptr)) { \
390
+ log_error_and_throw(env, function_name, \
391
+ "Failed to allocate " #napi_string \
392
+ " cobhan buffer"); \
393
+ } \
394
+ /* Copy */ \
395
+ cobhan_buffer = copy_nstring_to_cbuffer(env, napi_string, \
396
+ napi_string##_utf8_byte_length, \
397
+ cobhan_buffer, &bytes_copied); \
398
+ if (unlikely(cobhan_buffer == nullptr)) { \
399
+ log_error_and_throw(env, function_name, \
400
+ "Failed to copy " #napi_string " to cobhan buffer"); \
401
+ } \
402
+ } while (0);
403
+
404
+ #define NAPI_BUFFER_TO_CBUFFER(napi_buffer, cobhan_buffer, bytes_copied, \
405
+ function_name) \
406
+ std::unique_ptr<char[]> napi_buffer##_unique_ptr; \
407
+ do { \
408
+ /* Determine size */ \
409
+ size_t napi_buffer##_byte_length = napi_buffer.ByteLength(); \
410
+ if (unlikely(napi_buffer##_byte_length == 0)) { \
411
+ log_error_and_throw(env, function_name, #napi_buffer " is empty"); \
412
+ } \
413
+ /* Allocate */ \
414
+ if (napi_buffer##_byte_length < max_stack_alloc_size) { \
415
+ /* If the buffer is small enough, allocate it on the stack */ \
416
+ size_t napi_buffer##_cobhan_buffer_allocation_size = \
417
+ calculate_cobhan_buffer_allocation_size(napi_buffer##_byte_length); \
418
+ debug_log_alloca(function_name, #cobhan_buffer, \
419
+ napi_buffer##_cobhan_buffer_allocation_size); \
420
+ cobhan_buffer = \
421
+ (char *)alloca(napi_buffer##_cobhan_buffer_allocation_size); \
422
+ configure_cbuffer(cobhan_buffer, napi_buffer##_byte_length); \
423
+ } else { \
424
+ /* Otherwise, allocate it on the heap */ \
425
+ napi_buffer##_unique_ptr = \
426
+ heap_allocate_cbuffer(#cobhan_buffer, napi_buffer##_byte_length); \
427
+ cobhan_buffer = napi_buffer##_unique_ptr.get(); \
428
+ } \
429
+ if (unlikely(cobhan_buffer == nullptr)) { \
430
+ log_error_and_throw( \
431
+ env, function_name, \
432
+ "Failed to allocate cobhan buffer for " #napi_buffer); \
433
+ } \
434
+ /* Copy */ \
435
+ cobhan_buffer = copy_nbuffer_to_cbuffer(env, napi_buffer, cobhan_buffer); \
436
+ if (unlikely(cobhan_buffer == nullptr)) { \
437
+ log_error_and_throw(env, function_name, \
438
+ "Failed to copy " #napi_buffer " to cobhan buffer"); \
439
+ } \
440
+ bytes_copied = napi_buffer##_byte_length; \
441
+ } while (0);
442
+
443
+ #define ALLOCATE_OUTPUT_CBUFFER(cobhan_buffer, buffer_size, function_name) \
444
+ std::unique_ptr<char[]> cobhan_buffer##_unique_ptr; \
445
+ do { \
446
+ if (buffer_size < max_stack_alloc_size) { \
447
+ /* If the buffer is small enough, allocate it on the stack */ \
448
+ size_t cobhan_buffer##_cobhan_buffer_allocation_size = \
449
+ calculate_cobhan_buffer_allocation_size(buffer_size); \
450
+ debug_log_alloca(function_name, #cobhan_buffer, \
451
+ cobhan_buffer##_cobhan_buffer_allocation_size); \
452
+ cobhan_buffer = \
453
+ (char *)alloca(cobhan_buffer##_cobhan_buffer_allocation_size); \
454
+ configure_cbuffer(cobhan_buffer, buffer_size); \
455
+ } else { \
456
+ /* Otherwise, allocate it on the heap */ \
457
+ cobhan_buffer##_unique_ptr = \
458
+ heap_allocate_cbuffer(#cobhan_buffer, buffer_size); \
459
+ cobhan_buffer = output_cobhan_buffer_unique_ptr.get(); \
460
+ } \
461
+ if (unlikely(cobhan_buffer == nullptr)) { \
462
+ log_error_and_throw(env, function_name, \
463
+ "Failed to allocate " #cobhan_buffer); \
464
+ } \
465
+ } while (0);
466
+
361
467
  #endif