asherah 1.2.9 → 1.3.0

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/dist/asherah.d.ts CHANGED
@@ -46,3 +46,4 @@ export declare function decrypt(partitionId: string, dataRowRecord: string): Buf
46
46
  export declare function encrypt(partitionId: string, data: Buffer): string;
47
47
  export declare function decrypt_string(partitionId: string, dataRowRecord: string): string;
48
48
  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;
package/dist/asherah.js CHANGED
@@ -1,23 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.encrypt_string = exports.decrypt_string = exports.encrypt = exports.decrypt = exports.shutdown = exports.setup = void 0;
4
- const cobhan_1 = require("cobhan");
3
+ exports.set_max_stack_alloc_item_size = exports.encrypt_string = exports.decrypt_string = exports.encrypt = exports.decrypt = exports.shutdown = exports.setup = void 0;
5
4
  const napi_asherah = require('../build/Release/napiasherah.node');
6
- const EstimatedEncryptionOverhead = 48;
7
- const EstimatedEnvelopeOverhead = 185;
8
- const Base64Overhead = 1.34;
9
- let EstimatedIntermediateKeyOverhead = 0;
10
- function estimate_buffer(dataLen, partitionLen) {
11
- const estimatedDataLen = (dataLen + EstimatedEncryptionOverhead) * Base64Overhead;
12
- return EstimatedEnvelopeOverhead + EstimatedIntermediateKeyOverhead + partitionLen + estimatedDataLen;
13
- }
14
5
  function setup(config) {
15
- const configJsonBuffer = (0, cobhan_1.json_to_cbuffer)(config);
16
- EstimatedIntermediateKeyOverhead = config.ProductID.length + config.ServiceName.length;
17
- const result = napi_asherah.Napi_SetupJson(configJsonBuffer);
18
- if (result < 0) {
19
- throw new Error('setupJson failed: ' + result);
20
- }
6
+ const configStr = JSON.stringify(config);
7
+ napi_asherah.Napi_SetupJson(configStr, config.ProductID.length, config.ServiceName.length, configStr.length);
21
8
  }
22
9
  exports.setup = setup;
