asherah 1.3.20 → 1.3.22

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
@@ -3,8 +3,8 @@
3
3
  {
4
4
  'target_name': 'asherah',
5
5
  'include_dirs': ["<!(node -p \"require('node-addon-api').include_dir\")"],
6
- "cflags": ["-fexceptions", "-g", "-O3"],
7
- "cflags_cc": ["-fexceptions", "-g", "-O3"],
6
+ "cflags": ["-fexceptions", "-g", "-O3", "-std=c++17"],
7
+ "cflags_cc": ["-fexceptions", "-g", "-O3", "-std=c++17"],
8
8
  "cflags!": [ "-fno-exceptions"],
9
9
  "cflags_cc!": [ "-fno-exceptions" ],
10
10
  'xcode_settings': {
@@ -12,7 +12,8 @@
12
12
  'OTHER_CFLAGS': [
13
13
  '-fexceptions',
14
14
  '-g',
15
- '-O3'
15
+ '-O3',
16
+ '-std=c++17'
16
17
  ],
17
18
  },
18
19
  'defines': [ 'NAPI_CPP_EXCEPTIONS', 'NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS', 'NODE_ADDON_API_DISABLE_DEPRECATED', 'NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED' ],
@@ -23,6 +24,8 @@
23
24
  'src/logging.h',
24
25
  'src/cobhan_napi_interop.cc',
25
26
  'src/cobhan_napi_interop.h',
27
+ 'src/cobhan.h',
28
+ 'src/cobhan.cc',
26
29
  'src/hints.h'
27
30
  ],
