asherah 1.3.0 → 1.3.2

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/.asherah-version CHANGED
@@ -1 +1 @@
1
- ASHERAH_VERSION=v0.4.25
1
+ ASHERAH_VERSION=v0.4.26
package/binding.gyp CHANGED
@@ -1,13 +1,23 @@
1
1
  {
2
2
  'targets': [
3
- {
3
+ {
4
4
  'target_name': 'napiasherah',
5
5
  'include_dirs': ["<!(node -p \"require('node-addon-api').include_dir\")"],
6
+ "cflags": ["-fexceptions", "-g"],
7
+ "cflags_cc": ["-fexceptions", "-g"],
8
+ "cflags!": [ "-fno-exceptions"],
9
+ "cflags_cc!": [ "-fno-exceptions" ],
10
+ 'xcode_settings': {
11
+ 'OTHER_CFLAGS': [
12
+ '-fexceptions',
13
+ '-g'
14
+ ],
15
+ },
16
+ 'defines': [ 'NAPI_CPP_EXCEPTIONS', 'NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS' ],
6
17
  'sources': [
7
18
  'lib/libasherah.h',
8
19
  'src/napiasherah.cc'
9
20
  ],
10
- 'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
11
21
  'libraries': [ '../lib/libasherah.a' ]
12
22
  }
13
23
  ]
package/dist/asherah.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="ref-napi" />
3
2
  export type AsherahConfig = {
4
3
  /** The name of this service (Required) */
5
4
  ServiceName: string;
@@ -46,4 +45,5 @@ export declare function decrypt(partitionId: string, dataRowRecord: string): Buf
46
45
  export declare function encrypt(partitionId: string, data: Buffer): string;
47
46
  export declare function decrypt_string(partitionId: string, dataRowRecord: string): string;
48
47
  export declare function encrypt_string(partitionId: string, data: string): string;
49
- export declare function set_max_stack_alloc_item_size(max_item_size: number): any;
48
+ export declare function set_max_stack_alloc_item_size(max_item_size: number): void;
49
+ export declare function set_safety_padding_overhead(safety_padding_overhead: number): void;
package/dist/asherah.js CHANGED
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.set_max_stack_alloc_item_size = exports.encrypt_string = exports.decrypt_string = exports.encrypt = exports.decrypt = exports.shutdown = exports.setup = void 0;
3
+ exports.set_safety_padding_overhead = exports.set_max_stack_alloc_item_size = exports.encrypt_string = exports.decrypt_string = exports.encrypt = exports.decrypt = exports.shutdown = exports.setup = void 0;
4
4
  const napi_asherah = require('../build/Release/napiasherah.node');
5
5
  function setup(config) {
6
6
  const configStr = JSON.stringify(config);
7
- napi_asherah.Napi_SetupJson(configStr, config.ProductID.length, config.ServiceName.length, configStr.length);
7
+ napi_asherah.Napi_SetupJson(configStr, config.ProductID.length, config.ServiceName.length, config.Verbose);
8
8
  }
9
9
  exports.setup = setup;
10
10
  function shutdown() {
@@ -31,3 +31,7 @@ function set_max_stack_alloc_item_size(max_item_size) {
31
31
  return napi_asherah.Napi_SetMaxStackAllocItemSize(max_item_size);
32
32
  }
33
33
  exports.set_max_stack_alloc_item_size = set_max_stack_alloc_item_size;
34
+ function set_safety_padding_overhead(safety_padding_overhead) {
35
+ return napi_asherah.Napi_SetSafetyPaddingOverhead(safety_padding_overhead);
36
+ }
37
+ exports.set_safety_padding_overhead = set_safety_padding_overhead;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asherah",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Asherah envelope encryption and key rotation library",
5
5
  "main": "dist/asherah.js",
6
6
  "repository": {
@@ -10,7 +10,7 @@
10
10
  "scripts": {
11
11
  "build": "npx tsc",
12
12
  "preinstall": "scripts/download-libraries.sh",
13
- "install": "node-gyp rebuild",
13
+ "install": "CFLAGS=-fexceptions CXXFLAGS=-fexceptions node-gyp rebuild",
14
14
  "test:mocha": "mocha",
15
15
  "test": "nyc npm run test:mocha",
16
16
  "posttest": "npm run lint",
@@ -34,7 +34,6 @@
34
34
  "@types/chai": "^4.3.0",
35
35
  "@types/mocha": "^9.1.0",
36
36
  "@types/node": "^17.0.22",
37
- "@types/ref-napi": "^3.0.4",
38
37
  "@typescript-eslint/eslint-plugin": "^5.16.0",
39
38
  "@typescript-eslint/parser": "^5.16.0",
40
39
  "benchmark": "^2.1.4",
@@ -1,444 +1,825 @@
1
- #include <napi.h>
2
1
  #include "../lib/libasherah.h"
2
+ #include <iostream>
3
+ #include <napi.h>
4
+
5
+ #define unlikely(expr) __builtin_expect(!!(expr), 0)
6
+ #define likely(expr) __builtin_expect(!!(expr), 1)
7
+
8
+ const size_t cobhan_header_size = 64 / 8;
9
+ const size_t est_encryption_overhead = 48;
10
+ const size_t est_envelope_overhead = 185;
11
+ const double base64_overhead = 1.34;
12
+
13
+ size_t est_intermediate_key_overhead = 0;
14
+ size_t safety_padding = 0;
15
+ size_t max_stack_alloc_size = 2048;
16
+
17
+ const char *setupjson_failed_message = "SetupJson failed: ";
18
+ const char *decrypt_failed_message = "Decrypt failed: ";
19
+ const char *encrypt_failed_message = "Encrypt failed: ";
20
+
21
+ int32_t setup_state = 0;
22
+ int32_t verbose_flag = 0;
23
+
24
+ __attribute__((always_inline)) inline void debug_log(std::string message) {
25
+ if (unlikely(verbose_flag)) {
26
+ std::cerr << "asherah-node:" << message << std::endl << std::flush;
27
+ }
28
+ }
29
+
30
+ __attribute__((always_inline)) inline void debug_log_alloca(size_t length) {
31
+ if (unlikely(verbose_flag)) {
32
+ std::cerr << "asherah-node:" << "Calling alloca(" << length << ") (stack)" << std::endl << std::flush;
33
+ }
34
+ }
35
+
36
+ __attribute__((always_inline)) inline void error_log(std::string message) {
37
+ if (unlikely(verbose_flag)) {
38
+ std::cerr << "asherah-node:" << message << std::endl << std::flush;
39
+ }
40
+ }
3
41
 
4
- const size_t EstimatedEncryptionOverhead = 48;
5
- const size_t EstimatedEnvelopeOverhead = 185;
6
- const double Base64Overhead = 1.34;
7
- size_t EstimatedIntermediateKeyOverhead = 0;
8
- size_t SafetyPaddingOverhead = 0;
9
- const size_t header_size = 64 / 8;
10
- size_t max_stack_alloc_size = 4096;
11
- const char* SetupJsonFailedMessage = "SetupJson failed: ";
12
- const char* DecryptFailedMessage = "Decrypt failed: ";
13
- const char* EncryptFailedMessage = "Encrypt failed: ";
14
-
15
- void finalize_cbuffer(napi_env env, void* finalize_data) {
16
- char* buffer = ((char*) finalize_data) - header_size;
17
- delete[] buffer;
42
+ std::string napi_status_to_string(napi_status status) {
43
+ switch (status) {
44
+ case napi_ok:
45
+ return "napi_ok";
46
+ case napi_invalid_arg:
47
+ return "napi_invalid_arg";
48
+ case napi_object_expected:
49
+ return "napi_object_expected";
50
+ case napi_string_expected:
51
+ return "napi_string_expected";
52
+ case napi_name_expected:
53
+ return "napi_name_expected";
54
+ case napi_function_expected:
55
+ return "napi_function_expected";
56
+ case napi_number_expected:
57
+ return "napi_number_expected";
58
+ case napi_boolean_expected:
59
+ return "napi_boolean_expected";
60
+ case napi_array_expected:
61
+ return "napi_array_expected";
62
+ case napi_generic_failure:
63
+ return "napi_generic_failure";
64
+ case napi_pending_exception:
65
+ return "napi_pending_exception";
66
+ case napi_cancelled:
67
+ return "napi_cancelled";
68
+ case napi_escape_called_twice:
69
+ return "napi_escape_called_twice";
70
+ case napi_handle_scope_mismatch:
71
+ return "napi_handle_scope_mismatch";
72
+ case napi_callback_scope_mismatch:
73
+ return "napi_callback_scope_mismatch";
74
+ case napi_queue_full:
75
+ return "napi_queue_full";
76
+ case napi_closing:
77
+ return "napi_closing";
78
+ case napi_bigint_expected:
79
+ return "napi_bigint_expected";
80
+ case napi_date_expected:
81
+ return "napi_date_expected";
82
+ case napi_arraybuffer_expected:
83
+ return "napi_arraybuffer_expected";
84
+ case napi_detachable_arraybuffer_expected:
85
+ return "napi_detachable_arraybuffer_expected";
86
+ case napi_would_deadlock:
87
+ return "napi_would_deadlock";
88
+ default:
89
+ return "Unknown napi_status";
90
+ }
91
+ }
92
+
93
+ __attribute__((always_inline)) inline Napi::Value
94
+ LogErrorAndThrow(Napi::Env &env, std::string error_msg) {
95
+ error_log(error_msg);
96
+ Napi::Error::New(env, error_msg).ThrowAsJavaScriptException();
97
+ return env.Null();
18
98
  }
19
99
 
20
- __attribute__((always_inline)) inline size_t estimate_buffer(size_t dataLen, size_t partitionLen) {
21
- double estimatedDataLen = double(dataLen + EstimatedEncryptionOverhead) * Base64Overhead;
22
- return size_t(EstimatedEnvelopeOverhead + EstimatedIntermediateKeyOverhead + partitionLen + estimatedDataLen + SafetyPaddingOverhead);
100
+ __attribute__((always_inline)) inline size_t
101
+ cobhan_buffer_size(size_t dataLen) {
102
+ return dataLen + cobhan_header_size + safety_padding +
103
+ 1; // Add one for possible NULL delimiter due to Node string functions
23
104
  }
24
- __attribute__((always_inline)) inline char* configure_cbuffer(char *buffer, size_t length) {
25
- *((int32_t*)buffer) = length;
26
- *((int32_t*)(buffer+sizeof(int32_t))) = 0;
27
- return buffer;
105
+
106
+ __attribute__((always_inline)) inline size_t
107
+ estimate_asherah_output_size(size_t dataLen, size_t partitionLen) {
108
+ double estimatedDataLen =
109
+ double(dataLen + est_encryption_overhead) * base64_overhead;
110
+ if(unlikely(verbose_flag)) {
111
+ std::string log_msg = "estimate_asherah_output_size(" + std::to_string(dataLen) + ", " + std::to_string(partitionLen) + ") estimatedDataLen: " + std::to_string(estimatedDataLen) + " base64_overhead: " + std::to_string(base64_overhead) + " est_encryption_overhead: " + std::to_string(est_encryption_overhead);
112
+ debug_log(log_msg);
113
+ }
114
+ size_t asherah_output_size = size_t(est_envelope_overhead + est_intermediate_key_overhead +
115
+ partitionLen + estimatedDataLen + safety_padding);
116
+ if(unlikely(verbose_flag)) {
117
+ std::string log_msg = "estimate_asherah_output_size(" + std::to_string(dataLen) + ", " + std::to_string(partitionLen) + ") estimatedDataLen: " + std::to_string(estimatedDataLen) + " asherah_output_size: " + std::to_string(asherah_output_size);
118
+ debug_log(log_msg);
119
+ }
120
+ return asherah_output_size;
28
121
  }
29
122
 
30
- __attribute__((always_inline)) inline char* allocate_cbuffer(size_t length) {
31
- char *cobhanBuffer = new char[length + header_size + SafetyPaddingOverhead];
32
- return configure_cbuffer(cobhanBuffer, length);
123
+ __attribute__((always_inline)) inline void configure_cbuffer(char *buffer,
124
+ size_t length) {
125
+ *((int32_t *)buffer) = length;
126
+ // Reserved for future use
127
+ *((int32_t *)(buffer + sizeof(int32_t))) = 0;
33
128
  }
34
129
 
35
- __attribute__((always_inline)) inline char* nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &buffer) {
36
- size_t bufferLength = buffer.ByteLength();
37
- char *cobhanBuffer = new char[bufferLength + header_size + SafetyPaddingOverhead];
38
- memcpy(cobhanBuffer + header_size, buffer.Data(), bufferLength);
39
- return configure_cbuffer(cobhanBuffer, bufferLength);
130
+ __attribute__((always_inline)) inline std::unique_ptr<char[]>
131
+ allocate_cbuffer(size_t length) {
132
+ size_t cobhanBufferSize = cobhan_buffer_size(length);
133
+ if (unlikely(verbose_flag)) {
134
+ std::string log_msg =
135
+ "allocate_cbuffer(" + std::to_string(length) +
136
+ ") (heap) cobhanBufferSize: " + std::to_string(cobhanBufferSize);
137
+ debug_log(log_msg);
138
+ }
139
+
140
+ char *cobhanBuffer = new (std::nothrow) char[cobhanBufferSize];
141
+ if (unlikely(cobhanBuffer == nullptr)) {
142
+ std::string error_msg = "allocate_cbuffer: new[" +
143
+ std::to_string(cobhanBufferSize) + " returned null";
144
+ error_log(error_msg);
145
+ return nullptr;
146
+ }
147
+ std::unique_ptr<char[]> cobhanBufferPtr(cobhanBuffer);
148
+ configure_cbuffer(cobhanBuffer, length + safety_padding);
149
+ return cobhanBufferPtr;
40
150
  }
41
151
 
42
- __attribute__((always_inline)) inline Napi::Value cbuffer_to_nstring(Napi::Env &env, char *cobhanBuffer) {
152
+ __attribute__((always_inline)) inline Napi::Value
153
+ cbuffer_to_nstring(Napi::Env &env, char *cobhanBuffer) {
43
154
  napi_value output;
44
- //Using C function because it allows length delimited input
45
- napi_status status = napi_create_string_utf8(env, ((const char*) cobhanBuffer) + header_size, *((int*) cobhanBuffer), &output);
46
- if(status != napi_ok) {
47
- Napi::Error::New(env, "cbuffer_to_nstring failed")
48
- .ThrowAsJavaScriptException();
49
- return env.Null();
155
+
156
+ // Using C function because it allows length delimited input
157
+ napi_status status = napi_create_string_utf8(
158
+ env, ((const char *)cobhanBuffer) + cobhan_header_size,
159
+ *((int *)cobhanBuffer), &output);
160
+
161
+ if (unlikely(status != napi_ok)) {
162
+ return LogErrorAndThrow(
163
+ env, "cbuffer_to_nstring: napi_create_string_utf8 failed: " +
164
+ napi_status_to_string(status));
50
165
  }
166
+
51
167
  return Napi::String(env, output);
52
168
  }
53
169
 
54
- __attribute__((always_inline)) inline size_t nstring_utf8_length(Napi::Env &env, Napi::String &str) {
170
+ __attribute__((always_inline)) inline size_t
171
+ nstring_utf8_length(Napi::Env &env, Napi::String &str) {
55
172
  napi_status status;
56
173
  size_t utf8_length;
57
174
 
58
- status = napi_get_value_string_utf8(env, str, NULL, 0, &utf8_length);
59
- if(status != napi_ok) {
60
- Napi::Error::New(env, "nstring_to_cbuffer: Napi utf8 string conversion failure (length check): " + std::to_string(status))
61
- .ThrowAsJavaScriptException();
175
+ status = napi_get_value_string_utf8(env, str, nullptr, 0, &utf8_length);
176
+ if (unlikely(status != napi_ok)) {
177
+ LogErrorAndThrow(
178
+ env,
179
+ "nstring_utf8_length: napi_get_value_string_utf8 length check failed" +
180
+ napi_status_to_string(status));
62
181
  return (size_t)(-1);
63
182
  }
183
+
64
184
  return utf8_length;
65
185
  }
66
186
 
67
- __attribute__((always_inline)) inline char* copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str, size_t utf8_length, char *cbuffer, size_t *length = NULL) {
187
+ __attribute__((always_inline)) inline char *
188
+ copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str, size_t utf8_length,
189
+ char *cbuffer, size_t *length = nullptr) {
68
190
  napi_status status;
69
191
  size_t copied_bytes;
70
- status = napi_get_value_string_utf8(env, str, cbuffer + header_size, utf8_length + 1, &copied_bytes);
71
- if(status != napi_ok) {
72
- Napi::Error::New(env, "nstring_to_cbuffer: Napi utf8 string conversion failure: " + std::to_string(status))
73
- .ThrowAsJavaScriptException();
74
- return NULL;
192
+ status = napi_get_value_string_utf8(env, str, cbuffer + cobhan_header_size,
193
+ utf8_length + 1, &copied_bytes);
194
+ if (unlikely(status != napi_ok)) {
195
+ LogErrorAndThrow(env,
196
+ "copy_nstring_to_cbuffer: Napi utf8 string conversion "
197
+ "failure: " +
198
+ napi_status_to_string(status));
199
+ return nullptr;
75
200
  }
76
201
 
77
- if(copied_bytes != utf8_length) {
78
- Napi::Error::New(env, "nstring_to_cbuffer: Did not copy expected number of bytes " + std::to_string(utf8_length) + " copied " + std::to_string(copied_bytes))
79
- .ThrowAsJavaScriptException();
80
- return NULL;
202
+ if (unlikely(copied_bytes != utf8_length)) {
203
+ LogErrorAndThrow(env,
204
+ "copy_nstring_to_cbuffer: Did not copy expected number "
205
+ "of bytes " +
206
+ std::to_string(utf8_length) + " copied " +
207
+ std::to_string(copied_bytes));
208
+ return nullptr;
81
209
  }
82
210
 
83
- *((int*)cbuffer) = copied_bytes;
84
- *((int*)(cbuffer+sizeof(int32_t))) = 0;
211
+ *((int *)cbuffer) = copied_bytes;
212
+ *((int *)(cbuffer + sizeof(int32_t))) = 0;
85
213
 
86
- if(length != NULL)
214
+ if (length != nullptr)
87
215
  *length = copied_bytes;
88
216
  return cbuffer;
89
217
  }
90
218
 
91
- __attribute__((always_inline)) inline char* nstring_to_cbuffer(Napi::Env &env, Napi::String &str, size_t *length = NULL) {
92
- size_t utf8_length = nstring_utf8_length(env, str);
93
- if(utf8_length == (size_t)(-1)) {
94
- return NULL;
95
- }
219
+ __attribute__((always_inline)) inline Napi::Buffer<unsigned char>
220
+ cbuffer_to_nbuffer(Napi::Env &env, char *cobhanBuffer) {
221
+ return Napi::Buffer<unsigned char>::Copy(
222
+ env, ((unsigned char *)cobhanBuffer) + cobhan_header_size,
223
+ *((int *)cobhanBuffer));
224
+ }
96
225
 
97
- char *cobhanBuffer = new char[utf8_length + 1 + header_size + SafetyPaddingOverhead];
226
+ Napi::Value Napi_SetupJson(const Napi::CallbackInfo &info) {
227
+ Napi::Env env = info.Env();
98
228
 
99
- char *output = copy_nstring_to_cbuffer(env, str, utf8_length, cobhanBuffer, length);
100
- if(output == NULL) {
101
- delete[] cobhanBuffer;
229
+ if(unlikely(verbose_flag)) {
230
+ debug_log("SetupJson called");
102
231
  }
103
- return output;
104
- }
105
232
 
106
- Napi::Value Napi_SetupJson(const Napi::CallbackInfo& info) {
107
- Napi::Env env = info.Env();
233
+ if (unlikely(setup_state == 1)) {
234
+ return LogErrorAndThrow(env, setupjson_failed_message +
235
+ std::string("SetupJson called twice"));
236
+ }
108
237
 
109
- if (info.Length() < 3) {
110
- Napi::TypeError::New(env, "SetupJson: Wrong number of arguments")
111
- .ThrowAsJavaScriptException();
112
- return env.Null();
238
+ if (unlikely(info.Length() < 3)) {
239
+ return LogErrorAndThrow(env, "SetupJson: Wrong number of arguments");
113
240
  }
114
241
 
115
- if (!info[0].IsString() || !info[1].IsNumber() || !info[2].IsNumber()) {
116
- Napi::TypeError::New(env, "SetupJson: Wrong argument types")
117
- .ThrowAsJavaScriptException();
118
- return env.Null();
242
+ if (unlikely(!info[0].IsString() || !info[1].IsNumber() ||
243
+ !info[2].IsNumber() || !info[3].IsBoolean())) {
244
+ return LogErrorAndThrow(env, "SetupJson: Wrong argument types");
119
245
  }
120
246
 
247
+ Napi::Boolean verbose = info[3].As<Napi::Boolean>();
248
+ verbose.Value() ? verbose_flag = 1 : verbose_flag = 0;
249
+ debug_log("SetupJson: verbose_flag: " + std::to_string(verbose_flag) +
250
+ " verbose.Value(): " + std::to_string(verbose.Value()));
251
+
252
+ // Determine size
253
+ size_t config_utf8_length;
121
254
  Napi::String configJson = info[0].As<Napi::String>();
122
- char *configJsonCobhanBuffer = nstring_to_cbuffer(env, configJson);
123
- if (configJsonCobhanBuffer == NULL) {
124
- return env.Null();
255
+ config_utf8_length = nstring_utf8_length(env, configJson);
256
+ if (unlikely(config_utf8_length == (size_t)(-1))) {
257
+ return LogErrorAndThrow(
258
+ env, encrypt_failed_message +
259
+ std::string(" failed to get configJson utf8 length"));
260
+ }
261
+
262
+ // Allocate
263
+ char *configJsonCobhanBuffer;
264
+ std::unique_ptr<char[]> configJsonCobhanBufferPtr;
265
+ if (config_utf8_length < max_stack_alloc_size) {
266
+ size_t cobhan_buf_size = cobhan_buffer_size(config_utf8_length);
267
+ debug_log_alloca(cobhan_buf_size);
268
+ configJsonCobhanBuffer = (char *)alloca(cobhan_buf_size);
269
+ } else {
270
+ configJsonCobhanBufferPtr = allocate_cbuffer(config_utf8_length);
271
+ configJsonCobhanBuffer = configJsonCobhanBufferPtr.get();
272
+ }
273
+ if (unlikely(configJsonCobhanBuffer == nullptr)) {
274
+ return LogErrorAndThrow(
275
+ env, encrypt_failed_message +
276
+ std::string(" failed to allocate configJson cobhan buffer"));
277
+ }
278
+
279
+ // Copy
280
+ size_t config_copied_bytes;
281
+ configJsonCobhanBuffer =
282
+ copy_nstring_to_cbuffer(env, configJson, config_utf8_length,
283
+ configJsonCobhanBuffer, &config_copied_bytes);
284
+ if (unlikely(configJsonCobhanBuffer == nullptr)) {
285
+ return LogErrorAndThrow(
286
+ env, encrypt_failed_message +
287
+ std::string(" failed to copy configJson to cobhan buffer"));
125
288
  }
126
289
 
127
290
  Napi::Number productIdLength = info[1].As<Napi::Number>();
128
291
  Napi::Number serviceNameLength = info[2].As<Napi::Number>();
129
292
 
130
- EstimatedIntermediateKeyOverhead = productIdLength.Int32Value() + serviceNameLength.Int32Value();
293
+ est_intermediate_key_overhead =
294
+ productIdLength.Int32Value() + serviceNameLength.Int32Value();
131
295
 
132
- //extern GoInt32 SetupJson(void* configJson);
296
+ // extern GoInt32 SetupJson(void* configJson);
133
297
  GoInt32 result = SetupJson(configJsonCobhanBuffer);
134
- delete[] configJsonCobhanBuffer;
135
- if (result < 0) {
136
- Napi::TypeError::New(env, SetupJsonFailedMessage + std::to_string(result))
137
- .ThrowAsJavaScriptException();
298
+ if (unlikely(result < 0)) {
299
+ return LogErrorAndThrow(env,
300
+ setupjson_failed_message + std::to_string(result));
138
301
  }
302
+ setup_state = 1;
139
303
  return env.Null();
140
304
  }
141
305
 
142
- Napi::Value Napi_EncryptFromBufferToJson(const Napi::CallbackInfo& info) {
306
+ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
307
+ size_t data_bytes, char *partitionIdCobhanBuffer,
308
+ char *dataCobhanBuffer) {
309
+
310
+ size_t asherah_output_size =
311
+ estimate_asherah_output_size(data_bytes, partition_bytes);
312
+
313
+ if(unlikely(verbose_flag)) {
314
+ debug_log("encrypt_to_json asherah_output_size " +
315
+ std::to_string(asherah_output_size));
316
+ }
317
+
318
+ char *cobhanOutputBuffer;
319
+ std::unique_ptr<char[]> cobhanOutputBufferPtr;
320
+ if (asherah_output_size < max_stack_alloc_size) {
321
+ size_t cobhan_ouput_buffer_size = cobhan_buffer_size(asherah_output_size);
322
+ debug_log_alloca(cobhan_ouput_buffer_size);
323
+ cobhanOutputBuffer = (char *)alloca(cobhan_ouput_buffer_size);
324
+ configure_cbuffer(cobhanOutputBuffer, asherah_output_size + safety_padding);
325
+ } else {
326
+ cobhanOutputBufferPtr = allocate_cbuffer(asherah_output_size);
327
+ cobhanOutputBuffer = cobhanOutputBufferPtr.get();
328
+ }
329
+ if (unlikely(cobhanOutputBuffer == nullptr)) {
330
+ return LogErrorAndThrow(
331
+ env, encrypt_failed_message +
332
+ std::string(" failed to allocate cobhan output buffer"));
333
+ }
334
+
335
+ // extern GoInt32 EncryptToJson(void* partitionIdPtr, void* dataPtr, void*
336
+ // jsonPtr);
337
+ GoInt32 result = EncryptToJson(partitionIdCobhanBuffer, dataCobhanBuffer,
338
+ cobhanOutputBuffer);
339
+ if (unlikely(result < 0)) {
340
+ return LogErrorAndThrow(env,
341
+ encrypt_failed_message + std::to_string(result));
342
+ }
343
+
344
+ Napi::Value output = cbuffer_to_nstring(env, cobhanOutputBuffer);
345
+ return output;
346
+ }
347
+
348
+ Napi::Value Napi_EncryptFromBufferToJson(const Napi::CallbackInfo &info) {
143
349
  Napi::Env env = info.Env();
144
350
 
145
- if (info.Length() < 2) {
146
- Napi::TypeError::New(env, "EncryptFromBufferToJson: Wrong number of arguments")
147
- .ThrowAsJavaScriptException();
148
- return env.Null();
351
+ if(unlikely(verbose_flag)) {
352
+ debug_log("EncryptFromBufferToJson called");
149
353
  }
150
354
 
151
- if (!info[0].IsString() || !info[1].IsBuffer()) {
152
- Napi::TypeError::New(env, "EncryptFromBufferToJson: Wrong argument types")
153
- .ThrowAsJavaScriptException();
154
- return env.Null();
355
+ if (unlikely(setup_state == 0)) {
356
+ return LogErrorAndThrow(env, encrypt_failed_message +
357
+ std::string("SetupJson not called"));
155
358
  }
156
359
 
157
- size_t partition_utf8_length, partition_copied_bytes;
360
+ if (unlikely(info.Length() < 2)) {
361
+ return LogErrorAndThrow(
362
+ env, "EncryptFromBufferToJson: Wrong number of arguments");
363
+ }
364
+
365
+ if (unlikely(!info[0].IsString() || !info[1].IsBuffer())) {
366
+ return LogErrorAndThrow(env,
367
+ "EncryptFromBufferToJson: Wrong argument types");
368
+ }
369
+
370
+ // Determine size
371
+ size_t partition_utf8_length;
158
372
  Napi::String partitionId = info[0].As<Napi::String>();
159
373
  partition_utf8_length = nstring_utf8_length(env, partitionId);
160
- if(partition_utf8_length == (size_t)(-1)) {
161
- return env.Null();
374
+ if (unlikely(partition_utf8_length == (size_t)(-1))) {
375
+ return LogErrorAndThrow(
376
+ env, encrypt_failed_message +
377
+ std::string(" failed to get partitionId utf8 length"));
162
378
  }
379
+
380
+ // Allocate
163
381
  char *partitionIdCobhanBuffer;
382
+ std::unique_ptr<char[]> partitionIdCobhanBufferPtr;
164
383
  if (partition_utf8_length < max_stack_alloc_size) {
165
- partitionIdCobhanBuffer = (char*)alloca(partition_utf8_length + 1 + header_size + SafetyPaddingOverhead);
384
+ size_t cobhan_buf_size = cobhan_buffer_size(partition_utf8_length);
385
+ debug_log_alloca(cobhan_buf_size);
386
+ partitionIdCobhanBuffer = (char *)alloca(cobhan_buf_size);
166
387
  } else {
167
- partitionIdCobhanBuffer = new char[partition_utf8_length + 1 + header_size + SafetyPaddingOverhead];
388
+ partitionIdCobhanBufferPtr = allocate_cbuffer(partition_utf8_length);
389
+ partitionIdCobhanBuffer = partitionIdCobhanBufferPtr.get();
390
+ }
391
+ if (unlikely(partitionIdCobhanBuffer == nullptr)) {
392
+ return LogErrorAndThrow(
393
+ env, encrypt_failed_message +
394
+ std::string(" failed to allocate partitionId cobhan buffer"));
395
+ }
396
+
397
+ // Copy
398
+ size_t partition_copied_bytes;
399
+ partitionIdCobhanBuffer =
400
+ copy_nstring_to_cbuffer(env, partitionId, partition_utf8_length,
401
+ partitionIdCobhanBuffer, &partition_copied_bytes);
402
+ if (unlikely(partitionIdCobhanBuffer == nullptr)) {
403
+ return LogErrorAndThrow(
404
+ env, encrypt_failed_message +
405
+ std::string(" failed to copy partitionId to cobhan buffer"));
406
+ }
407
+
408
+ // Determine size
409
+ Napi::Buffer<unsigned char> inputNapiBuffer =
410
+ info[1].As<Napi::Buffer<unsigned char>>();
411
+ size_t input_byte_length = inputNapiBuffer.ByteLength();
412
+
413
+ // Allocate
414
+ char *inputBuffer;
415
+ std::unique_ptr<char[]> inputBufferPtr;
416
+ if (input_byte_length < max_stack_alloc_size) {
417
+ size_t cobhan_buf_size = cobhan_buffer_size(input_byte_length);
418
+ debug_log_alloca(cobhan_buf_size);
419
+ inputBuffer = (char *)alloca(cobhan_buf_size);
420
+ } else {
421
+ inputBufferPtr = allocate_cbuffer(input_byte_length);
422
+ inputBuffer = inputBufferPtr.get();
168
423
  }
169
- partitionIdCobhanBuffer = copy_nstring_to_cbuffer(env, partitionId, partition_utf8_length, partitionIdCobhanBuffer, &partition_copied_bytes);
170
- if (partitionIdCobhanBuffer == NULL) {
171
- if (partition_utf8_length >= max_stack_alloc_size)
172
- delete[] partitionIdCobhanBuffer;
173
- return env.Null();
424
+ if (unlikely(inputBuffer == nullptr)) {
425
+ return LogErrorAndThrow(
426
+ env,
427
+ encrypt_failed_message +
428
+ std::string(" failed to allocate cobhan buffer for input buffer"));
174
429
  }
175
430
 
176
- Napi::Buffer<unsigned char> data = info[1].As<Napi::Buffer<unsigned char>>();
177
- char *dataCobhanBuffer = nbuffer_to_cbuffer(env, data);
178
- if (dataCobhanBuffer == NULL) {
179
- if (partition_utf8_length >= max_stack_alloc_size)
180
- delete[] partitionIdCobhanBuffer;
181
- return env.Null();
182
- }
431
+ // Copy
432
+ memcpy(inputBuffer + cobhan_header_size, inputNapiBuffer.Data(),
433
+ input_byte_length);
434
+ configure_cbuffer(inputBuffer, input_byte_length);
183
435
 
184
- size_t bufferSize = estimate_buffer(partition_copied_bytes, data.ByteLength());
436
+ return encrypt_to_json(env, partition_copied_bytes, input_byte_length,
437
+ partitionIdCobhanBuffer, inputBuffer);
438
+ }
185
439
 
186
- char *cobhanOutputBuffer;
187
- if (bufferSize < max_stack_alloc_size) {
188
- cobhanOutputBuffer = configure_cbuffer((char*)alloca(bufferSize + header_size + SafetyPaddingOverhead), bufferSize);
189
- } else {
190
- cobhanOutputBuffer = allocate_cbuffer(bufferSize);
191
- }
440
+ Napi::Value Napi_EncryptFromStringToJson(const Napi::CallbackInfo &info) {
441
+ Napi::Env env = info.Env();
192
442
 
193
- //extern GoInt32 EncryptToJson(void* partitionIdPtr, void* dataPtr, void* jsonPtr);
194
- GoInt32 result = EncryptToJson(partitionIdCobhanBuffer, dataCobhanBuffer, cobhanOutputBuffer);
195
- if (partition_utf8_length >= max_stack_alloc_size)
196
- delete[] partitionIdCobhanBuffer;
197
- delete[] dataCobhanBuffer;
198
- if (result < 0) {
199
- if (bufferSize >= max_stack_alloc_size)
200
- delete[] cobhanOutputBuffer;
201
- Napi::TypeError::New(env, EncryptFailedMessage + std::to_string(result))
202
- .ThrowAsJavaScriptException();
203
- return env.Null();
443
+ if(unlikely(verbose_flag)) {
444
+ debug_log("EncryptFromStringToJson called");
204
445
  }
205
446
 
206
- Napi::Value output = cbuffer_to_nstring(env, cobhanOutputBuffer);
207
- if (bufferSize >= max_stack_alloc_size)
208
- delete[] cobhanOutputBuffer;
209
- return output;
210
- }
211
-
212
- Napi::Value Napi_EncryptFromStringToJson(const Napi::CallbackInfo& info) {
213
- Napi::Env env = info.Env();
447
+ if (unlikely(setup_state == 0)) {
448
+ return LogErrorAndThrow(env, encrypt_failed_message +
449
+ std::string("SetupJson not called"));
450
+ }
214
451
 
215
- if (info.Length() < 2) {
216
- Napi::TypeError::New(env, "EncryptFromStringToJson: Wrong number of arguments")
217
- .ThrowAsJavaScriptException();
218
- return env.Null();
452
+ if (unlikely(info.Length() < 2)) {
453
+ return LogErrorAndThrow(
454
+ env, "EncryptFromStringToJson: Wrong number of arguments");
219
455
  }
220
456
 
221
- if (!info[0].IsString() || !info[1].IsString()) {
222
- Napi::TypeError::New(env, "EncryptFromStringToJson: Wrong argument types")
223
- .ThrowAsJavaScriptException();
224
- return env.Null();
457
+ if (unlikely(!info[0].IsString() || !info[1].IsString())) {
458
+ return LogErrorAndThrow(env,
459
+ "EncryptFromStringToJson: Wrong argument types");
225
460
  }
226
461
 
227
- size_t partition_utf8_length, partition_copied_bytes;
462
+ // Determine size
463
+ size_t partition_utf8_length;
228
464
  Napi::String partitionId = info[0].As<Napi::String>();
229
465
  partition_utf8_length = nstring_utf8_length(env, partitionId);
230
- if(partition_utf8_length == (size_t)(-1)) {
231
- return env.Null();
466
+ if (unlikely(partition_utf8_length == (size_t)(-1))) {
467
+ return LogErrorAndThrow(
468
+ env, encrypt_failed_message +
469
+ std::string(" failed to get partitionId utf8 length"));
232
470
  }
471
+
472
+ // Allocate
233
473
  char *partitionIdCobhanBuffer;
474
+ std::unique_ptr<char[]> partitionIdCobhanBufferPtr;
234
475
  if (partition_utf8_length < max_stack_alloc_size) {
235
- partitionIdCobhanBuffer = (char*)alloca(partition_utf8_length + 1 + header_size + SafetyPaddingOverhead);
476
+ size_t cobhan_buf_size = cobhan_buffer_size(partition_utf8_length);
477
+ debug_log_alloca(cobhan_buf_size);
478
+ partitionIdCobhanBuffer = (char *)alloca(cobhan_buf_size);
236
479
  } else {
237
- partitionIdCobhanBuffer = new char[partition_utf8_length + 1 + header_size + SafetyPaddingOverhead];
480
+ partitionIdCobhanBufferPtr = allocate_cbuffer(partition_utf8_length);
481
+ partitionIdCobhanBuffer = partitionIdCobhanBufferPtr.get();
238
482
  }
239
- partitionIdCobhanBuffer = copy_nstring_to_cbuffer(env, partitionId, partition_utf8_length, partitionIdCobhanBuffer, &partition_copied_bytes);
240
- if (partitionIdCobhanBuffer == NULL) {
241
- if (partition_utf8_length >= max_stack_alloc_size)
242
- delete[] partitionIdCobhanBuffer;
243
- return env.Null();
483
+ if (unlikely(partitionIdCobhanBuffer == nullptr)) {
484
+ return LogErrorAndThrow(
485
+ env, encrypt_failed_message +
486
+ std::string(" failed to allocate partitionId cobhan buffer"));
244
487
  }
245
488
 
246
- size_t input_utf8_length;
247
- Napi::String input = info[1].As<Napi::String>();
248
- char *inputCobhanBuffer = nstring_to_cbuffer(env, input, &input_utf8_length);
249
- if (inputCobhanBuffer == NULL) {
250
- if (partition_utf8_length >= max_stack_alloc_size)
251
- delete[] partitionIdCobhanBuffer;
252
- return env.Null();
489
+ // Copy
490
+ size_t partition_copied_bytes;
491
+ partitionIdCobhanBuffer =
492
+ copy_nstring_to_cbuffer(env, partitionId, partition_utf8_length,
493
+ partitionIdCobhanBuffer, &partition_copied_bytes);
494
+ if (unlikely(partitionIdCobhanBuffer == nullptr)) {
495
+ return LogErrorAndThrow(
496
+ env, encrypt_failed_message +
497
+ std::string(" failed to copy partitionId to cobhan buffer"));
253
498
  }
254
499
 
255
- //Call estimate_buffer to determine Cobhan output buffer length
256
- size_t bufferSize = estimate_buffer(partition_utf8_length, input_utf8_length);
257
-
258
- char *cobhanOutputBuffer;
259
- if (bufferSize < max_stack_alloc_size) {
260
- cobhanOutputBuffer = configure_cbuffer((char*)alloca(bufferSize + header_size + SafetyPaddingOverhead), bufferSize);
500
+ // Determine size
501
+ size_t input_utf8_length;
502
+ Napi::String input = info[1].As<Napi::String>();
503
+ input_utf8_length = nstring_utf8_length(env, input);
504
+ if (unlikely(input_utf8_length == (size_t)(-1))) {
505
+ return LogErrorAndThrow(
506
+ env, encrypt_failed_message +
507
+ std::string(" failed to get input utf8 length"));
508
+ }
509
+
510
+ // Allocate
511
+ char *inputCobhanBuffer;
512
+ std::unique_ptr<char[]> inputCobhanBufferPtr;
513
+ if (input_utf8_length < max_stack_alloc_size) {
514
+ size_t cobhan_buf_size = cobhan_buffer_size(input_utf8_length);
515
+ debug_log_alloca(cobhan_buf_size);
516
+ inputCobhanBuffer = (char *)alloca(cobhan_buf_size);
261
517
  } else {
262
- cobhanOutputBuffer = allocate_cbuffer(bufferSize);
518
+ inputCobhanBufferPtr = allocate_cbuffer(input_utf8_length);
519
+ inputCobhanBuffer = inputCobhanBufferPtr.get();
520
+ }
521
+ if (unlikely(inputCobhanBuffer == nullptr)) {
522
+ return LogErrorAndThrow(
523
+ env, encrypt_failed_message +
524
+ std::string(" failed to allocate input cobhan buffer"));
263
525
  }
264
526
 
265
- //extern GoInt32 EncryptToJson(void* partitionIdPtr, void* dataPtr, void* jsonPtr);
266
- GoInt32 result = EncryptToJson(partitionIdCobhanBuffer, inputCobhanBuffer, cobhanOutputBuffer);
267
- if (partition_utf8_length >= max_stack_alloc_size)
268
- delete[] partitionIdCobhanBuffer;
269
- delete[] inputCobhanBuffer;
270
- if (result < 0) {
271
- if (bufferSize >= max_stack_alloc_size)
272
- delete[] cobhanOutputBuffer;
273
- Napi::TypeError::New(env, EncryptFailedMessage + std::to_string(result))
274
- .ThrowAsJavaScriptException();
275
- return env.Null();
527
+ // Copy
528
+ size_t input_copied_bytes;
529
+ inputCobhanBuffer = copy_nstring_to_cbuffer(
530
+ env, input, input_utf8_length, inputCobhanBuffer, &input_copied_bytes);
531
+ if (unlikely(inputCobhanBuffer == nullptr)) {
532
+ return LogErrorAndThrow(
533
+ env, encrypt_failed_message +
534
+ std::string(" failed to copy input to cobhan buffer"));
276
535
  }
277
536
 
278
- Napi::Value output = cbuffer_to_nstring(env, cobhanOutputBuffer);
279
- if (bufferSize >= max_stack_alloc_size)
280
- delete[] cobhanOutputBuffer;
281
- return output;
537
+ return encrypt_to_json(env, partition_copied_bytes, input_utf8_length,
538
+ partitionIdCobhanBuffer, inputCobhanBuffer);
282
539
  }
283
540
 
284
- Napi::Value Napi_DecryptFromJsonToBuffer(const Napi::CallbackInfo& info) {
541
+ Napi::Value Napi_DecryptFromJsonToBuffer(const Napi::CallbackInfo &info) {
285
542
  Napi::Env env = info.Env();
286
543
 
287
- if (info.Length() < 2) {
288
- Napi::TypeError::New(env, "DecryptFromJsonToBuffer: Wrong number of arguments")
289
- .ThrowAsJavaScriptException();
290
- return env.Null();
544
+ if(unlikely(verbose_flag)) {
545
+ debug_log("DecryptFromJsonToBuffer called");
546
+ }
547
+
548
+ if (unlikely(setup_state == 0)) {
549
+ return LogErrorAndThrow(env, decrypt_failed_message +
550
+ std::string("SetupJson not called"));
291
551
  }
292
552
 
293
- if (!info[0].IsString() || !info[1].IsString()) {
294
- Napi::TypeError::New(env, "DecryptFromJsonToBuffer: Wrong argument types")
295
- .ThrowAsJavaScriptException();
296
- return env.Null();
553
+ if (unlikely(info.Length() < 2)) {
554
+ return LogErrorAndThrow(
555
+ env, "DecryptFromJsonToBuffer: Wrong number of arguments");
297
556
  }
298
557
 
558
+ if (unlikely(!info[0].IsString() || !info[1].IsString())) {
559
+ return LogErrorAndThrow(env,
560
+ "DecryptFromJsonToBuffer: Wrong argument types");
561
+ }
562
+
563
+ // Determine size
299
564
  size_t partition_utf8_length, partition_copied_bytes;
300
565
  Napi::String partitionId = info[0].As<Napi::String>();
301
566
  partition_utf8_length = nstring_utf8_length(env, partitionId);
302
- if(partition_utf8_length == (size_t)(-1)) {
303
- return env.Null();
567
+ if (unlikely(partition_utf8_length == (size_t)(-1))) {
568
+ return LogErrorAndThrow(
569
+ env, decrypt_failed_message +
570
+ std::string(" failed to get partitionId utf8 length"));
304
571
  }
572
+
573
+ // Allocate
305
574
  char *partitionIdCobhanBuffer;
575
+ std::unique_ptr<char[]> partitionIdCobhanBufferPtr;
306
576
  if (partition_utf8_length < max_stack_alloc_size) {
307
- partitionIdCobhanBuffer = (char*)alloca(partition_utf8_length + 1 + header_size + SafetyPaddingOverhead);
577
+ size_t cobhan_buf_size = cobhan_buffer_size(partition_utf8_length);
578
+ debug_log_alloca(cobhan_buf_size);
579
+ partitionIdCobhanBuffer = (char *)alloca(cobhan_buf_size);
308
580
  } else {
309
- partitionIdCobhanBuffer = new char[partition_utf8_length + 1 + header_size + SafetyPaddingOverhead];
581
+ partitionIdCobhanBufferPtr = allocate_cbuffer(partition_utf8_length);
582
+ partitionIdCobhanBuffer = partitionIdCobhanBufferPtr.get();
310
583
  }
311
- partitionIdCobhanBuffer = copy_nstring_to_cbuffer(env, partitionId, partition_utf8_length, partitionIdCobhanBuffer, &partition_copied_bytes);
312
- if (partitionIdCobhanBuffer == NULL) {
313
- if (partition_utf8_length >= max_stack_alloc_size)
314
- delete[] partitionIdCobhanBuffer;
315
- return env.Null();
584
+ if (unlikely(partitionIdCobhanBuffer == nullptr)) {
585
+ return LogErrorAndThrow(
586
+ env, decrypt_failed_message +
587
+ std::string(" failed to allocate partitionId cobhan buffer"));
316
588
  }
317
589
 
318
- size_t utf8_length;
319
- Napi::String inputJson = info[1].As<Napi::String>();
320
- char *inputJsonCobhanBuffer = nstring_to_cbuffer(env, inputJson, &utf8_length);
321
- if (inputJsonCobhanBuffer == NULL) {
322
- if (partition_utf8_length >= max_stack_alloc_size)
323
- delete[] partitionIdCobhanBuffer;
324
- return env.Null();
590
+ // Copy
591
+ partitionIdCobhanBuffer =
592
+ copy_nstring_to_cbuffer(env, partitionId, partition_utf8_length,
593
+ partitionIdCobhanBuffer, &partition_copied_bytes);
594
+ if (unlikely(partitionIdCobhanBuffer == nullptr)) {
595
+ return LogErrorAndThrow(
596
+ env, decrypt_failed_message +
597
+ std::string(" failed to copy partitionId to cobhan buffer"));
325
598
  }
326
599
 
327
- char *cobhanOutputBuffer;
328
- if (utf8_length < max_stack_alloc_size) {
329
- cobhanOutputBuffer = configure_cbuffer((char*)alloca(utf8_length + header_size + SafetyPaddingOverhead), utf8_length);
600
+ // Determine size
601
+ size_t input_utf8_length;
602
+ Napi::String input = info[1].As<Napi::String>();
603
+ input_utf8_length = nstring_utf8_length(env, input);
604
+ if (unlikely(input_utf8_length == (size_t)(-1))) {
605
+ return LogErrorAndThrow(
606
+ env, decrypt_failed_message +
607
+ std::string(" failed to get input utf8 length"));
608
+ }
609
+
610
+ if(unlikely(verbose_flag)) {
611
+ debug_log("DecryptFromJsonToBuffer input size " +
612
+ std::to_string(input_utf8_length));
613
+ }
614
+
615
+ // Allocate
616
+ char *inputJsonCobhanBuffer;
617
+ std::unique_ptr<char[]> inputJsonCobhanBufferPtr;
618
+ if (input_utf8_length < max_stack_alloc_size) {
619
+ size_t cobhan_buf_size = cobhan_buffer_size(input_utf8_length);
620
+ debug_log_alloca(cobhan_buf_size);
621
+ inputJsonCobhanBuffer = (char *)alloca(cobhan_buf_size);
330
622
  } else {
331
- cobhanOutputBuffer = allocate_cbuffer(utf8_length);
332
- }
333
-
334
- //extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr, void* dataPtr);
335
- GoInt32 result = DecryptFromJson(partitionIdCobhanBuffer, inputJsonCobhanBuffer, cobhanOutputBuffer);
336
- if (partition_utf8_length >= max_stack_alloc_size)
337
- delete[] partitionIdCobhanBuffer;
338
- delete[] inputJsonCobhanBuffer;
339
- if (result < 0) {
340
- delete[] cobhanOutputBuffer;
341
- Napi::TypeError::New(env, DecryptFailedMessage + std::to_string(result))
342
- .ThrowAsJavaScriptException();
343
- return env.Null();
344
- }
345
-
346
- //Wrap the Cobhan output buffer with a NAPI buffer with finalizer
347
- if (utf8_length < max_stack_alloc_size) {
348
- return Napi::Buffer<unsigned char>::Copy(env,
349
- ((unsigned char*) cobhanOutputBuffer) + header_size,
350
- *((int*) cobhanOutputBuffer));
623
+ inputJsonCobhanBufferPtr = allocate_cbuffer(input_utf8_length);
624
+ inputJsonCobhanBuffer = inputJsonCobhanBufferPtr.get();
625
+ }
626
+ if (unlikely(inputJsonCobhanBuffer == nullptr)) {
627
+ return LogErrorAndThrow(
628
+ env, decrypt_failed_message +
629
+ std::string(" failed to allocate input cobhan buffer"));
630
+ }
631
+
632
+ // Copy
633
+ size_t input_copied_bytes;
634
+ inputJsonCobhanBuffer =
635
+ copy_nstring_to_cbuffer(env, input, input_utf8_length,
636
+ inputJsonCobhanBuffer, &input_copied_bytes);
637
+ if (unlikely(inputJsonCobhanBuffer == nullptr)) {
638
+ return LogErrorAndThrow(
639
+ env, decrypt_failed_message +
640
+ std::string(" failed to copy inputJson to cobhan buffer"));
641
+ }
642
+
643
+ char *cobhanOutputBuffer;
644
+ std::unique_ptr<char[]> cobhanOutputBufferPtr;
645
+ if (input_utf8_length < max_stack_alloc_size) {
646
+ size_t cobhan_buf_size = cobhan_buffer_size(input_utf8_length);
647
+ debug_log_alloca(cobhan_buf_size);
648
+ cobhanOutputBuffer = (char *)alloca(cobhan_buf_size);
649
+ configure_cbuffer(cobhanOutputBuffer, input_utf8_length);
351
650
  } else {
352
- return Napi::Buffer<unsigned char>::New(env,
353
- ((unsigned char*) cobhanOutputBuffer) + header_size,
354
- *((int*) cobhanOutputBuffer),
355
- &finalize_cbuffer);
651
+ cobhanOutputBufferPtr = allocate_cbuffer(input_utf8_length);
652
+ cobhanOutputBuffer = cobhanOutputBufferPtr.get();
653
+ }
654
+ if (unlikely(cobhanOutputBuffer == nullptr)) {
655
+ return LogErrorAndThrow(
656
+ env, decrypt_failed_message +
657
+ std::string(" failed to allocate cobhan output buffer"));
658
+ }
659
+
660
+ // extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr, void*
661
+ // dataPtr);
662
+ GoInt32 result = DecryptFromJson(partitionIdCobhanBuffer,
663
+ inputJsonCobhanBuffer, cobhanOutputBuffer);
664
+ if (unlikely(result < 0)) {
665
+ return LogErrorAndThrow(env,
666
+ decrypt_failed_message + std::to_string(result));
356
667
  }
668
+
669
+ return cbuffer_to_nbuffer(env, cobhanOutputBuffer);
357
670
  }
358
671
 
359
- Napi::Value Napi_DecryptFromJsonToString(const Napi::CallbackInfo& info) {
672
+ Napi::Value Napi_DecryptFromJsonToString(const Napi::CallbackInfo &info) {
360
673
  Napi::Env env = info.Env();
361
674
 
362
- if (info.Length() < 2) {
363
- Napi::TypeError::New(env, "DecryptFromJsonToString: Wrong number of arguments")
364
- .ThrowAsJavaScriptException();
365
- return env.Null();
675
+ if(unlikely(verbose_flag)) {
676
+ debug_log("DecryptFromJsonToString called");
366
677
  }
367
678
 
368
- if (!info[0].IsString() || !info[1].IsString()) {
369
- Napi::TypeError::New(env, "DecryptFromJsonToString: Wrong argument types")
370
- .ThrowAsJavaScriptException();
371
- return env.Null();
679
+ if (unlikely(setup_state == 0)) {
680
+ return LogErrorAndThrow(env, decrypt_failed_message +
681
+ std::string("SetupJson not called"));
372
682
  }
373
683
 
374
- size_t partition_utf8_length, partition_copied_bytes;
684
+ if (unlikely(info.Length() < 2)) {
685
+ return LogErrorAndThrow(
686
+ env, "DecryptFromJsonToString: Wrong number of arguments");
687
+ }
688
+
689
+ if (unlikely(!info[0].IsString() || !info[1].IsString())) {
690
+ return LogErrorAndThrow(env,
691
+ "DecryptFromJsonToString: Wrong argument types");
692
+ }
693
+
694
+ // Determine size
695
+ size_t partition_utf8_length;
375
696
  Napi::String partitionId = info[0].As<Napi::String>();
376
697
  partition_utf8_length = nstring_utf8_length(env, partitionId);
377
- if(partition_utf8_length == (size_t)(-1)) {
378
- return env.Null();
698
+ if (unlikely(partition_utf8_length == (size_t)(-1))) {
699
+ return LogErrorAndThrow(
700
+ env, decrypt_failed_message +
701
+ std::string(" failed to get partitionId utf8 length"));
379
702
  }
703
+
704
+ // Allocate
380
705
  char *partitionIdCobhanBuffer;
706
+ std::unique_ptr<char[]> partitionIdCobhanBufferPtr;
381
707
  if (partition_utf8_length < max_stack_alloc_size) {
382
- partitionIdCobhanBuffer = (char*)alloca(partition_utf8_length + 1 + header_size + SafetyPaddingOverhead);
708
+ size_t cobhan_buf_size = cobhan_buffer_size(partition_utf8_length);
709
+ debug_log_alloca(cobhan_buf_size);
710
+ partitionIdCobhanBuffer = (char *)alloca(cobhan_buf_size);
383
711
  } else {
384
- partitionIdCobhanBuffer = new char[partition_utf8_length + 1 + header_size + SafetyPaddingOverhead];
712
+ partitionIdCobhanBufferPtr = allocate_cbuffer(partition_utf8_length);
713
+ partitionIdCobhanBuffer = partitionIdCobhanBufferPtr.get();
385
714
  }
386
- partitionIdCobhanBuffer = copy_nstring_to_cbuffer(env, partitionId, partition_utf8_length, partitionIdCobhanBuffer, &partition_copied_bytes);
387
- if (partitionIdCobhanBuffer == NULL) {
388
- if (partition_utf8_length >= max_stack_alloc_size)
389
- delete[] partitionIdCobhanBuffer;
390
- return env.Null();
715
+ if (unlikely(partitionIdCobhanBuffer == nullptr)) {
716
+ return LogErrorAndThrow(
717
+ env, decrypt_failed_message +
718
+ std::string(" failed to allocate partitionId cobhan buffer"));
391
719
  }
392
720
 
393
- size_t utf8_length;
394
- Napi::String inputJson = info[1].As<Napi::String>();
395
- char *inputJsonCobhanBuffer = nstring_to_cbuffer(env, inputJson, &utf8_length);
396
- if (inputJsonCobhanBuffer == NULL) {
397
- if (partition_utf8_length >= max_stack_alloc_size)
398
- delete[] partitionIdCobhanBuffer;
399
- return env.Null();
721
+ // Copy
722
+ size_t partition_copied_bytes;
723
+ partitionIdCobhanBuffer =
724
+ copy_nstring_to_cbuffer(env, partitionId, partition_utf8_length,
725
+ partitionIdCobhanBuffer, &partition_copied_bytes);
726
+ if (unlikely(partitionIdCobhanBuffer == nullptr)) {
727
+ return LogErrorAndThrow(
728
+ env, decrypt_failed_message +
729
+ std::string(" failed to copy partitionId to cobhan buffer"));
730
+ }
731
+
732
+ // Determine size
733
+ size_t input_utf8_length;
734
+ Napi::String input = info[1].As<Napi::String>();
735
+ input_utf8_length = nstring_utf8_length(env, input);
736
+ if (unlikely(input_utf8_length == (size_t)(-1))) {
737
+ return LogErrorAndThrow(
738
+ env, decrypt_failed_message +
739
+ std::string(" failed to get input utf8 length"));
740
+ }
741
+
742
+ // Allocate
743
+ char *inputJsonCobhanBuffer;
744
+ std::unique_ptr<char[]> inputJsonCobhanBufferPtr;
745
+ if (input_utf8_length < max_stack_alloc_size) {
746
+ size_t cobhan_buf_size = cobhan_buffer_size(input_utf8_length);
747
+ debug_log_alloca(cobhan_buf_size);
748
+ inputJsonCobhanBuffer = (char *)alloca(cobhan_buf_size);
749
+ } else {
750
+ inputJsonCobhanBufferPtr = allocate_cbuffer(input_utf8_length);
751
+ inputJsonCobhanBuffer = inputJsonCobhanBufferPtr.get();
752
+ }
753
+ if (unlikely(inputJsonCobhanBuffer == nullptr)) {
754
+ return LogErrorAndThrow(
755
+ env, decrypt_failed_message +
756
+ std::string(" failed to allocate input cobhan buffer"));
757
+ }
758
+
759
+ // Copy
760
+ size_t input_copied_bytes;
761
+ inputJsonCobhanBuffer =
762
+ copy_nstring_to_cbuffer(env, input, input_utf8_length,
763
+ inputJsonCobhanBuffer, &input_copied_bytes);
764
+ if (unlikely(inputJsonCobhanBuffer == nullptr)) {
765
+ return LogErrorAndThrow(
766
+ env, decrypt_failed_message +
767
+ std::string(" failed to copy inputJson to cobhan buffer"));
400
768
  }
401
769
 
402
770
  char *cobhanOutputBuffer;
403
- if (utf8_length < max_stack_alloc_size) {
404
- cobhanOutputBuffer = configure_cbuffer((char*)alloca(utf8_length + header_size + SafetyPaddingOverhead), utf8_length);
771
+ std::unique_ptr<char[]> cobhanOutputBufferPtr;
772
+ if (input_utf8_length < max_stack_alloc_size) {
773
+ size_t cobhan_buf_size = cobhan_buffer_size(input_utf8_length);
774
+ debug_log_alloca(cobhan_buf_size);
775
+ cobhanOutputBuffer = (char *)alloca(cobhan_buf_size);
776
+ configure_cbuffer(cobhanOutputBuffer, input_utf8_length);
405
777
  } else {
406
- cobhanOutputBuffer = allocate_cbuffer(utf8_length);
778
+ cobhanOutputBufferPtr = allocate_cbuffer(input_utf8_length);
779
+ cobhanOutputBuffer = cobhanOutputBufferPtr.get();
780
+ }
781
+ if (unlikely(cobhanOutputBuffer == nullptr)) {
782
+ return LogErrorAndThrow(
783
+ env, decrypt_failed_message +
784
+ std::string(" failed to allocate cobhan output buffer"));
407
785
  }
408
786
 
409
- //extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr, void* dataPtr);
410
- GoInt32 result = DecryptFromJson(partitionIdCobhanBuffer, inputJsonCobhanBuffer, cobhanOutputBuffer);
411
- if (partition_utf8_length >= max_stack_alloc_size)
412
- delete[] partitionIdCobhanBuffer;
413
- delete[] inputJsonCobhanBuffer;
414
- if (result < 0) {
415
- if (utf8_length >= max_stack_alloc_size)
416
- delete[] cobhanOutputBuffer;
417
- Napi::TypeError::New(env, DecryptFailedMessage + std::to_string(result))
418
- .ThrowAsJavaScriptException();
419
- return env.Null();
787
+ // extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr, void*
788
+ // dataPtr);
789
+ GoInt32 result = DecryptFromJson(partitionIdCobhanBuffer,
790
+ inputJsonCobhanBuffer, cobhanOutputBuffer);
791
+ if (unlikely(result < 0)) {
792
+ return LogErrorAndThrow(env,
793
+ decrypt_failed_message + std::to_string(result));
420
794
  }
421
795
 
422
796
  Napi::Value output = cbuffer_to_nstring(env, cobhanOutputBuffer);
423
- if (utf8_length >= max_stack_alloc_size)
424
- delete[] cobhanOutputBuffer;
425
797
  return output;
426
798
  }
427
799
 
428
- Napi::Value Napi_Shutdown(const Napi::CallbackInfo& info) {
800
+ Napi::Value Napi_Shutdown(const Napi::CallbackInfo &info) {
429
801
  Napi::Env env = info.Env();
430
- //extern void Shutdown();
802
+
803
+ if(unlikely(verbose_flag)) {
804
+ debug_log("Shutdown called");
805
+ }
806
+
807
+ setup_state = 0;
808
+ // extern void Shutdown();
431
809
  Shutdown();
432
810
  return env.Null();
433
811
  }
434
812
 
435
- Napi::Value Napi_SetMaxStackAllocItemSize(const Napi::CallbackInfo& info) {
813
+ Napi::Value Napi_SetMaxStackAllocItemSize(const Napi::CallbackInfo &info) {
436
814
  Napi::Env env = info.Env();
437
815
 
438
- if (info.Length() < 1) {
439
- Napi::TypeError::New(env, "SetMaxStackAllocItemSize: Wrong number of arguments")
440
- .ThrowAsJavaScriptException();
441
- return env.Null();
816
+ if(unlikely(verbose_flag)) {
817
+ debug_log("SetMaxStackAllocItemSize called");
818
+ }
819
+
820
+ if (unlikely(info.Length() < 1)) {
821
+ return LogErrorAndThrow(
822
+ env, "SetMaxStackAllocItemSize: Wrong number of arguments");
442
823
  }
443
824
 
444
825
  Napi::Number item_size = info[0].As<Napi::Number>();
@@ -447,28 +828,41 @@ Napi::Value Napi_SetMaxStackAllocItemSize(const Napi::CallbackInfo& info) {
447
828
  return env.Null();
448
829
  }
449
830
 
450
- Napi::Value Napi_SetSafetyPaddingOverhead(const Napi::CallbackInfo& info) {
831
+ Napi::Value Napi_SetSafetyPaddingOverhead(const Napi::CallbackInfo &info) {
451
832
  Napi::Env env = info.Env();
452
833
 
453
- if (info.Length() < 1) {
454
- Napi::TypeError::New(env, "SetSafetyPaddingOverhead: Wrong number of arguments")
455
- .ThrowAsJavaScriptException();
456
- return env.Null();
834
+ if(unlikely(verbose_flag)) {
835
+ debug_log("SetSafetyPaddingOverhead called");
836
+ }
837
+
838
+ if (unlikely(info.Length() < 1)) {
839
+ return LogErrorAndThrow(
840
+ env, "SetSafetyPaddingOverhead: Wrong number of arguments");
457
841
  }
458
842
 
459
- Napi::Number safety_padding = info[0].As<Napi::Number>();
843
+ Napi::Number safety_padding_number = info[0].As<Napi::Number>();
460
844
 
461
- SafetyPaddingOverhead = (size_t)safety_padding.Int32Value();
845
+ safety_padding = (size_t)safety_padding_number.Int32Value();
462
846
  return env.Null();
463
847
  }
464
848
 
465
849
  Napi::Object Init(Napi::Env env, Napi::Object exports) {
466
- exports.Set(Napi::String::New(env, "Napi_SetupJson"), Napi::Function::New(env, Napi_SetupJson));
467
- exports.Set(Napi::String::New(env, "Napi_EncryptFromBufferToJson"), Napi::Function::New(env, Napi_EncryptFromBufferToJson));
468
- exports.Set(Napi::String::New(env, "Napi_EncryptFromStringToJson"), Napi::Function::New(env, Napi_EncryptFromStringToJson));
469
- exports.Set(Napi::String::New(env, "Napi_DecryptFromJsonToBuffer"), Napi::Function::New(env, Napi_DecryptFromJsonToBuffer));
470
- exports.Set(Napi::String::New(env, "Napi_DecryptFromJsonToString"), Napi::Function::New(env, Napi_DecryptFromJsonToString));
471
- exports.Set(Napi::String::New(env, "Napi_Shutdown"), Napi::Function::New(env, Napi_Shutdown));
850
+ exports.Set(Napi::String::New(env, "Napi_SetupJson"),
851
+ Napi::Function::New(env, Napi_SetupJson));
852
+ exports.Set(Napi::String::New(env, "Napi_EncryptFromBufferToJson"),
853
+ Napi::Function::New(env, Napi_EncryptFromBufferToJson));
854
+ exports.Set(Napi::String::New(env, "Napi_EncryptFromStringToJson"),
855
+ Napi::Function::New(env, Napi_EncryptFromStringToJson));
856
+ exports.Set(Napi::String::New(env, "Napi_DecryptFromJsonToBuffer"),
857
+ Napi::Function::New(env, Napi_DecryptFromJsonToBuffer));
858
+ exports.Set(Napi::String::New(env, "Napi_DecryptFromJsonToString"),
859
+ Napi::Function::New(env, Napi_DecryptFromJsonToString));
860
+ exports.Set(Napi::String::New(env, "Napi_SetSafetyPaddingOverhead"),
861
+ Napi::Function::New(env, Napi_SetSafetyPaddingOverhead));
862
+ exports.Set(Napi::String::New(env, "Napi_SetMaxStackAllocItemSize"),
863
+ Napi::Function::New(env, Napi_SetMaxStackAllocItemSize));
864
+ exports.Set(Napi::String::New(env, "Napi_Shutdown"),
865
+ Napi::Function::New(env, Napi_Shutdown));
472
866
  return exports;
473
867
  }
474
868