23
10
  function shutdown() {
@@ -25,32 +12,22 @@ function shutdown() {
25
12
  }
26
13
  exports.shutdown = shutdown;
27
14
  function decrypt(partitionId, dataRowRecord) {
28
- const partitionIdBuffer = (0, cobhan_1.string_to_cbuffer)(partitionId);
29
- const jsonBuffer = (0, cobhan_1.string_to_cbuffer)(dataRowRecord);
30
- const outputDataBuffer = (0, cobhan_1.allocate_cbuffer)(jsonBuffer.byteLength);
31
- const result = napi_asherah.Napi_DecryptFromJson(partitionIdBuffer, jsonBuffer, outputDataBuffer);
32
- if (result < 0) {
33
- throw new Error('decrypt failed: ' + result);
34
- }
35
- return (0, cobhan_1.cbuffer_to_buffer)(outputDataBuffer);
15
+ return napi_asherah.Napi_DecryptFromJsonToBuffer(partitionId, dataRowRecord);
36
16
  }
37
17
  exports.decrypt = decrypt;
38
18
  function encrypt(partitionId, data) {
39
- const partitionIdBuffer = (0, cobhan_1.string_to_cbuffer)(partitionId);
40
- const dataBuffer = (0, cobhan_1.buffer_to_cbuffer)(data);
41
- const outputJsonBuffer = (0, cobhan_1.allocate_cbuffer)(estimate_buffer(data.byteLength, partitionId.length));
42
- const result = napi_asherah.Napi_EncryptToJson(partitionIdBuffer, dataBuffer, outputJsonBuffer);
43
- if (result < 0) {
44
- throw new Error('encrypt failed: ' + result);
45
- }
46
- return (0, cobhan_1.cbuffer_to_string)(outputJsonBuffer);
19
+ return napi_asherah.Napi_EncryptFromBufferToJson(partitionId, data);
47
20
  }
48
21
  exports.encrypt = encrypt;
49
22
  function decrypt_string(partitionId, dataRowRecord) {
50
- return decrypt(partitionId, dataRowRecord).toString('utf8');
23
+ return napi_asherah.Napi_DecryptFromJsonToString(partitionId, dataRowRecord);
51
24
  }
52
25
  exports.decrypt_string = decrypt_string;
53
26
  function encrypt_string(partitionId, data) {
54
- return encrypt(partitionId, Buffer.from(data, 'utf8'));
27
+ return napi_asherah.Napi_EncryptFromStringToJson(partitionId, data);
55
28
  }
56
29
  exports.encrypt_string = encrypt_string;
30
+ function set_max_stack_alloc_item_size(max_item_size) {
31
+ return napi_asherah.Napi_SetMaxStackAllocItemSize(max_item_size);
32
+ }
33
+ exports.set_max_stack_alloc_item_size = set_max_stack_alloc_item_size;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asherah",
3
- "version": "1.2.9",
3
+ "version": "1.3.0",
4
4
  "description": "Asherah envelope encryption and key rotation library",
5
5
  "main": "dist/asherah.js",
6
6
  "repository": {
@@ -1,85 +1,473 @@
1
1
  #include <napi.h>
2
2
  #include "../lib/libasherah.h"
3
3
 
4
- //extern GoInt32 SetupJson(void* configJson);
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;
18
+ }
19
+
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);
23
+ }
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;
28
+ }
29
+
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);
33
+ }
34
+
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);
40
+ }
41
+
42
+ __attribute__((always_inline)) inline Napi::Value cbuffer_to_nstring(Napi::Env &env, char *cobhanBuffer) {
43
+ 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();
50
+ }
51
+ return Napi::String(env, output);
52
+ }
53
+
54
+ __attribute__((always_inline)) inline size_t nstring_utf8_length(Napi::Env &env, Napi::String &str) {
55
+ napi_status status;
56
+ size_t utf8_length;
57
+
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();
62
+ return (size_t)(-1);
63
+ }
64
+ return utf8_length;
65
+ }
66
+
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) {
68
+ napi_status status;
69
+ 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;
75
+ }
76
+
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;
81
+ }
82
+
83
+ *((int*)cbuffer) = copied_bytes;
84
+ *((int*)(cbuffer+sizeof(int32_t))) = 0;
85
+
86
+ if(length != NULL)
87
+ *length = copied_bytes;
88
+ return cbuffer;
89
+ }
90
+
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
+ }
96
+
97
+ char *cobhanBuffer = new char[utf8_length + 1 + header_size + SafetyPaddingOverhead];
98
+
99
+ char *output = copy_nstring_to_cbuffer(env, str, utf8_length, cobhanBuffer, length);
100
+ if(output == NULL) {
101
+ delete[] cobhanBuffer;
102
+ }
103
+ return output;
104
+ }
105
+
5
106
  Napi::Value Napi_SetupJson(const Napi::CallbackInfo& info) {
6
107
  Napi::Env env = info.Env();
7
108
 
8
- if (info.Length() < 1) {
9
- Napi::TypeError::New(env, "Wrong number of arguments")
109
+ if (info.Length() < 3) {
110
+ Napi::TypeError::New(env, "SetupJson: Wrong number of arguments")
10
111
  .ThrowAsJavaScriptException();
11
112
  return env.Null();
12
113
  }
13
114
 
14
- Napi::Buffer<unsigned char> configJson = info[0].As<Napi::Buffer<unsigned char>>();
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();
119
+ }
120
+
121
+ Napi::String configJson = info[0].As<Napi::String>();
122
+ char *configJsonCobhanBuffer = nstring_to_cbuffer(env, configJson);
123
+ if (configJsonCobhanBuffer == NULL) {
124
+ return env.Null();
125
+ }
126
+
127
+ Napi::Number productIdLength = info[1].As<Napi::Number>();
128
+ Napi::Number serviceNameLength = info[2].As<Napi::Number>();
15
129
 
16
- GoInt32 result = SetupJson(configJson.Data());
130
+ EstimatedIntermediateKeyOverhead = productIdLength.Int32Value() + serviceNameLength.Int32Value();
17
131
 
18
- Napi::Number num = Napi::Number::New(env, result);
19
- return num;
132
+ //extern GoInt32 SetupJson(void* configJson);
133
+ GoInt32 result = SetupJson(configJsonCobhanBuffer);
134
+ delete[] configJsonCobhanBuffer;
135
+ if (result < 0) {
136
+ Napi::TypeError::New(env, SetupJsonFailedMessage + std::to_string(result))
137
+ .ThrowAsJavaScriptException();
138
+ }
139
+ return env.Null();
20
140
  }