28
31
  'libraries': [ '../lib/libasherah.a' ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asherah",
3
- "version": "1.3.20",
3
+ "version": "1.3.22",
4
4
  "description": "Asherah envelope encryption and key rotation library",
5
5
  "exports": {
6
6
  "node-addons": "./dist/asherah.node"
@@ -28,6 +28,8 @@
28
28
  "src/logging.cc",
29
29
  "src/cobhan_napi_interop.h",
30
30
  "src/cobhan_napi_interop.cc",
31
+ "src/cobhan.h",
32
+ "src/cobhan.cc",
31
33
  "src/asherah.d.ts",
32
34
  "scripts/download-libraries.sh",
33
35
  "scripts/build.sh",
package/src/asherah.cc CHANGED
@@ -3,28 +3,31 @@
3
3
  #include "hints.h"
4
4
  #include "logging.h"
5
5
  #include <iostream>
6
+ #include <mutex>
6
7
  #include <napi.h>
7
8
 
8
9
  size_t max_stack_alloc_size = 2048;
9
10
  int32_t setup_state = 0;
11
+ std::mutex asherah_lock;
10
12
 
11
13
  void setup(const Napi::CallbackInfo &info) {
12
- Napi::Env env = info.Env();
14
+ std::lock_guard<std::mutex> lock(asherah_lock);
13
15
 
14
16
  if (unlikely(verbose_flag)) {
15
17
  debug_log("setup", "called");
16
18
  }
17
19
 
18
20
  if (unlikely(setup_state == 1)) {
19
- log_error_and_throw(env, "setup", "setup called twice");
21
+ log_error_and_throw("setup", "setup called twice");
20
22
  }
21
23
 
22
24
  if (unlikely(info.Length() < 1)) {
23
- log_error_and_throw(env, "setup", "Wrong number of arguments");
25
+ log_error_and_throw("setup", "Wrong number of arguments");
24
26
  }
25
27
 
26
28
  Napi::String config;
27
29
  Napi::Object config_json;
30
+ Napi::Env env = info.Env();
28
31
  Napi::Object json = env.Global().Get("JSON").As<Napi::Object>();
29
32
  if (likely(info[0].IsObject())) {
30
33
  config_json = info[0].As<Napi::Object>();
@@ -35,13 +38,13 @@ void setup(const Napi::CallbackInfo &info) {
35
38
  Napi::Function parse = json.Get("parse").As<Napi::Function>();
36
39
  config_json = parse.Call(json, {config}).As<Napi::Object>();
37
40
  } else {
38
- log_error_and_throw(env, "setup", "Wrong argument type");
41
+ log_error_and_throw("setup", "Wrong argument type");
39
42
  }
40
43
 
41
44
  Napi::String product_id = config_json.Get("ProductID").As<Napi::String>();
42
45
  Napi::String service_name = config_json.Get("ServiceName").As<Napi::String>();
43
46
 
44
- *est_intermediate_key_overhead_ptr =
47
+ est_intermediate_key_overhead =
45
48
  product_id.Utf8Value().length() + service_name.Utf8Value().length();
46
49
 
47
50
  Napi::Value verbose = config_json.Get("Verbose");
@@ -54,13 +57,13 @@ void setup(const Napi::CallbackInfo &info) {
54
57
  }
55
58
 
56
59
  char *config_cobhan_buffer;
57
- size_t config_copied_bytes = 0;
58
- NAPI_STRING_TO_CBUFFER(config, config_cobhan_buffer, config_copied_bytes,
60
+ size_t config_copied_bytes;
61
+ NAPI_STRING_TO_CBUFFER(env, config, config_cobhan_buffer, config_copied_bytes,
59
62
  "setup");
60
63
 
61
64
  char *config_canary_ptr = get_canary_ptr(config_cobhan_buffer);
62
65
  if (unlikely(!check_canary_ptr(config_canary_ptr))) {
63
- log_error_and_throw(env, "encrypt_to_json",
66
+ log_error_and_throw("encrypt_to_json",
64
67
  "Failed initial canary check for config_cobhan_buffer");
65
68
  }
66
69
 
@@ -73,13 +76,13 @@ void setup(const Napi::CallbackInfo &info) {
73
76
 
74
77
  if (unlikely(!check_canary_ptr(config_canary_ptr))) {
75
78
  log_error_and_throw(
76
- env, "encrypt_to_json",
79
+ "encrypt_to_json",
77
80
  "Failed post-call canary check for config_cobhan_buffer");
78
81
  }
79
82
 
80
83
  if (unlikely(result < 0)) {
81
84
  // TODO: Convert this to a proper error message
82
- log_error_and_throw(env, "setup", std::to_string(result));
85
+ log_error_and_throw("setup", std::to_string(result));
83
86
  }
84
87
  setup_state = 1;
85
88
  }
@@ -98,23 +101,23 @@ Napi::String encrypt_to_json(Napi::Env &env, size_t partition_bytes,
98
101
  }
99
102
 
100
103
  char *output_cobhan_buffer;
101
- ALLOCATE_OUTPUT_CBUFFER(output_cobhan_buffer, asherah_output_size_bytes,
102
- "encrypt_to_json");
104
+ ALLOCATE_CBUFFER(output_cobhan_buffer, asherah_output_size_bytes,
105
+ "encrypt_to_json");
103
106
 
104
107
  char *partition_id_canary_ptr = get_canary_ptr(partition_id_cobhan_buffer);
105
108
  if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
106
109
  log_error_and_throw(
107
- env, "encrypt_to_json",
110
+ "encrypt_to_json",
108
111
  "Failed initial canary check for partition_id_cobhan_buffer");
109
112
  }
110
113
  char *input_canary_ptr = get_canary_ptr(input_cobhan_buffer);
111
114
  if (unlikely(!check_canary_ptr(input_canary_ptr))) {
112
- log_error_and_throw(env, "encrypt_to_json",
115
+ log_error_and_throw("encrypt_to_json",
113
116
  "Failed initial canary check for input_cobhan_buffer");
114
117
  }
115
118
  char *output_canary_ptr = get_canary_ptr(output_cobhan_buffer);
116
119
  if (unlikely(!check_canary_ptr(output_canary_ptr))) {
117
- log_error_and_throw(env, "encrypt_to_json",
120
+ log_error_and_throw("encrypt_to_json",
118
121
  "Failed initial canary check for output_cobhan_buffer");
119
122
  }
120
123
 
@@ -133,23 +136,23 @@ Napi::String encrypt_to_json(Napi::Env &env, size_t partition_bytes,
133
136
 
134
137
  if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
135
138
  log_error_and_throw(
136
- env, "encrypt_to_json",
139
+ "encrypt_to_json",
137
140
  "Failed post-call canary check for partition_id_cobhan_buffer");
138
141
  }
139
142
  if (unlikely(!check_canary_ptr(input_canary_ptr))) {
140
143
  log_error_and_throw(
141
- env, "encrypt_to_json",
144
+ "encrypt_to_json",
142
145
  "Failed post-call canary check for input_cobhan_buffer");
143
146
  }
144
147
  if (unlikely(!check_canary_ptr(output_canary_ptr))) {
145
148
  log_error_and_throw(
146
- env, "encrypt_to_json",
149
+ "encrypt_to_json",
147
150
  "Failed post-call canary check for output_cobhan_buffer");
148
151
  }
149
152
 
150
153
  if (unlikely(result < 0)) {
151
154
  // TODO: Convert this to a proper error message
152
- log_error_and_throw(env, "encrypt_to_json", std::to_string(result));
155
+ log_error_and_throw("encrypt_to_json", std::to_string(result));
153
156
  }
154
157
 
155
158
  Napi::String output = cbuffer_to_nstring(env, output_cobhan_buffer);
@@ -157,35 +160,37 @@ Napi::String encrypt_to_json(Napi::Env &env, size_t partition_bytes,
157
160
  }
158
161
 
159
162
  Napi::String encrypt(const Napi::CallbackInfo &info) {
160
- Napi::Env env = info.Env();
163
+ std::lock_guard<std::mutex> lock(asherah_lock);
161
164
 
162
165
  if (unlikely(verbose_flag)) {
163
166
  debug_log("encrypt", "called");
164
167
  }
165
168
 
166
169
  if (unlikely(setup_state == 0)) {
167
- log_error_and_throw(env, "encrypt", "setup() not called");
170
+ log_error_and_throw("encrypt", "setup() not called");
168
171
  }
169
172
 
170
173
  if (unlikely(info.Length() < 2)) {
171
- log_error_and_throw(env, "encrypt", "Wrong number of arguments");
174
+ log_error_and_throw("encrypt", "Wrong number of arguments");
172
175
  }
173
176
 
174
177
  if (unlikely(!info[0].IsString() || !info[1].IsBuffer())) {
175
- log_error_and_throw(env, "encrypt", "Wrong argument types");
178
+ log_error_and_throw("encrypt", "Wrong argument types");
176
179
  }
177
180
 
181
+ Napi::Env env = info.Env();
182
+
178
183
  Napi::String partition_id = info[0].As<Napi::String>();
179
184
  char *partition_id_cobhan_buffer;
180
- size_t partition_id_copied_bytes = 0;
181
- NAPI_STRING_TO_CBUFFER(partition_id, partition_id_cobhan_buffer,
185
+ size_t partition_id_copied_bytes;
186
+ NAPI_STRING_TO_CBUFFER(env, partition_id, partition_id_cobhan_buffer,
182
187
  partition_id_copied_bytes, "encrypt");
183
188
 
184
189
  Napi::Buffer<unsigned char> input_napi_buffer =
185
190
  info[1].As<Napi::Buffer<unsigned char>>();
186
191
  char *input_cobhan_buffer;
187
- size_t input_copied_bytes = 0;
188
- NAPI_BUFFER_TO_CBUFFER(input_napi_buffer, input_cobhan_buffer,
192
+ size_t input_copied_bytes;
193
+ NAPI_BUFFER_TO_CBUFFER(env, input_napi_buffer, input_cobhan_buffer,
189
194
  input_copied_bytes, "encrypt");
190
195
 
191
196
  Napi::String output =
@@ -200,34 +205,36 @@ Napi::String encrypt(const Napi::CallbackInfo &info) {
200
205
  }
201
206
 
202
207
  Napi::String encrypt_string(const Napi::CallbackInfo &info) {
203
- Napi::Env env = info.Env();
208
+ std::lock_guard<std::mutex> lock(asherah_lock);
204
209
 
205
210
  if (unlikely(verbose_flag)) {
206
211
  debug_log("encrypt_string", "called");
207
212
  }
208
213
 
209
214
  if (unlikely(setup_state == 0)) {
210
- log_error_and_throw(env, "encrypt_string", "setup() not called");
215
+ log_error_and_throw("encrypt_string", "setup() not called");
211
216
  }
212
217
 
213
218
  if (unlikely(info.Length() < 2)) {
214
- log_error_and_throw(env, "encrypt_string", "Wrong number of arguments");
219
+ log_error_and_throw("encrypt_string", "Wrong number of arguments");
215
220
  }
216
221
 
217
222
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
218
- log_error_and_throw(env, "encrypt_string", "Wrong argument types");
223
+ log_error_and_throw("encrypt_string", "Wrong argument types");
219
224
  }
220
225
 
226
+ Napi::Env env = info.Env();
227
+
221
228
  Napi::String partition_id = info[0].As<Napi::String>();
222
229
  char *partition_id_cobhan_buffer;
223
- size_t partition_id_copied_bytes = 0;
224
- NAPI_STRING_TO_CBUFFER(partition_id, partition_id_cobhan_buffer,
230
+ size_t partition_id_copied_bytes;
231
+ NAPI_STRING_TO_CBUFFER(env, partition_id, partition_id_cobhan_buffer,
225
232
  partition_id_copied_bytes, "encrypt_string");
226
233
 
227
234
  Napi::String input = info[1].As<Napi::String>();
228
235
  char *input_cobhan_buffer;
229
- size_t input_copied_bytes = 0;
230
- NAPI_STRING_TO_CBUFFER(input, input_cobhan_buffer, input_copied_bytes,
236
+ size_t input_copied_bytes;
237
+ NAPI_STRING_TO_CBUFFER(env, input, input_cobhan_buffer, input_copied_bytes,
231
238
  "encrypt_string");
232
239
 
233
240
  Napi::String output =
@@ -242,53 +249,55 @@ Napi::String encrypt_string(const Napi::CallbackInfo &info) {
242
249
  }
243
250
 
244
251
  Napi::Buffer<unsigned char> decrypt(const Napi::CallbackInfo &info) {
245
- Napi::Env env = info.Env();
252
+ std::lock_guard<std::mutex> lock(asherah_lock);
246
253
 
247
254
  if (unlikely(verbose_flag)) {
248
255
  debug_log("decrypt", "called");
249
256
  }
250
257
 
251
258
  if (unlikely(setup_state == 0)) {
252
- log_error_and_throw(env, "decrypt", "setup() not called");
259
+ log_error_and_throw("decrypt", "setup() not called");
253
260
  }
254
261
 
255
262
  if (unlikely(info.Length() < 2)) {
256
- log_error_and_throw(env, "decrypt", "Wrong number of arguments");
263
+ log_error_and_throw("decrypt", "Wrong number of arguments");
257
264
  }
258
265
 
259
266
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
260
- log_error_and_throw(env, "decrypt", "Wrong argument types");
267
+ log_error_and_throw("decrypt", "Wrong argument types");
261
268
  }
262
269
 
270
+ Napi::Env env = info.Env();
271
+
263
272
  Napi::String partition_id = info[0].As<Napi::String>();
264
273
  char *partition_id_cobhan_buffer;
265
- size_t partition_id_copied_bytes = 0;
266
- NAPI_STRING_TO_CBUFFER(partition_id, partition_id_cobhan_buffer,
274
+ size_t partition_id_copied_bytes;
275
+ NAPI_STRING_TO_CBUFFER(env, partition_id, partition_id_cobhan_buffer,
267
276
  partition_id_copied_bytes, "decrypt");
268
277
 
269
278
  Napi::String input = info[1].As<Napi::String>();
270
279
  char *input_cobhan_buffer;
271
- size_t input_copied_bytes = 0;
272
- NAPI_STRING_TO_CBUFFER(input, input_cobhan_buffer, input_copied_bytes,
280
+ size_t input_copied_bytes;
281
+ NAPI_STRING_TO_CBUFFER(env, input, input_cobhan_buffer, input_copied_bytes,
273
282
  "decrypt");
274
283
 
275
284
  char *output_cobhan_buffer;
276
- ALLOCATE_OUTPUT_CBUFFER(output_cobhan_buffer, input_copied_bytes, "decrypt");
285
+ ALLOCATE_CBUFFER(output_cobhan_buffer, input_copied_bytes, "decrypt");
277
286
 
278
287
  char *partition_id_canary_ptr = get_canary_ptr(partition_id_cobhan_buffer);
279
288
  if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
280
289
  log_error_and_throw(
281
- env, "encrypt_to_json",
290
+ "encrypt_to_json",
282
291
  "Failed initial canary check for partition_id_cobhan_buffer");
283
292
  }
284
293
  char *input_canary_ptr = get_canary_ptr(input_cobhan_buffer);
285
294
  if (unlikely(!check_canary_ptr(input_canary_ptr))) {
286
- log_error_and_throw(env, "encrypt_to_json",
295
+ log_error_and_throw("encrypt_to_json",
287
296
  "Failed initial canary check for input_cobhan_buffer");
288
297
  }
289
298
  char *output_canary_ptr = get_canary_ptr(output_cobhan_buffer);
290
299
  if (unlikely(!check_canary_ptr(output_canary_ptr))) {
291
- log_error_and_throw(env, "encrypt_to_json",
300
+ log_error_and_throw("encrypt_to_json",
292
301
  "Failed initial canary check for output_cobhan_buffer");
293
302
  }
294
303
 
@@ -307,23 +316,23 @@ Napi::Buffer<unsigned char> decrypt(const Napi::CallbackInfo &info) {
307
316
 
308
317
  if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
309
318
  log_error_and_throw(
310
- env, "encrypt_to_json",
319
+ "encrypt_to_json",
311
320
  "Failed post-call canary check for partition_id_cobhan_buffer");
312
321
  }
313
322
  if (unlikely(!check_canary_ptr(input_canary_ptr))) {
314
323
  log_error_and_throw(
315
- env, "encrypt_to_json",
324
+ "encrypt_to_json",
316
325
  "Failed post-call canary check for input_cobhan_buffer");
317
326
  }
318
327
  if (unlikely(!check_canary_ptr(output_canary_ptr))) {
319
328
  log_error_and_throw(
320
- env, "encrypt_to_json",
329
+ "encrypt_to_json",
321
330
  "Failed post-call canary check for output_cobhan_buffer");
322
331
  }
323
332
 
324
333
  if (unlikely(result < 0)) {
325
334
  // TODO: Convert this to a proper error message
326
- log_error_and_throw(env, "decrypt", std::to_string(result));
335
+ log_error_and_throw("decrypt", std::to_string(result));
327
336
  }
328
337
 
329
338
  Napi::Buffer<unsigned char> output =
@@ -337,54 +346,55 @@ Napi::Buffer<unsigned char> decrypt(const Napi::CallbackInfo &info) {
337
346
  }
338
347
 
339
348
  Napi::String decrypt_string(const Napi::CallbackInfo &info) {
340
- Napi::Env env = info.Env();
349
+ std::lock_guard<std::mutex> lock(asherah_lock);
341
350
 
342
351
  if (unlikely(verbose_flag)) {
343
352
  debug_log("decrypt_string", "called");
344
353
  }
345
354
 
346
355
  if (unlikely(setup_state == 0)) {
347
- log_error_and_throw(env, "decrypt_string", "setup() not called");
356
+ log_error_and_throw("decrypt_string", "setup() not called");
348
357
  }
349
358
 
350
359
  if (unlikely(info.Length() < 2)) {
351
- log_error_and_throw(env, "decrypt_string", "Wrong number of arguments");
360
+ log_error_and_throw("decrypt_string", "Wrong number of arguments");
352
361
  }
353
362
 
354
363
  if (unlikely(!info[0].IsString() || !info[1].IsString())) {
355
- log_error_and_throw(env, "decrypt_string", "Wrong argument types");
364
+ log_error_and_throw("decrypt_string", "Wrong argument types");
356
365
  }
357
366
 
367
+ Napi::Env env = info.Env();
368
+
358
369
  Napi::String partition_id = info[0].As<Napi::String>();
359
370
  char *partition_id_cobhan_buffer;
360
- size_t partition_id_copied_bytes = 0;
361
- NAPI_STRING_TO_CBUFFER(partition_id, partition_id_cobhan_buffer,
371
+ size_t partition_id_copied_bytes;
372
+ NAPI_STRING_TO_CBUFFER(env, partition_id, partition_id_cobhan_buffer,
362
373
  partition_id_copied_bytes, "decrypt_string");
363
374
 
364
375
  Napi::String input = info[1].As<Napi::String>();
365
376
  char *input_cobhan_buffer;
366
- size_t input_copied_bytes = 0;
367
- NAPI_STRING_TO_CBUFFER(input, input_cobhan_buffer, input_copied_bytes,
377
+ size_t input_copied_bytes;
378
+ NAPI_STRING_TO_CBUFFER(env, input, input_cobhan_buffer, input_copied_bytes,
368
379
  "decrypt_string");
369
380
 
370
381
  char *output_cobhan_buffer;
371
- ALLOCATE_OUTPUT_CBUFFER(output_cobhan_buffer, input_copied_bytes,
372
- "decrypt_string");
382
+ ALLOCATE_CBUFFER(output_cobhan_buffer, input_copied_bytes, "decrypt_string");
373
383
 
374
384
  char *partition_id_canary_ptr = get_canary_ptr(partition_id_cobhan_buffer);
375
385
  if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
376
386
  log_error_and_throw(
377
- env, "encrypt_to_json",
387
+ "encrypt_to_json",
378
388
  "Failed initial canary check for partition_id_cobhan_buffer");
379
389
  }
380
390
  char *input_canary_ptr = get_canary_ptr(input_cobhan_buffer);
381
391
  if (unlikely(!check_canary_ptr(input_canary_ptr))) {
382
- log_error_and_throw(env, "encrypt_to_json",
392
+ log_error_and_throw("encrypt_to_json",
383
393
  "Failed initial canary check for input_cobhan_buffer");
384
394
  }
385
395
  char *output_canary_ptr = get_canary_ptr(output_cobhan_buffer);
386
396
  if (unlikely(!check_canary_ptr(output_canary_ptr))) {
387
- log_error_and_throw(env, "encrypt_to_json",
397
+ log_error_and_throw("encrypt_to_json",
388
398
  "Failed initial canary check for output_cobhan_buffer");
389
399
  }
390
400
 
@@ -403,23 +413,23 @@ Napi::String decrypt_string(const Napi::CallbackInfo &info) {
403
413
 
404
414
  if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
405
415
  log_error_and_throw(
406
- env, "encrypt_to_json",
416
+ "encrypt_to_json",
407
417
  "Failed post-call canary check for partition_id_cobhan_buffer");
408
418
  }
409
419
  if (unlikely(!check_canary_ptr(input_canary_ptr))) {
410
420
  log_error_and_throw(
411
- env, "encrypt_to_json",
421
+ "encrypt_to_json",
412
422
  "Failed post-call canary check for input_cobhan_buffer");
413
423
  }
414
424
  if (unlikely(!check_canary_ptr(output_canary_ptr))) {
415
425
  log_error_and_throw(
416
- env, "encrypt_to_json",
426
+ "encrypt_to_json",
417
427
  "Failed post-call canary check for output_cobhan_buffer");
418
428
  }
419
429
 
420
430
  if (unlikely(result < 0)) {
421
431
  // TODO: Convert this to a proper error message
422
- log_error_and_throw(env, "decrypt_string", std::to_string(result));
432
+ log_error_and_throw("decrypt_string", std::to_string(result));
423
433
  }
424
434
 
425
435
  Napi::String output = cbuffer_to_nstring(env, output_cobhan_buffer);
@@ -432,6 +442,8 @@ Napi::String decrypt_string(const Napi::CallbackInfo &info) {
432
442
  }
433
443
 
434
444
  void shutdown(const Napi::CallbackInfo &info) {
445
+ std::lock_guard<std::mutex> lock(asherah_lock);
446
+
435
447
  if (unlikely(verbose_flag)) {
436
448
  debug_log("shutdown", "called");
437
449
  }
@@ -451,14 +463,14 @@ void shutdown(const Napi::CallbackInfo &info) {
451
463
  }
452
464
 
453
465
  void set_max_stack_alloc_item_size(const Napi::CallbackInfo &info) {
454
- Napi::Env env = info.Env();
466
+ std::lock_guard<std::mutex> lock(asherah_lock);
455
467
 
456
468
  if (unlikely(verbose_flag)) {
457
469
  debug_log("set_max_stack_alloc_item_size", "called");
458
470
  }
459
471
 
460
472
  if (unlikely(info.Length() < 1)) {
461
- log_error_and_throw(env, "set_max_stack_alloc_item_size",
473
+ log_error_and_throw("set_max_stack_alloc_item_size",
462
474
  "Wrong number of arguments");
463
475
  }
464
476
 
@@ -468,20 +480,20 @@ void set_max_stack_alloc_item_size(const Napi::CallbackInfo &info) {
468
480
  }
469
481
 
470
482
  void set_safety_padding_overhead(const Napi::CallbackInfo &info) {
471
- Napi::Env env = info.Env();
483
+ std::lock_guard<std::mutex> lock(asherah_lock);
472
484
 
473
485
  if (unlikely(verbose_flag)) {
474
486
  debug_log("set_safety_padding_overhead", "called");
475
487
  }
476
488
 
477
489
  if (unlikely(info.Length() < 1)) {
478
- log_error_and_throw(env, "set_safety_padding_overhead",
490
+ log_error_and_throw("set_safety_padding_overhead",
479
491
  "Wrong number of arguments");
480
492
  }
481
493
 
482
494
  Napi::Number safety_padding_number = info[0].ToNumber();
483
495
 
484
- *safety_padding_bytes_ptr = (size_t)safety_padding_number.Int32Value();
496
+ set_safety_padding_bytes((size_t)safety_padding_number.Int32Value());
485
497
  }
486
498
 
487
499
  Napi::Object Init(Napi::Env env, Napi::Object exports) {
package/src/cobhan.cc ADDED
@@ -0,0 +1,2 @@
1
+ #include <stddef.h>
2
+ __attribute__((used)) size_t safety_padding_bytes = 0;
package/src/cobhan.h ADDED
@@ -0,0 +1,150 @@
1
+ #ifndef COBHAN_H
2
+ #define COBHAN_H
3
+ #include "logging.h"
4
+ #include <cstdint>
5
+ #include <stddef.h>
6
+ #include <string>
7
+
8
+ extern size_t safety_padding_bytes;
9
+
10
+ const size_t cobhan_header_size_bytes = 64 / 8;
11
+ const size_t canary_size = sizeof(int32_t) * 2;
12
+ const int32_t canary_constant = 0xdeadbeef;
13
+
14
+ __attribute__((always_inline)) inline void
15
+ set_safety_padding_bytes(size_t new_safety_padding_bytes) {
16
+ safety_padding_bytes = new_safety_padding_bytes;
17
+ }
18
+
19
+ __attribute__((always_inline)) inline int32_t
20
+ cbuffer_byte_length(char *cobhan_buffer) {
21
+ return *((int32_t *)cobhan_buffer);
22
+ }
23
+
24
+ __attribute__((always_inline)) inline char *
25
+ cbuffer_data_ptr(char *cobhan_buffer) {
26
+ return cobhan_buffer + cobhan_header_size_bytes;
27
+ }
28
+
29
+ __attribute__((always_inline)) inline size_t
30
+ calculate_cobhan_buffer_allocation_size(size_t data_len_bytes) {
31
+ return data_len_bytes + cobhan_header_size_bytes +
32
+ 1 + // Add one for possible NULL delimiter due to Node string functions
33
+ canary_size // Add space for canary value
34
+ + safety_padding_bytes; // Add safety padding if configured
35
+ }
36
+
37
+ __attribute__((always_inline)) inline void
38
+ configure_cbuffer(char *cobhan_buffer, size_t length) {
39
+ if (unlikely(verbose_flag)) {
40
+ debug_log("configure_cbuffer", "configure_cbuffer(" +
41
+ format_ptr(cobhan_buffer) + ", " +
42
+ std::to_string(length) + ")");
43
+ }
44
+
45
+ *((int32_t *)cobhan_buffer) = length;
46
+ // Reserved for future use
47
+ *((int32_t *)(cobhan_buffer + sizeof(int32_t))) = 0;
48
+
49
+ // Write canary values
50
+ char *data_ptr = cbuffer_data_ptr(cobhan_buffer);
51
+ #ifdef LOG_CANARY_WRITES
52
+ if (unlikely(verbose_flag)) {
53
+ debug_log("configure_cbuffer",
54
+ "Writing first canary at " + format_ptr(data_ptr + length + 1));
55
+ }
56
+ #endif
57
+
58
+ // First canary value is a int32_t 0 which gives us four NULLs
59
+ *((int32_t *)(data_ptr + length + 1)) = 0;
60
+ #ifdef LOG_CANARY_WRITES
61
+ if (unlikely(verbose_flag)) {
62
+ debug_log("configure_cbuffer",
63
+ "Writing second canary at " +
64
+ format_ptr(data_ptr + length + 1 + sizeof(int32_t)));
65
+ }
66
+ #endif
67
+
68
+ // Second canary value is a int32_t 0xdeadbeef
69
+ *((int32_t *)(data_ptr + length + 1 + sizeof(int32_t))) = canary_constant;
70
+ }
71
+
72
+ __attribute__((always_inline)) inline char *
73
+ get_canary_ptr(char *cobhan_buffer) {
74
+ int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
75
+ return cbuffer_data_ptr(cobhan_buffer) + cobhan_buffer_size_bytes + 1;
76
+ }
77
+
78
+ __attribute__((always_inline)) inline bool check_canary_ptr(char *canary_ptr) {
79
+ int32_t zero_value = *((int32_t *)(canary_ptr));
80
+ if (zero_value != 0) {
81
+ std::string error_msg =
82
+ "Canary check failed: " + std::to_string(zero_value) + " != 0";
83
+ error_log("canary_check_cbuffer", error_msg);
84
+ return false;
85
+ }
86
+ int32_t canary_value = *((int32_t *)(canary_ptr + sizeof(int32_t)));
87
+ if (canary_value != canary_constant) {
88
+ std::string error_msg =
89
+ "Canary check failed: " + std::to_string(canary_value) +
90
+ " != " + std::to_string(canary_constant);
91
+ error_log("canary_check_cbuffer", error_msg);
92
+ return false;
93
+ }
94
+ return true;
95
+ }
96
+
97
+ __attribute__((always_inline)) inline std::unique_ptr<char[]>
98
+ heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
99
+ size_t cobhan_buffer_allocation_size =
100
+ calculate_cobhan_buffer_allocation_size(size_bytes);
101
+ if (unlikely(verbose_flag)) {
102
+ std::string log_msg =
103
+ "heap_allocate_cbuffer(" + std::to_string(size_bytes) +
104
+ ") (heap) cobhan_buffer_allocation_size: " +
105
+ std::to_string(cobhan_buffer_allocation_size) + " for " + variable_name;
106
+ debug_log("allocate_cbuffer", log_msg);
107
+ }
108
+
109
+ char *cobhan_buffer = new (std::nothrow) char[cobhan_buffer_allocation_size];
110
+ if (unlikely(cobhan_buffer == nullptr)) {
111
+ std::string error_msg = "new[" +
112
+ std::to_string(cobhan_buffer_allocation_size) +
113
+ "] returned null";
114
+ error_log("allocate_cbuffer", error_msg);
115
+ return nullptr;
116
+ }
117
+ std::unique_ptr<char[]> cobhan_buffer_unique_ptr(cobhan_buffer);
118
+ configure_cbuffer(cobhan_buffer, size_bytes + safety_padding_bytes);
119
+ return cobhan_buffer_unique_ptr;
120
+ }
121
+
122
+ #define ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, buffer_size, unique_ptr, \
123
+ function_name) \
124
+ do { \
125
+ if (buffer_size < max_stack_alloc_size) { \
126
+ /* If the buffer is small enough, allocate it on the stack */ \
127
+ size_t cobhan_buffer##_cobhan_buffer_allocation_size = \
128
+ calculate_cobhan_buffer_allocation_size(buffer_size); \
129
+ debug_log_alloca(function_name, #cobhan_buffer, \
130
+ cobhan_buffer##_cobhan_buffer_allocation_size); \
131
+ cobhan_buffer = \
132
+ (char *)alloca(cobhan_buffer##_cobhan_buffer_allocation_size); \
133
+ configure_cbuffer(cobhan_buffer, buffer_size); \
134
+ } else { \
135
+ /* Otherwise, allocate it on the heap */ \
136
+ unique_ptr = heap_allocate_cbuffer(#cobhan_buffer, buffer_size); \
137
+ cobhan_buffer = unique_ptr.get(); \
138
+ } \
139
+ if (unlikely(cobhan_buffer == nullptr)) { \
140
+ log_error_and_throw(function_name, \
141
+ "Failed to allocate " #cobhan_buffer); \
142
+ } \
143
+ } while (0);
144
+
145
+ #define ALLOCATE_CBUFFER(cobhan_buffer, buffer_size, function_name) \
146
+ std::unique_ptr<char[]> cobhan_buffer##_unique_ptr; \
147
+ ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, buffer_size, \
148
+ cobhan_buffer##_unique_ptr, function_name);
149
+
150
+ #endif
@@ -1,11 +1,2 @@
1
1
  #include <stddef.h>
2
- static size_t est_intermediate_key_overhead = 0;
3
- static size_t safety_padding_bytes = 0;
4
-
5
- size_t* get_est_intermediate_key_overhead_ptr() {
6
- return &est_intermediate_key_overhead;
7
- }
8
-
9
- size_t* get_safety_padding_bytes_ptr() {
10
- return &safety_padding_bytes;
11
- }
2
+ __attribute__((used)) size_t est_intermediate_key_overhead = 0;
@@ -1,26 +1,17 @@
1
1
  #ifndef COBHAN_NAPI_INTEROP_H
2
2
  #define COBHAN_NAPI_INTEROP_H
3
+ #include "cobhan.h"
3
4
  #include "hints.h"
4
5
  #include "logging.h"
5
6
  #include <napi.h>
6
7
  #include <string>
7
8
 
8
- // Stupid hack to get around extern issues
9
- size_t *get_est_intermediate_key_overhead_ptr();
10
- size_t *get_safety_padding_bytes_ptr();
11
-
12
- size_t *est_intermediate_key_overhead_ptr =
13
- get_est_intermediate_key_overhead_ptr();
14
- size_t *safety_padding_bytes_ptr = get_safety_padding_bytes_ptr();
9
+ extern size_t est_intermediate_key_overhead;
15
10
 
16
11
  const size_t est_encryption_overhead = 48;
17
12
  const size_t est_envelope_overhead = 185;
18
13
  const double base64_overhead = 1.34;
19
14
 
20
- const size_t cobhan_header_size_bytes = 64 / 8;
21
- const size_t canary_size = sizeof(int32_t) * 2;
22
- const int32_t canary_constant = 0xdeadbeef;
23
-
24
15
  std::string napi_status_to_string(napi_status status) {
25
16
  switch (status) {
26
17
  case napi_ok:
@@ -72,27 +63,6 @@ std::string napi_status_to_string(napi_status status) {
72
63
  }
73
64
  }
74
65
 
75
- __attribute__((always_inline)) inline int32_t
76
- cbuffer_byte_length(char *cobhan_buffer) {
77
- return *((int32_t *)cobhan_buffer);
78
- }
79
-
80
- __attribute__((always_inline)) inline void
81
- log_error_and_throw(Napi::Env &env, const char *function_name,
82
- std::string error_msg) {
83
- error_log(function_name, error_msg);
84
- Napi::Error::New(env, function_name + (": " + error_msg))
85
- .ThrowAsJavaScriptException();
86
- }
87
-
88
- __attribute__((always_inline)) inline size_t
89
- calculate_cobhan_buffer_allocation_size(size_t data_len_bytes) {
90
- return data_len_bytes + cobhan_header_size_bytes +
91
- 1 + // Add one for possible NULL delimiter due to Node string functions
92
- canary_size // Add space for canary value
93
- + *safety_padding_bytes_ptr; // Add safety padding if configured
94
- }
95
-
96
66
  __attribute__((always_inline)) inline size_t
97
67
  estimate_asherah_output_size_bytes(size_t data_byte_len,
98
68
  size_t partition_byte_len) {
@@ -100,9 +70,9 @@ estimate_asherah_output_size_bytes(size_t data_byte_len,
100
70
  double est_data_byte_len =
101
71
  (double(data_byte_len + est_encryption_overhead) * base64_overhead) + 1;
102
72
 
103
- size_t asherah_output_size_bytes = size_t(
104
- est_envelope_overhead + *est_intermediate_key_overhead_ptr +
105
- partition_byte_len + est_data_byte_len + *safety_padding_bytes_ptr);
73
+ size_t asherah_output_size_bytes =
74
+ size_t(est_envelope_overhead + est_intermediate_key_overhead +
75
+ partition_byte_len + est_data_byte_len);
106
76
  if (unlikely(verbose_flag)) {
107
77
  std::string log_msg =
108
78
  "estimate_asherah_output_size(" + std::to_string(data_byte_len) + ", " +
@@ -115,118 +85,6 @@ estimate_asherah_output_size_bytes(size_t data_byte_len,
115
85
  return asherah_output_size_bytes;
116
86
  }
117
87
 
118
- __attribute__((always_inline)) inline char *
119
- cbuffer_data_ptr(char *cobhan_buffer) {
120
- return cobhan_buffer + cobhan_header_size_bytes;
121
- }
122
-
123
- __attribute__((always_inline)) inline void configure_cbuffer(char *buffer,
124
- size_t length) {
125
- if (verbose_flag) {
126
- debug_log("configure_cbuffer", "configure_cbuffer(" +
127
- std::to_string((intptr_t)buffer) + ", " +
128
- std::to_string(length) + ")");
129
- }
130
-
131
- *((int32_t *)buffer) = length;
132
- // Reserved for future use
133
- *((int32_t *)(buffer + sizeof(int32_t))) = 0;
134
-
135
- // Write canary values
136
- char *data_ptr = cbuffer_data_ptr(buffer);
137
- if (verbose_flag) {
138
- debug_log("configure_cbuffer",
139
- "Writing first canary at " +
140
- std::to_string((intptr_t)(data_ptr + length + 1)));
141
- }
142
-
143
- // First canary value is a int32_t 0 which gives us four NULLs
144
- *((int32_t *)(data_ptr + length + 1)) = 0;
145
-
146
- if (verbose_flag) {
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
- }
152
-
153
- // Second canary value is a int32_t 0xdeadbeef
154
- *((int32_t *)(data_ptr + length + 1 + sizeof(int32_t))) = canary_constant;
155
- }
156
-
157
- __attribute__((always_inline)) inline char *
158
- get_canary_ptr(char *cobhan_buffer) {
159
- int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
160
- return cbuffer_data_ptr(cobhan_buffer) + cobhan_buffer_size_bytes + 1;
161
- }
162
-
163
- __attribute__((always_inline)) inline bool check_canary_ptr(char *canary_ptr) {
164
- int32_t zero_value = *((int32_t *)(canary_ptr));
165
- if (zero_value != 0) {
166
- std::string error_msg =
167
- "Canary check failed: " + std::to_string(zero_value) + " != 0";
168
- error_log("canary_check_cbuffer", error_msg);
169
- return false;
170
- }
171
- int32_t canary_value = *((int32_t *)(canary_ptr + sizeof(int32_t)));
172
- if (canary_value != canary_constant) {
173
- std::string error_msg =
174
- "Canary check failed: " + std::to_string(canary_value) +
175
- " != " + std::to_string(canary_constant);
176
- error_log("canary_check_cbuffer", error_msg);
177
- return false;
178
- }
179
- return true;
180
- }
181
-
182
- __attribute__((always_inline)) inline std::unique_ptr<char[]>
183
- heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
184
- size_t cobhan_buffer_allocation_size =
185
- calculate_cobhan_buffer_allocation_size(size_bytes);
186
- if (unlikely(verbose_flag)) {
187
- std::string log_msg =
188
- "heap_allocate_cbuffer(" + std::to_string(size_bytes) +
189
- ") (heap) cobhan_buffer_allocation_size: " +
190
- std::to_string(cobhan_buffer_allocation_size) + " for " + variable_name;
191
- debug_log("allocate_cbuffer", log_msg);
192
- }
193
-
194
- char *cobhan_buffer = new (std::nothrow) char[cobhan_buffer_allocation_size];
195
- if (unlikely(cobhan_buffer == nullptr)) {
196
- std::string error_msg = "new[" +
197
- std::to_string(cobhan_buffer_allocation_size) +
198
- "] returned null";
199
- error_log("allocate_cbuffer", error_msg);
200
- return nullptr;
201
- }
202
- std::unique_ptr<char[]> cobhan_buffer_unique_ptr(cobhan_buffer);
203
- configure_cbuffer(cobhan_buffer, size_bytes + *safety_padding_bytes_ptr);
204
- return cobhan_buffer_unique_ptr;
205
- }
206
-
207
- __attribute__((always_inline)) inline Napi::String
208
- cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
209
- napi_value output;
210
-
211
- int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
212
- if (cobhan_buffer_size_bytes <= 0) {
213
- log_error_and_throw(env, "cbuffer_to_nstring",
214
- "Invalid cobhan buffer byte length");
215
- }
216
-
217
- // Using C function because it allows length delimited input
218
- napi_status status = napi_create_string_utf8(
219
- env, cbuffer_data_ptr(cobhan_buffer), cobhan_buffer_size_bytes, &output);
220
-
221
- if (unlikely(status != napi_ok)) {
222
- log_error_and_throw(env, "cbuffer_to_nstring",
223
- "napi_create_string_utf8 failed: " +
224
- napi_status_to_string(status));
225
- }
226
-
227
- return Napi::String(env, output);
228
- }
229
-
230
88
  __attribute__((always_inline)) inline size_t
231
89
  nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
232
90
  napi_status status;
@@ -234,9 +92,9 @@ nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
234
92
 
235
93
  status = napi_get_value_string_utf8(env, str, nullptr, 0, &utf8_length);
236
94
  if (unlikely(status != napi_ok)) {
237
- log_error_and_throw(env, "nstring_utf8_length",
238
- "napi_get_value_string_utf8 length check failed: " +
239
- napi_status_to_string(status));
95
+ error_log("nstring_utf8_length",
96
+ "napi_get_value_string_utf8 length check failed: " +
97
+ napi_status_to_string(status));
240
98
  return (size_t)(-1);
241
99
  }
242
100
 
@@ -250,24 +108,21 @@ copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
250
108
 
251
109
  size_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
252
110
  if (unlikely(cobhan_buffer_size_bytes <= 0)) {
253
- log_error_and_throw(env, "copy_nstring_to_cbuffer",
254
- "Invalid cobhan buffer byte length");
111
+ error_log("copy_nstring_to_cbuffer", "Invalid cobhan buffer byte length");
255
112
  return nullptr;
256
113
  }
257
114
 
258
115
  if (cobhan_buffer_size_bytes < str_utf8_byte_length) {
259
- log_error_and_throw(env, "copy_nstring_to_cbuffer",
260
- "String too large for cobhan buffer");
116
+ error_log("copy_nstring_to_cbuffer", "String too large for cobhan buffer");
261
117
  return nullptr;
262
118
  }
263
119
 
264
120
  if (unlikely(verbose_flag)) {
265
121
  debug_log("copy_nstring_to_cbuffer",
266
122
  "Copying " + std::to_string(str_utf8_byte_length) + " bytes to " +
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)));
123
+ format_ptr(cbuffer_data_ptr(cobhan_buffer)) + " - " +
124
+ format_ptr((cbuffer_data_ptr(cobhan_buffer) +
125
+ str_utf8_byte_length)));
271
126
  }
272
127
 
273
128
  napi_status status;
@@ -278,17 +133,17 @@ copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
278
133
  status = napi_get_value_string_utf8(env, str, cbuffer_data_ptr(cobhan_buffer),
279
134
  str_utf8_byte_length + 1, &copied_bytes);
280
135
  if (unlikely(status != napi_ok)) {
281
- log_error_and_throw(env, "copy_nstring_to_cbuffer",
282
- "Napi utf8 string conversion failure: " +
283
- napi_status_to_string(status));
136
+ error_log("copy_nstring_to_cbuffer",
137
+ "Napi utf8 string conversion failure: " +
138
+ napi_status_to_string(status));
284
139
  return nullptr;
285
140
  }
286
141
 
287
142
  if (unlikely(copied_bytes != str_utf8_byte_length)) {
288
- log_error_and_throw(env, "copy_nstring_to_cbuffer",
289
- "Did not copy expected number of bytes " +
290
- std::to_string(str_utf8_byte_length) + " copied " +
291
- std::to_string(copied_bytes));
143
+ error_log("copy_nstring_to_cbuffer",
144
+ "Did not copy expected number of bytes " +
145
+ std::to_string(str_utf8_byte_length) + " copied " +
146
+ std::to_string(copied_bytes));
292
147
  return nullptr;
293
148
  }
294
149
 
@@ -299,34 +154,34 @@ copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
299
154
  return cobhan_buffer;
300
155
  }
301
156
 
302
- __attribute__((always_inline)) inline char *
303
- copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
304
- char *cobhan_buffer) {
157
+ __attribute__((always_inline)) inline Napi::String
158
+ cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
159
+ napi_value output;
305
160
 
306
161
  int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
307
- if (unlikely(cobhan_buffer_size_bytes <= 0)) {
308
- log_error_and_throw(env, "copy_nbuffer_to_cbuffer",
162
+ if (cobhan_buffer_size_bytes <= 0) {
163
+ log_error_and_throw("cbuffer_to_nstring",
309
164
  "Invalid cobhan buffer byte length");
310
- return nullptr;
311
165
  }
312
166
 
313
- size_t nbuffer_byte_length = nbuffer.ByteLength();
314
- if (nbuffer_byte_length > INT32_MAX ||
315
- cobhan_buffer_size_bytes < (int32_t)nbuffer_byte_length) {
316
- log_error_and_throw(env, "copy_nbuffer_to_cbuffer",
317
- "Buffer too large for cobhan buffer");
318
- return nullptr;
167
+ // Using C function because it allows length delimited input
168
+ napi_status status = napi_create_string_utf8(
169
+ env, cbuffer_data_ptr(cobhan_buffer), cobhan_buffer_size_bytes, &output);
170
+
171
+ if (unlikely(status != napi_ok)) {
172
+ log_error_and_throw("cbuffer_to_nstring",
173
+ "napi_create_string_utf8 failed: " +
174
+ napi_status_to_string(status));
319
175
  }
320
- memcpy(cbuffer_data_ptr(cobhan_buffer), nbuffer.Data(), nbuffer_byte_length);
321
- configure_cbuffer(cobhan_buffer, nbuffer_byte_length);
322
- return cobhan_buffer;
176
+
177
+ return Napi::String(env, output);
323
178
  }
324
179
 
325
180
  __attribute__((always_inline)) inline Napi::Buffer<unsigned char>
326
181
  cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
327
182
  int32_t cobhan_buffer_byte_length = cbuffer_byte_length(cobhan_buffer);
328
183
  if (unlikely(cobhan_buffer_byte_length <= 0)) {
329
- log_error_and_throw(env, "cbuffer_to_nbuffer",
184
+ log_error_and_throw("cbuffer_to_nbuffer",
330
185
  "Invalid cobhan buffer byte length");
331
186
  }
332
187
 
@@ -337,7 +192,7 @@ cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
337
192
  }
338
193
 
339
194
  if (unlikely(cobhan_buffer_byte_length <= 0)) {
340
- log_error_and_throw(env, "cbuffer_to_nbuffer",
195
+ log_error_and_throw("cbuffer_to_nbuffer",
341
196
  "Invalid cobhan buffer byte length");
342
197
  }
343
198
 
@@ -353,115 +208,75 @@ cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
353
208
  return nbuffer;
354
209
  }
355
210
 
211
+ __attribute__((always_inline)) inline char *
212
+ copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
213
+ char *cobhan_buffer) {
214
+
215
+ int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
216
+ if (unlikely(cobhan_buffer_size_bytes <= 0)) {
217
+ error_log("copy_nbuffer_to_cbuffer", "Invalid cobhan buffer byte length");
218
+ return nullptr;
219
+ }
220
+
221
+ size_t nbuffer_byte_length = nbuffer.ByteLength();
222
+ if (nbuffer_byte_length > INT32_MAX ||
223
+ cobhan_buffer_size_bytes < (int32_t)nbuffer_byte_length) {
224
+ error_log("copy_nbuffer_to_cbuffer", "Buffer too large for cobhan buffer");
225
+ return nullptr;
226
+ }
227
+ memcpy(cbuffer_data_ptr(cobhan_buffer), nbuffer.Data(), nbuffer_byte_length);
228
+ configure_cbuffer(cobhan_buffer, nbuffer_byte_length);
229
+ return cobhan_buffer;
230
+ }
231
+
356
232
  // These are macros due to the use of alloca()
357
233
 
358
- #define NAPI_STRING_TO_CBUFFER(napi_string, cobhan_buffer, bytes_copied, \
234
+ #define NAPI_STRING_TO_CBUFFER(env, napi_string, cobhan_buffer, bytes_copied, \
359
235
  function_name) \
360
- std::unique_ptr<char[]> napi_string##_cobhan_buffer_unique_ptr; \
236
+ std::unique_ptr<char[]> napi_string##_unique_ptr; \
361
237
  do { \
362
238
  /* Determine size */ \
363
239
  size_t napi_string##_utf8_byte_length = \
364
240
  nstring_utf8_byte_length(env, napi_string); \
365
241
  if (unlikely(napi_string##_utf8_byte_length == (size_t)(-1))) { \
366
- log_error_and_throw(env, function_name, \
242
+ log_error_and_throw(function_name, \
367
243
  "Failed to get " #napi_string " utf8 length"); \
368
244
  } \
369
245
  if (unlikely(napi_string##_utf8_byte_length == 0)) { \
370
- log_error_and_throw(env, function_name, #napi_string " is empty"); \
246
+ log_error_and_throw(function_name, #napi_string " is empty"); \
371
247
  } \
372
248
  /* 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
- } \
249
+ ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, napi_string##_utf8_byte_length, \
250
+ napi_string##_unique_ptr, function_name); \
394
251
  /* Copy */ \
395
252
  cobhan_buffer = copy_nstring_to_cbuffer(env, napi_string, \
396
253
  napi_string##_utf8_byte_length, \
397
254
  cobhan_buffer, &bytes_copied); \
398
255
  if (unlikely(cobhan_buffer == nullptr)) { \
399
- log_error_and_throw(env, function_name, \
256
+ log_error_and_throw(function_name, \
400
257
  "Failed to copy " #napi_string " to cobhan buffer"); \
401
258
  } \
402
259
  } while (0);
403
260
 
404
- #define NAPI_BUFFER_TO_CBUFFER(napi_buffer, cobhan_buffer, bytes_copied, \
261
+ #define NAPI_BUFFER_TO_CBUFFER(env, napi_buffer, cobhan_buffer, bytes_copied, \
405
262
  function_name) \
406
263
  std::unique_ptr<char[]> napi_buffer##_unique_ptr; \
407
264
  do { \
408
265
  /* Determine size */ \
409
266
  size_t napi_buffer##_byte_length = napi_buffer.ByteLength(); \
410
267
  if (unlikely(napi_buffer##_byte_length == 0)) { \
411
- log_error_and_throw(env, function_name, #napi_buffer " is empty"); \
268
+ log_error_and_throw(function_name, #napi_buffer " is empty"); \
412
269
  } \
413
270
  /* 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
- } \
271
+ ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, napi_buffer##_byte_length, \
272
+ napi_buffer##_unique_ptr, function_name); \
434
273
  /* Copy */ \
435
274
  cobhan_buffer = copy_nbuffer_to_cbuffer(env, napi_buffer, cobhan_buffer); \
436
275
  if (unlikely(cobhan_buffer == nullptr)) { \
437
- log_error_and_throw(env, function_name, \
276
+ log_error_and_throw(function_name, \
438
277
  "Failed to copy " #napi_buffer " to cobhan buffer"); \
439
278
  } \
440
279
  bytes_copied = napi_buffer##_byte_length; \
441
280
  } while (0);
442
281
 
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
-
467
282
  #endif
package/src/logging.cc CHANGED
@@ -1,2 +1,2 @@
1
1
  #include <cstdint>
2
- int32_t verbose_flag = 0;
2
+ __attribute__((used)) int32_t verbose_flag = 0;
package/src/logging.h CHANGED
@@ -2,11 +2,22 @@
2
2
  #define LOGGING_H
3
3
  #include "hints.h"
4
4
  #include <cstdint>
5
- #include <string>
5
+ #include <iomanip>
6
6
  #include <iostream>
7
+ #include <sstream>
8
+ #include <string>
7
9
 
8
10
  extern int32_t verbose_flag;
9
11
 
12
+ __attribute__((always_inline)) inline void debug_log(const char *function_name,
13
+ const char *message) {
14
+ if (unlikely(verbose_flag)) {
15
+ std::cerr << "asherah-node: [DEBUG] " << function_name << ": " << message
16
+ << std::endl
17
+ << std::flush;
18
+ }
19
+ }
20
+
10
21
  __attribute__((always_inline)) inline void debug_log(const char *function_name,
11
22
  std::string message) {
12
23
  if (unlikely(verbose_flag)) {
@@ -27,6 +38,15 @@ debug_log_alloca(const char *function_name, const char *variable_name,
27
38
  }
28
39
  }
29
40
 
41
+ __attribute__((always_inline)) inline void error_log(const char *function_name,
42
+ const char *message) {
43
+ if (unlikely(verbose_flag)) {
44
+ std::cerr << "asherah-node: [ERROR] " << function_name << ": " << message
45
+ << std::endl
46
+ << std::flush;
47
+ }
48
+ }
49
+
30
50
  __attribute__((always_inline)) inline void error_log(const char *function_name,
31
51
  std::string message) {
32
52
  if (unlikely(verbose_flag)) {
@@ -36,4 +56,16 @@ __attribute__((always_inline)) inline void error_log(const char *function_name,
36
56
  }
37
57
  }
38
58
 
59
+ __attribute__((always_inline)) inline std::string format_ptr(char *ptr) {
60
+ std::ostringstream ss;
61
+ ss << "0x" << std::hex << (intptr_t)ptr;
62
+ return ss.str();
63
+ }
64
+
65
+ __attribute__((always_inline, noreturn)) inline void
66
+ log_error_and_throw(const char *function_name, std::string error_msg) {
67
+ error_log(function_name, error_msg);
68
+ throw new std::runtime_error(function_name + (": " + error_msg));
69
+ }
70
+
39
71
  #endif