21
141
 
22
- //extern GoInt32 EncryptToJson(void* partitionIdPtr, void* dataPtr, void* jsonPtr);
23
- Napi::Value Napi_EncryptToJson(const Napi::CallbackInfo& info) {
142
+ Napi::Value Napi_EncryptFromBufferToJson(const Napi::CallbackInfo& info) {
24
143
  Napi::Env env = info.Env();
25
144
 
26
- if (info.Length() < 3) {
27
- Napi::TypeError::New(env, "Wrong number of arguments")
145
+ if (info.Length() < 2) {
146
+ Napi::TypeError::New(env, "EncryptFromBufferToJson: Wrong number of arguments")
28
147
  .ThrowAsJavaScriptException();
29
148
  return env.Null();
30
149
  }
31
150
 
32
- if (!info[0].IsBuffer() || !info[1].IsBuffer() || !info[2].IsBuffer()) {
33
- Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
151
+ if (!info[0].IsString() || !info[1].IsBuffer()) {
152
+ Napi::TypeError::New(env, "EncryptFromBufferToJson: Wrong argument types")
153
+ .ThrowAsJavaScriptException();
154
+ return env.Null();
155
+ }
156
+
157
+ size_t partition_utf8_length, partition_copied_bytes;
158
+ Napi::String partitionId = info[0].As<Napi::String>();
159
+ partition_utf8_length = nstring_utf8_length(env, partitionId);
160
+ if(partition_utf8_length == (size_t)(-1)) {
161
+ return env.Null();
162
+ }
163
+ char *partitionIdCobhanBuffer;
164
+ if (partition_utf8_length < max_stack_alloc_size) {
165
+ partitionIdCobhanBuffer = (char*)alloca(partition_utf8_length + 1 + header_size + SafetyPaddingOverhead);
166
+ } else {
167
+ partitionIdCobhanBuffer = new char[partition_utf8_length + 1 + header_size + SafetyPaddingOverhead];
168
+ }
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;
34
173
  return env.Null();
35
174
  }
36
175
 
37
- Napi::Buffer<unsigned char> partitionId = info[0].As<Napi::Buffer<unsigned char>>();
38
176
  Napi::Buffer<unsigned char> data = info[1].As<Napi::Buffer<unsigned char>>();
39
- Napi::Buffer<unsigned char> outputJson = info[2].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
+ }
183
+
184
+ size_t bufferSize = estimate_buffer(partition_copied_bytes, data.ByteLength());
185
+
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
+ }
40
192
 
41
- GoInt32 result = EncryptToJson(partitionId.Data(), data.Data(), outputJson.Data());
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();
204
+ }
42
205
 
43
- Napi::Number num = Napi::Number::New(env, result);
44
- return num;
206
+ Napi::Value output = cbuffer_to_nstring(env, cobhanOutputBuffer);
207
+ if (bufferSize >= max_stack_alloc_size)
208
+ delete[] cobhanOutputBuffer;
209
+ return output;
45
210
  }
46
211
 
47
- //extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr, void* dataPtr);
48
- Napi::Value Napi_DecryptFromJson(const Napi::CallbackInfo& info) {
212
+ Napi::Value Napi_EncryptFromStringToJson(const Napi::CallbackInfo& info) {
49
213
  Napi::Env env = info.Env();
50
214
 
51
- if (info.Length() < 3) {
52
- Napi::TypeError::New(env, "Wrong number of arguments")
215
+ if (info.Length() < 2) {
216
+ Napi::TypeError::New(env, "EncryptFromStringToJson: Wrong number of arguments")
53
217
  .ThrowAsJavaScriptException();
54
218
  return env.Null();
55
219
  }
56
220
 
57
- if (!info[0].IsBuffer() || !info[1].IsBuffer() || !info[2].IsBuffer()) {
58
- Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
221
+ if (!info[0].IsString() || !info[1].IsString()) {
222
+ Napi::TypeError::New(env, "EncryptFromStringToJson: Wrong argument types")
223
+ .ThrowAsJavaScriptException();
224
+ return env.Null();
225
+ }
226
+
227
+ size_t partition_utf8_length, partition_copied_bytes;
228
+ Napi::String partitionId = info[0].As<Napi::String>();
229
+ partition_utf8_length = nstring_utf8_length(env, partitionId);
230
+ if(partition_utf8_length == (size_t)(-1)) {
231
+ return env.Null();
232
+ }
233
+ char *partitionIdCobhanBuffer;
234
+ if (partition_utf8_length < max_stack_alloc_size) {
235
+ partitionIdCobhanBuffer = (char*)alloca(partition_utf8_length + 1 + header_size + SafetyPaddingOverhead);
236
+ } else {
237
+ partitionIdCobhanBuffer = new char[partition_utf8_length + 1 + header_size + SafetyPaddingOverhead];
238
+ }
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();
244
+ }
245
+
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;
59
252
  return env.Null();
60
253
  }
61
254
 
62
- Napi::Buffer<unsigned char> partitionId = info[0].As<Napi::Buffer<unsigned char>>();
63
- Napi::Buffer<unsigned char> inputJson = info[1].As<Napi::Buffer<unsigned char>>();
64
- Napi::Buffer<unsigned char> outputData = info[2].As<Napi::Buffer<unsigned char>>();
255
+ //Call estimate_buffer to determine Cobhan output buffer length
256
+ size_t bufferSize = estimate_buffer(partition_utf8_length, input_utf8_length);
65
257
 
66
- GoInt32 result = DecryptFromJson(partitionId.Data(), inputJson.Data(), outputData.Data());
258
+ char *cobhanOutputBuffer;
259
+ if (bufferSize < max_stack_alloc_size) {
260
+ cobhanOutputBuffer = configure_cbuffer((char*)alloca(bufferSize + header_size + SafetyPaddingOverhead), bufferSize);
261
+ } else {
262
+ cobhanOutputBuffer = allocate_cbuffer(bufferSize);
263
+ }
67
264
 
68
- Napi::Number num = Napi::Number::New(env, result);
69
- return num;
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();
276
+ }
277
+
278
+ Napi::Value output = cbuffer_to_nstring(env, cobhanOutputBuffer);
279
+ if (bufferSize >= max_stack_alloc_size)
280
+ delete[] cobhanOutputBuffer;
281
+ return output;
282
+ }
283
+
284
+ Napi::Value Napi_DecryptFromJsonToBuffer(const Napi::CallbackInfo& info) {
285
+ Napi::Env env = info.Env();
286
+
287
+ if (info.Length() < 2) {
288
+ Napi::TypeError::New(env, "DecryptFromJsonToBuffer: Wrong number of arguments")
289
+ .ThrowAsJavaScriptException();
290
+ return env.Null();
291
+ }
292
+
293
+ if (!info[0].IsString() || !info[1].IsString()) {
294
+ Napi::TypeError::New(env, "DecryptFromJsonToBuffer: Wrong argument types")
295
+ .ThrowAsJavaScriptException();
296
+ return env.Null();
297
+ }
298
+
299
+ size_t partition_utf8_length, partition_copied_bytes;
300
+ Napi::String partitionId = info[0].As<Napi::String>();
301
+ partition_utf8_length = nstring_utf8_length(env, partitionId);
302
+ if(partition_utf8_length == (size_t)(-1)) {
303
+ return env.Null();
304
+ }
305
+ char *partitionIdCobhanBuffer;
306
+ if (partition_utf8_length < max_stack_alloc_size) {
307
+ partitionIdCobhanBuffer = (char*)alloca(partition_utf8_length + 1 + header_size + SafetyPaddingOverhead);
308
+ } else {
309
+ partitionIdCobhanBuffer = new char[partition_utf8_length + 1 + header_size + SafetyPaddingOverhead];
310
+ }
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();
316
+ }
317
+
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();
325
+ }
326
+
327
+ char *cobhanOutputBuffer;
328
+ if (utf8_length < max_stack_alloc_size) {
329
+ cobhanOutputBuffer = configure_cbuffer((char*)alloca(utf8_length + header_size + SafetyPaddingOverhead), utf8_length);
330
+ } 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));
351
+ } else {
352
+ return Napi::Buffer<unsigned char>::New(env,
353
+ ((unsigned char*) cobhanOutputBuffer) + header_size,
354
+ *((int*) cobhanOutputBuffer),
355
+ &finalize_cbuffer);
356
+ }
357
+ }
358
+
359
+ Napi::Value Napi_DecryptFromJsonToString(const Napi::CallbackInfo& info) {
360
+ Napi::Env env = info.Env();
361
+
362
+ if (info.Length() < 2) {
363
+ Napi::TypeError::New(env, "DecryptFromJsonToString: Wrong number of arguments")
364
+ .ThrowAsJavaScriptException();
365
+ return env.Null();
366
+ }
367
+
368
+ if (!info[0].IsString() || !info[1].IsString()) {
369
+ Napi::TypeError::New(env, "DecryptFromJsonToString: Wrong argument types")
370
+ .ThrowAsJavaScriptException();
371
+ return env.Null();
372
+ }
373
+
374
+ size_t partition_utf8_length, partition_copied_bytes;
375
+ Napi::String partitionId = info[0].As<Napi::String>();
376
+ partition_utf8_length = nstring_utf8_length(env, partitionId);
377
+ if(partition_utf8_length == (size_t)(-1)) {
378
+ return env.Null();
379
+ }
380
+ char *partitionIdCobhanBuffer;
381
+ if (partition_utf8_length < max_stack_alloc_size) {
382
+ partitionIdCobhanBuffer = (char*)alloca(partition_utf8_length + 1 + header_size + SafetyPaddingOverhead);
383
+ } else {
384
+ partitionIdCobhanBuffer = new char[partition_utf8_length + 1 + header_size + SafetyPaddingOverhead];
385
+ }
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();
391
+ }
392
+
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();
400
+ }
401
+
402
+ char *cobhanOutputBuffer;
403
+ if (utf8_length < max_stack_alloc_size) {
404
+ cobhanOutputBuffer = configure_cbuffer((char*)alloca(utf8_length + header_size + SafetyPaddingOverhead), utf8_length);
405
+ } else {
406
+ cobhanOutputBuffer = allocate_cbuffer(utf8_length);
407
+ }
408
+
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();
420
+ }
421
+
422
+ Napi::Value output = cbuffer_to_nstring(env, cobhanOutputBuffer);
423
+ if (utf8_length >= max_stack_alloc_size)
424
+ delete[] cobhanOutputBuffer;
425
+ return output;
70
426
  }
71
427
 
72
- //extern void Shutdown();
73
428
  Napi::Value Napi_Shutdown(const Napi::CallbackInfo& info) {
74
429
  Napi::Env env = info.Env();
430
+ //extern void Shutdown();
75
431
  Shutdown();
76
432
  return env.Null();
77
433
  }
78
434
 
435
+ Napi::Value Napi_SetMaxStackAllocItemSize(const Napi::CallbackInfo& info) {
436
+ Napi::Env env = info.Env();
437
+
438
+ if (info.Length() < 1) {
439
+ Napi::TypeError::New(env, "SetMaxStackAllocItemSize: Wrong number of arguments")
440
+ .ThrowAsJavaScriptException();
441
+ return env.Null();
442
+ }
443
+
444
+ Napi::Number item_size = info[0].As<Napi::Number>();
445
+
446
+ max_stack_alloc_size = (size_t)item_size.Int32Value();
447
+ return env.Null();
448
+ }
449
+
450
+ Napi::Value Napi_SetSafetyPaddingOverhead(const Napi::CallbackInfo& info) {
451
+ Napi::Env env = info.Env();
452
+
453
+ if (info.Length() < 1) {
454
+ Napi::TypeError::New(env, "SetSafetyPaddingOverhead: Wrong number of arguments")
455
+ .ThrowAsJavaScriptException();
456
+ return env.Null();
457
+ }
458
+
459
+ Napi::Number safety_padding = info[0].As<Napi::Number>();
460
+
461
+ SafetyPaddingOverhead = (size_t)safety_padding.Int32Value();
462
+ return env.Null();
463
+ }
464
+
79
465
  Napi::Object Init(Napi::Env env, Napi::Object exports) {
80
466
  exports.Set(Napi::String::New(env, "Napi_SetupJson"), Napi::Function::New(env, Napi_SetupJson));
81
- exports.Set(Napi::String::New(env, "Napi_EncryptToJson"), Napi::Function::New(env, Napi_EncryptToJson));
82
- exports.Set(Napi::String::New(env, "Napi_DecryptFromJson"), Napi::Function::New(env, Napi_DecryptFromJson));
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));
83
471
  exports.Set(Napi::String::New(env, "Napi_Shutdown"), Napi::Function::New(env, Napi_Shutdown));
84
472
  return exports;
85
473
  }