asherah 1.3.6 → 1.3.7
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.node +0 -0
- package/package.json +3 -3
- package/src/asherah.cc +983 -0
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "asherah",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.7",
|
|
4
4
|
"description": "Asherah envelope encryption and key rotation library",
|
|
5
5
|
"main": "dist/asherah.js",
|
|
6
6
|
"repository": {
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"files": [
|
|
23
23
|
"binding.gyp",
|
|
24
|
-
"src/
|
|
24
|
+
"src/asherah.cc",
|
|
25
25
|
"dist/asherah.d.ts",
|
|
26
26
|
"scripts/download-libraries.sh",
|
|
27
|
-
"
|
|
27
|
+
"dist/asherah.node",
|
|
28
28
|
"SHA256SUMS",
|
|
29
29
|
"SHA256SUMS-darwin",
|
|
30
30
|
".asherah-version"
|
package/src/asherah.cc
ADDED
|
@@ -0,0 +1,983 @@
|
|
|
1
|
+
#include "../lib/libasherah.h"
|
|
2
|
+
#include <iostream>
|
|
3
|
+
#define NODE_ADDON_API_DISABLE_DEPRECATED
|
|
4
|
+
#include <napi.h>
|
|
5
|
+
|
|
6
|
+
#define unlikely(expr) __builtin_expect(!!(expr), 0)
|
|
7
|
+
#define likely(expr) __builtin_expect(!!(expr), 1)
|
|
8
|
+
|
|
9
|
+
const size_t cobhan_header_size_bytes = 64 / 8;
|
|
10
|
+
const size_t est_encryption_overhead = 48;
|
|
11
|
+
const size_t est_envelope_overhead = 185;
|
|
12
|
+
const double base64_overhead = 1.34;
|
|
13
|
+
|
|
14
|
+
size_t est_intermediate_key_overhead = 0;
|
|
15
|
+
size_t safety_padding_bytes = 0;
|
|
16
|
+
size_t max_stack_alloc_size = 2048;
|
|
17
|
+
|
|
18
|
+
int32_t setup_state = 0;
|
|
19
|
+
int32_t verbose_flag = 0;
|
|
20
|
+
|
|
21
|
+
__attribute__((always_inline)) inline void debug_log(const char *function_name,
|
|
22
|
+
std::string message) {
|
|
23
|
+
if (unlikely(verbose_flag)) {
|
|
24
|
+
std::cerr << "asherah-node: [DEBUG] " << function_name << ": " << message
|
|
25
|
+
<< std::endl
|
|
26
|
+
<< std::flush;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
__attribute__((always_inline)) inline void
|
|
31
|
+
debug_log_alloca(const char *function_name, const char *variable_name,
|
|
32
|
+
size_t length) {
|
|
33
|
+
if (unlikely(verbose_flag)) {
|
|
34
|
+
std::cerr << "asherah-node: [DEBUG] " << function_name
|
|
35
|
+
<< ": Calling alloca(" << length << ") (stack) for "
|
|
36
|
+
<< variable_name << std::endl
|
|
37
|
+
<< std::flush;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
__attribute__((always_inline)) inline void error_log(const char *function_name,
|
|
42
|
+
std::string message) {
|
|
43
|
+
if (unlikely(verbose_flag)) {
|
|
44
|
+
std::cerr << "asherah-node: [ERROR] " << function_name << ": " << message
|
|
45
|
+
<< std::endl
|
|
46
|
+
<< std::flush;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
std::string napi_status_to_string(napi_status status) {
|
|
51
|
+
switch (status) {
|
|
52
|
+
case napi_ok:
|
|
53
|
+
return "napi_ok";
|
|
54
|
+
case napi_invalid_arg:
|
|
55
|
+
return "napi_invalid_arg";
|
|
56
|
+
case napi_object_expected:
|
|
57
|
+
return "napi_object_expected";
|
|
58
|
+
case napi_string_expected:
|
|
59
|
+
return "napi_string_expected";
|
|
60
|
+
case napi_name_expected:
|
|
61
|
+
return "napi_name_expected";
|
|
62
|
+
case napi_function_expected:
|
|
63
|
+
return "napi_function_expected";
|
|
64
|
+
case napi_number_expected:
|
|
65
|
+
return "napi_number_expected";
|
|
66
|
+
case napi_boolean_expected:
|
|
67
|
+
return "napi_boolean_expected";
|
|
68
|
+
case napi_array_expected:
|
|
69
|
+
return "napi_array_expected";
|
|
70
|
+
case napi_generic_failure:
|
|
71
|
+
return "napi_generic_failure";
|
|
72
|
+
case napi_pending_exception:
|
|
73
|
+
return "napi_pending_exception";
|
|
74
|
+
case napi_cancelled:
|
|
75
|
+
return "napi_cancelled";
|
|
76
|
+
case napi_escape_called_twice:
|
|
77
|
+
return "napi_escape_called_twice";
|
|
78
|
+
case napi_handle_scope_mismatch:
|
|
79
|
+
return "napi_handle_scope_mismatch";
|
|
80
|
+
case napi_callback_scope_mismatch:
|
|
81
|
+
return "napi_callback_scope_mismatch";
|
|
82
|
+
case napi_queue_full:
|
|
83
|
+
return "napi_queue_full";
|
|
84
|
+
case napi_closing:
|
|
85
|
+
return "napi_closing";
|
|
86
|
+
case napi_bigint_expected:
|
|
87
|
+
return "napi_bigint_expected";
|
|
88
|
+
case napi_date_expected:
|
|
89
|
+
return "napi_date_expected";
|
|
90
|
+
case napi_arraybuffer_expected:
|
|
91
|
+
return "napi_arraybuffer_expected";
|
|
92
|
+
case napi_detachable_arraybuffer_expected:
|
|
93
|
+
return "napi_detachable_arraybuffer_expected";
|
|
94
|
+
case napi_would_deadlock:
|
|
95
|
+
return "napi_would_deadlock";
|
|
96
|
+
default:
|
|
97
|
+
return "Unknown napi_status";
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
__attribute__((always_inline)) inline Napi::Value
|
|
102
|
+
LogErrorAndThrow(Napi::Env &env, const char *function_name,
|
|
103
|
+
std::string error_msg) {
|
|
104
|
+
error_log(function_name, error_msg);
|
|
105
|
+
Napi::Error::New(env, function_name + (": " + error_msg))
|
|
106
|
+
.ThrowAsJavaScriptException();
|
|
107
|
+
return env.Null();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
__attribute__((always_inline)) inline size_t
|
|
111
|
+
calculate_cobhan_buffer_size_bytes(size_t data_len_bytes) {
|
|
112
|
+
return data_len_bytes + cobhan_header_size_bytes + safety_padding_bytes +
|
|
113
|
+
1; // Add one for possible NULL delimiter due to Node string functions
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
__attribute__((always_inline)) inline size_t
|
|
117
|
+
estimate_asherah_output_size_bytes(size_t data_byte_len,
|
|
118
|
+
size_t partition_byte_len) {
|
|
119
|
+
// Add one rather than using std::ceil to round up
|
|
120
|
+
double est_data_byte_len =
|
|
121
|
+
(double(data_byte_len + est_encryption_overhead) * base64_overhead) + 1;
|
|
122
|
+
|
|
123
|
+
size_t asherah_output_size_bytes =
|
|
124
|
+
size_t(est_envelope_overhead + est_intermediate_key_overhead +
|
|
125
|
+
partition_byte_len + est_data_byte_len + safety_padding_bytes);
|
|
126
|
+
if (unlikely(verbose_flag)) {
|
|
127
|
+
std::string log_msg =
|
|
128
|
+
"estimate_asherah_output_size(" + std::to_string(data_byte_len) + ", " +
|
|
129
|
+
std::to_string(partition_byte_len) +
|
|
130
|
+
") est_data_byte_len: " + std::to_string(est_data_byte_len) +
|
|
131
|
+
" asherah_output_size_bytes: " +
|
|
132
|
+
std::to_string(asherah_output_size_bytes);
|
|
133
|
+
debug_log("estimate_asherah_output_size", log_msg);
|
|
134
|
+
}
|
|
135
|
+
return asherah_output_size_bytes;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
__attribute__((always_inline)) inline void configure_cbuffer(char *buffer,
|
|
139
|
+
size_t length) {
|
|
140
|
+
*((int32_t *)buffer) = length;
|
|
141
|
+
// Reserved for future use
|
|
142
|
+
*((int32_t *)(buffer + sizeof(int32_t))) = 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
__attribute__((always_inline)) inline std::unique_ptr<char[]>
|
|
146
|
+
heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
|
|
147
|
+
size_t cobhan_buffer_size_bytes =
|
|
148
|
+
calculate_cobhan_buffer_size_bytes(size_bytes);
|
|
149
|
+
if (unlikely(verbose_flag)) {
|
|
150
|
+
std::string log_msg =
|
|
151
|
+
"heap_allocate_cbuffer(" + std::to_string(size_bytes) +
|
|
152
|
+
") (heap) cobhan_buffer_size_bytes: " +
|
|
153
|
+
std::to_string(cobhan_buffer_size_bytes) + " for " + variable_name;
|
|
154
|
+
debug_log("allocate_cbuffer", log_msg);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
char *cobhan_buffer = new (std::nothrow) char[cobhan_buffer_size_bytes];
|
|
158
|
+
if (unlikely(cobhan_buffer == nullptr)) {
|
|
159
|
+
std::string error_msg =
|
|
160
|
+
"new[" + std::to_string(cobhan_buffer_size_bytes) + " returned null";
|
|
161
|
+
error_log("allocate_cbuffer", error_msg);
|
|
162
|
+
return nullptr;
|
|
163
|
+
}
|
|
164
|
+
std::unique_ptr<char[]> cobhan_buffer_unique_ptr(cobhan_buffer);
|
|
165
|
+
configure_cbuffer(cobhan_buffer, size_bytes + safety_padding_bytes);
|
|
166
|
+
return cobhan_buffer_unique_ptr;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
__attribute__((always_inline)) inline Napi::Value
|
|
170
|
+
cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
|
|
171
|
+
napi_value output;
|
|
172
|
+
|
|
173
|
+
// Using C function because it allows length delimited input
|
|
174
|
+
napi_status status = napi_create_string_utf8(
|
|
175
|
+
env, ((const char *)cobhan_buffer) + cobhan_header_size_bytes,
|
|
176
|
+
*((int *)cobhan_buffer), &output);
|
|
177
|
+
|
|
178
|
+
if (unlikely(status != napi_ok)) {
|
|
179
|
+
return LogErrorAndThrow(env, "cbuffer_to_nstring",
|
|
180
|
+
"napi_create_string_utf8 failed: " +
|
|
181
|
+
napi_status_to_string(status));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return Napi::String(env, output);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
__attribute__((always_inline)) inline size_t
|
|
188
|
+
nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
|
|
189
|
+
napi_status status;
|
|
190
|
+
size_t utf8_length;
|
|
191
|
+
|
|
192
|
+
status = napi_get_value_string_utf8(env, str, nullptr, 0, &utf8_length);
|
|
193
|
+
if (unlikely(status != napi_ok)) {
|
|
194
|
+
LogErrorAndThrow(env, "nstring_utf8_length",
|
|
195
|
+
"napi_get_value_string_utf8 length check failed: " +
|
|
196
|
+
napi_status_to_string(status));
|
|
197
|
+
return (size_t)(-1);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return utf8_length;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
__attribute__((always_inline)) inline char *
|
|
204
|
+
copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
|
|
205
|
+
size_t utf8_byte_length, char *cobhan_buffer,
|
|
206
|
+
size_t *byte_length = nullptr) {
|
|
207
|
+
napi_status status;
|
|
208
|
+
size_t copied_bytes;
|
|
209
|
+
status = napi_get_value_string_utf8(env, str,
|
|
210
|
+
cobhan_buffer + cobhan_header_size_bytes,
|
|
211
|
+
utf8_byte_length + 1, &copied_bytes);
|
|
212
|
+
if (unlikely(status != napi_ok)) {
|
|
213
|
+
LogErrorAndThrow(env, "copy_nstring_to_cbuffer",
|
|
214
|
+
"Napi utf8 string conversion failure: " +
|
|
215
|
+
napi_status_to_string(status));
|
|
216
|
+
return nullptr;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (unlikely(copied_bytes != utf8_byte_length)) {
|
|
220
|
+
LogErrorAndThrow(env, "copy_nstring_to_cbuffer",
|
|
221
|
+
"Did not copy expected number of bytes " +
|
|
222
|
+
std::to_string(utf8_byte_length) + " copied " +
|
|
223
|
+
std::to_string(copied_bytes));
|
|
224
|
+
return nullptr;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
configure_cbuffer(cobhan_buffer, copied_bytes);
|
|
228
|
+
|
|
229
|
+
if (byte_length != nullptr)
|
|
230
|
+
*byte_length = copied_bytes;
|
|
231
|
+
return cobhan_buffer;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
__attribute__((always_inline)) inline Napi::Buffer<unsigned char>
|
|
235
|
+
cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
|
|
236
|
+
return Napi::Buffer<unsigned char>::Copy(
|
|
237
|
+
env, ((unsigned char *)cobhan_buffer) + cobhan_header_size_bytes,
|
|
238
|
+
*((int *)cobhan_buffer));
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
void setup(const Napi::CallbackInfo &info) {
|
|
242
|
+
Napi::Env env = info.Env();
|
|
243
|
+
|
|
244
|
+
if (unlikely(verbose_flag)) {
|
|
245
|
+
debug_log("setup", "called");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (unlikely(setup_state == 1)) {
|
|
249
|
+
LogErrorAndThrow(env, "setup", "setup called twice");
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (unlikely(info.Length() < 1)) {
|
|
254
|
+
LogErrorAndThrow(env, "setup", "Wrong number of arguments");
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
Napi::String config;
|
|
259
|
+
Napi::Object config_json;
|
|
260
|
+
Napi::Object json = env.Global().Get("JSON").As<Napi::Object>();
|
|
261
|
+
if (likely(info[0].IsObject())) {
|
|
262
|
+
config_json = info[0].As<Napi::Object>();
|
|
263
|
+
Napi::Function stringify = json.Get("stringify").As<Napi::Function>();
|
|
264
|
+
config = stringify.Call(json, {config_json}).As<Napi::String>();
|
|
265
|
+
} else if (likely(info[0].IsString())) {
|
|
266
|
+
config = info[0].As<Napi::String>();
|
|
267
|
+
Napi::Function parse = json.Get("parse").As<Napi::Function>();
|
|
268
|
+
config_json = parse.Call(json, {config}).As<Napi::Object>();
|
|
269
|
+
} else {
|
|
270
|
+
LogErrorAndThrow(env, "setup", "Wrong argument type");
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
Napi::String product_id = config_json.Get("ProductID").As<Napi::String>();
|
|
275
|
+
Napi::String service_name = config_json.Get("ServiceName").As<Napi::String>();
|
|
276
|
+
|
|
277
|
+
est_intermediate_key_overhead =
|
|
278
|
+
product_id.Utf8Value().length() + service_name.Utf8Value().length();
|
|
279
|
+
|
|
280
|
+
Napi::Value verbose = config_json.Get("Verbose");
|
|
281
|
+
if (likely(verbose.IsBoolean())) {
|
|
282
|
+
verbose_flag = verbose.As<Napi::Boolean>().Value();
|
|
283
|
+
debug_log("setup", "verbose_flag: " + std::to_string(verbose_flag));
|
|
284
|
+
} else {
|
|
285
|
+
verbose_flag = 0;
|
|
286
|
+
debug_log("setup", "verbose_flag: defaulting to false");
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Determine size
|
|
290
|
+
size_t config_utf8_byte_length;
|
|
291
|
+
config_utf8_byte_length = nstring_utf8_byte_length(env, config);
|
|
292
|
+
if (unlikely(config_utf8_byte_length == (size_t)(-1))) {
|
|
293
|
+
LogErrorAndThrow(env, "setup", "Failed to get config utf8 length");
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Allocate
|
|
298
|
+
char *config_cobhan_buffer;
|
|
299
|
+
std::unique_ptr<char[]> config_cobhan_buffer_unique_ptr;
|
|
300
|
+
if (config_utf8_byte_length < max_stack_alloc_size) {
|
|
301
|
+
// If the buffer is small enough, allocate it on the stack
|
|
302
|
+
size_t config_cobhan_buffer_size_bytes =
|
|
303
|
+
calculate_cobhan_buffer_size_bytes(config_utf8_byte_length);
|
|
304
|
+
debug_log_alloca("setup", "config_cobhan_buffer", config_cobhan_buffer_size_bytes);
|
|
305
|
+
config_cobhan_buffer = (char *)alloca(config_cobhan_buffer_size_bytes);
|
|
306
|
+
} else {
|
|
307
|
+
// Otherwise, allocate it on the heap
|
|
308
|
+
config_cobhan_buffer_unique_ptr =
|
|
309
|
+
heap_allocate_cbuffer("config_cobhan_buffer", config_utf8_byte_length);
|
|
310
|
+
config_cobhan_buffer = config_cobhan_buffer_unique_ptr.get();
|
|
311
|
+
}
|
|
312
|
+
if (unlikely(config_cobhan_buffer == nullptr)) {
|
|
313
|
+
LogErrorAndThrow(env, "setup", "Failed to allocate config cobhan buffer");
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Copy
|
|
318
|
+
size_t config_copied_bytes;
|
|
319
|
+
config_cobhan_buffer =
|
|
320
|
+
copy_nstring_to_cbuffer(env, config, config_utf8_byte_length,
|
|
321
|
+
config_cobhan_buffer, &config_copied_bytes);
|
|
322
|
+
if (unlikely(config_cobhan_buffer == nullptr)) {
|
|
323
|
+
LogErrorAndThrow(env, "setup", "Failed to copy config to cobhan buffer");
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (unlikely(verbose_flag)) {
|
|
328
|
+
debug_log("setup", "Calling asherah-cobhan SetupJson");
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// extern GoInt32 SetupJson(void* configJson);
|
|
332
|
+
GoInt32 result = SetupJson(config_cobhan_buffer);
|
|
333
|
+
|
|
334
|
+
if (unlikely(verbose_flag)) {
|
|
335
|
+
debug_log("setup", "Returned from asherah-cobhan SetupJson");
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (unlikely(result < 0)) {
|
|
339
|
+
// TODO: Convert this to a proper error message
|
|
340
|
+
LogErrorAndThrow(env, "setup", std::to_string(result));
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
setup_state = 1;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
|
|
347
|
+
size_t data_bytes, char *partition_id_cobhan_buffer,
|
|
348
|
+
char *input_cobhan_buffer) {
|
|
349
|
+
|
|
350
|
+
size_t asherah_output_size_bytes =
|
|
351
|
+
estimate_asherah_output_size_bytes(data_bytes, partition_bytes);
|
|
352
|
+
|
|
353
|
+
if (unlikely(verbose_flag)) {
|
|
354
|
+
debug_log("encrypt_to_json", " asherah_output_size_bytes " +
|
|
355
|
+
std::to_string(asherah_output_size_bytes));
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
char *output_cobhan_buffer;
|
|
359
|
+
std::unique_ptr<char[]> output_cobhan_buffer_unique_ptr;
|
|
360
|
+
if (asherah_output_size_bytes < max_stack_alloc_size) {
|
|
361
|
+
// If the buffer is small enough, allocate it on the stack
|
|
362
|
+
size_t output_cobhan_buffer_size_bytes =
|
|
363
|
+
calculate_cobhan_buffer_size_bytes(asherah_output_size_bytes);
|
|
364
|
+
debug_log_alloca("encrypt_to_json", "output_cobhan_buffer",
|
|
365
|
+
output_cobhan_buffer_size_bytes);
|
|
366
|
+
output_cobhan_buffer = (char *)alloca(output_cobhan_buffer_size_bytes);
|
|
367
|
+
configure_cbuffer(output_cobhan_buffer,
|
|
368
|
+
asherah_output_size_bytes + safety_padding_bytes);
|
|
369
|
+
} else {
|
|
370
|
+
// Otherwise, allocate it on the heap
|
|
371
|
+
output_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
|
|
372
|
+
"output_cobhan_buffer", asherah_output_size_bytes);
|
|
373
|
+
output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
|
|
374
|
+
}
|
|
375
|
+
if (unlikely(output_cobhan_buffer == nullptr)) {
|
|
376
|
+
return LogErrorAndThrow(env, "encrypt_to_json",
|
|
377
|
+
"Failed to allocate cobhan output buffer");
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (unlikely(verbose_flag)) {
|
|
381
|
+
debug_log("encrypt_to_json", "Calling asherah-cobhan EncryptToJson");
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// extern GoInt32 EncryptToJson(void* partitionIdPtr, void* dataPtr, void*
|
|
385
|
+
// jsonPtr);
|
|
386
|
+
GoInt32 result = EncryptToJson(partition_id_cobhan_buffer,
|
|
387
|
+
input_cobhan_buffer, output_cobhan_buffer);
|
|
388
|
+
|
|
389
|
+
if (unlikely(verbose_flag)) {
|
|
390
|
+
debug_log("encrypt_to_json", "Returning from asherah-cobhan EncryptToJson");
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (unlikely(result < 0)) {
|
|
394
|
+
// TODO: Convert this to a proper error message
|
|
395
|
+
return LogErrorAndThrow(env, "encrypt_to_json", std::to_string(result));
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
Napi::Value output = cbuffer_to_nstring(env, output_cobhan_buffer);
|
|
399
|
+
return output;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
Napi::Value encrypt(const Napi::CallbackInfo &info) {
|
|
403
|
+
Napi::Env env = info.Env();
|
|
404
|
+
|
|
405
|
+
if (unlikely(verbose_flag)) {
|
|
406
|
+
debug_log("encrypt", "called");
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (unlikely(setup_state == 0)) {
|
|
410
|
+
return LogErrorAndThrow(env, "encrypt", "setup() not called");
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (unlikely(info.Length() < 2)) {
|
|
414
|
+
return LogErrorAndThrow(env, "encrypt", "Wrong number of arguments");
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (unlikely(!info[0].IsString() || !info[1].IsBuffer())) {
|
|
418
|
+
return LogErrorAndThrow(env, "encrypt", "Wrong argument types");
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Determine size
|
|
422
|
+
size_t partition_utf8_byte_length;
|
|
423
|
+
Napi::String partition_id = info[0].As<Napi::String>();
|
|
424
|
+
partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
|
|
425
|
+
if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
|
|
426
|
+
return LogErrorAndThrow(env, "encrypt",
|
|
427
|
+
"Failed to get partition_id utf8 length");
|
|
428
|
+
}
|
|
429
|
+
if (unlikely(partition_utf8_byte_length == 0)) {
|
|
430
|
+
return LogErrorAndThrow(env, "encrypt", "partition_id is empty");
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Allocate
|
|
434
|
+
char *partition_id_cobhan_buffer;
|
|
435
|
+
std::unique_ptr<char[]> partition_id_cobhan_buffer_unique_ptr;
|
|
436
|
+
if (partition_utf8_byte_length < max_stack_alloc_size) {
|
|
437
|
+
// If the buffer is small enough, allocate it on the stack
|
|
438
|
+
size_t partition_id_cobhan_buffer_size_bytes =
|
|
439
|
+
calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
|
|
440
|
+
debug_log_alloca("encrypt", "partition_id_cobhan_buffer", partition_id_cobhan_buffer_size_bytes);
|
|
441
|
+
partition_id_cobhan_buffer = (char *)alloca(partition_id_cobhan_buffer_size_bytes);
|
|
442
|
+
} else {
|
|
443
|
+
// Otherwise, allocate it on the heap
|
|
444
|
+
partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
|
|
445
|
+
"partition_id_cobhan_buffer", partition_utf8_byte_length);
|
|
446
|
+
partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
|
|
447
|
+
}
|
|
448
|
+
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
449
|
+
return LogErrorAndThrow(env, "encrypt",
|
|
450
|
+
"Failed to allocate partitionId cobhan buffer");
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Copy
|
|
454
|
+
size_t partition_copied_bytes;
|
|
455
|
+
partition_id_cobhan_buffer = copy_nstring_to_cbuffer(
|
|
456
|
+
env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
|
|
457
|
+
&partition_copied_bytes);
|
|
458
|
+
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
459
|
+
return LogErrorAndThrow(env, "encrypt",
|
|
460
|
+
"Failed to copy partitionId to cobhan buffer");
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Determine size
|
|
464
|
+
Napi::Buffer<unsigned char> input_napi_buffer =
|
|
465
|
+
info[1].As<Napi::Buffer<unsigned char>>();
|
|
466
|
+
size_t input_byte_length = input_napi_buffer.ByteLength();
|
|
467
|
+
if (unlikely(input_byte_length == 0)) {
|
|
468
|
+
return LogErrorAndThrow(env, "encrypt", "input is empty");
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Allocate
|
|
472
|
+
char *input_cobhan_buffer;
|
|
473
|
+
std::unique_ptr<char[]> input_buffer_unique_ptr;
|
|
474
|
+
if (input_byte_length < max_stack_alloc_size) {
|
|
475
|
+
// If the buffer is small enough, allocate it on the stack
|
|
476
|
+
size_t input_cobhan_buffer_size_bytes =
|
|
477
|
+
calculate_cobhan_buffer_size_bytes(input_byte_length);
|
|
478
|
+
debug_log_alloca("encrypt", "input_cobhan_buffer",
|
|
479
|
+
input_cobhan_buffer_size_bytes);
|
|
480
|
+
input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
|
|
481
|
+
} else {
|
|
482
|
+
// Otherwise, allocate it on the heap
|
|
483
|
+
input_buffer_unique_ptr =
|
|
484
|
+
heap_allocate_cbuffer("input_cobhan_buffer", input_byte_length);
|
|
485
|
+
input_cobhan_buffer = input_buffer_unique_ptr.get();
|
|
486
|
+
}
|
|
487
|
+
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
488
|
+
return LogErrorAndThrow(
|
|
489
|
+
env, "encrypt", "Failed to allocate cobhan buffer for input buffer");
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Copy
|
|
493
|
+
memcpy(input_cobhan_buffer + cobhan_header_size_bytes,
|
|
494
|
+
input_napi_buffer.Data(), input_byte_length);
|
|
495
|
+
configure_cbuffer(input_cobhan_buffer, input_byte_length);
|
|
496
|
+
|
|
497
|
+
return encrypt_to_json(env, partition_copied_bytes, input_byte_length,
|
|
498
|
+
partition_id_cobhan_buffer, input_cobhan_buffer);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
|
|
502
|
+
Napi::Env env = info.Env();
|
|
503
|
+
|
|
504
|
+
if (unlikely(verbose_flag)) {
|
|
505
|
+
debug_log("encrypt_string", "called");
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (unlikely(setup_state == 0)) {
|
|
509
|
+
return LogErrorAndThrow(env, "encrypt_string", "setup() not called");
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (unlikely(info.Length() < 2)) {
|
|
513
|
+
return LogErrorAndThrow(env, "encrypt_string", "Wrong number of arguments");
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (unlikely(!info[0].IsString() || !info[1].IsString())) {
|
|
517
|
+
return LogErrorAndThrow(env, "encrypt_string", "Wrong argument types");
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Determine size
|
|
521
|
+
size_t partition_utf8_byte_length;
|
|
522
|
+
Napi::String partition_id = info[0].As<Napi::String>();
|
|
523
|
+
partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
|
|
524
|
+
if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
|
|
525
|
+
return LogErrorAndThrow(env, "encrypt_string",
|
|
526
|
+
"Failed to get partition_id utf8 length");
|
|
527
|
+
}
|
|
528
|
+
if (unlikely(partition_utf8_byte_length == 0)) {
|
|
529
|
+
return LogErrorAndThrow(env, "encrypt_string", "partition_id is empty");
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Allocate
|
|
533
|
+
char *partition_id_cobhan_buffer;
|
|
534
|
+
std::unique_ptr<char[]> partition_id_cobhan_buffer_unique_ptr;
|
|
535
|
+
if (partition_utf8_byte_length < max_stack_alloc_size) {
|
|
536
|
+
// If the buffer is small enough, allocate it on the stack
|
|
537
|
+
size_t partition_id_cobhan_buffer_size_bytes =
|
|
538
|
+
calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
|
|
539
|
+
debug_log_alloca("encrypt_string", "partition_id_cobhan_buffer",
|
|
540
|
+
partition_id_cobhan_buffer_size_bytes);
|
|
541
|
+
partition_id_cobhan_buffer = (char *)alloca(partition_id_cobhan_buffer_size_bytes);
|
|
542
|
+
} else {
|
|
543
|
+
// Otherwise, allocate it on the heap
|
|
544
|
+
partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
|
|
545
|
+
"partition_id_cobhan_buffer", partition_utf8_byte_length);
|
|
546
|
+
partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
|
|
547
|
+
}
|
|
548
|
+
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
549
|
+
return LogErrorAndThrow(env, "encrypt_string",
|
|
550
|
+
"Failed to allocate partitionId cobhan buffer");
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Copy
|
|
554
|
+
size_t partition_copied_bytes;
|
|
555
|
+
partition_id_cobhan_buffer = copy_nstring_to_cbuffer(
|
|
556
|
+
env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
|
|
557
|
+
&partition_copied_bytes);
|
|
558
|
+
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
559
|
+
return LogErrorAndThrow(env, "encrypt_string",
|
|
560
|
+
"Failed to copy partitionId to cobhan buffer");
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// Determine size
|
|
564
|
+
size_t input_utf8_byte_length;
|
|
565
|
+
Napi::String input = info[1].As<Napi::String>();
|
|
566
|
+
input_utf8_byte_length = nstring_utf8_byte_length(env, input);
|
|
567
|
+
if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
|
|
568
|
+
return LogErrorAndThrow(env, "encrypt_string",
|
|
569
|
+
"Failed to get input utf8 length");
|
|
570
|
+
}
|
|
571
|
+
if (unlikely(input_utf8_byte_length == 0)) {
|
|
572
|
+
return LogErrorAndThrow(env, "encrypt_string", "input is empty");
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// Allocate
|
|
576
|
+
char *input_cobhan_buffer;
|
|
577
|
+
std::unique_ptr<char[]> input_cobhan_buffer_unique_ptr;
|
|
578
|
+
if (input_utf8_byte_length < max_stack_alloc_size) {
|
|
579
|
+
// If the buffer is small enough, allocate it on the stack
|
|
580
|
+
size_t input_cobhan_buffer_size_bytes =
|
|
581
|
+
calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
|
|
582
|
+
debug_log_alloca("encrypt_string", "input_cobhan_buffer", input_cobhan_buffer_size_bytes);
|
|
583
|
+
input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
|
|
584
|
+
} else {
|
|
585
|
+
// Otherwise, allocate it on the heap
|
|
586
|
+
input_cobhan_buffer_unique_ptr =
|
|
587
|
+
heap_allocate_cbuffer("input_cobhan_buffer", input_utf8_byte_length);
|
|
588
|
+
input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
|
|
589
|
+
}
|
|
590
|
+
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
591
|
+
return LogErrorAndThrow(env, "encrypt_string",
|
|
592
|
+
"Failed to allocate input cobhan buffer");
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Copy
|
|
596
|
+
size_t input_copied_bytes;
|
|
597
|
+
input_cobhan_buffer =
|
|
598
|
+
copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
|
|
599
|
+
input_cobhan_buffer, &input_copied_bytes);
|
|
600
|
+
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
601
|
+
return LogErrorAndThrow(env, "encrypt_string",
|
|
602
|
+
"Failed to copy input to cobhan buffer");
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
return encrypt_to_json(env, partition_copied_bytes, input_utf8_byte_length,
|
|
606
|
+
partition_id_cobhan_buffer, input_cobhan_buffer);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
610
|
+
Napi::Env env = info.Env();
|
|
611
|
+
|
|
612
|
+
if (unlikely(verbose_flag)) {
|
|
613
|
+
debug_log("decrypt", "called");
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (unlikely(setup_state == 0)) {
|
|
617
|
+
return LogErrorAndThrow(env, "decrypt", "setup() not called");
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
if (unlikely(info.Length() < 2)) {
|
|
621
|
+
return LogErrorAndThrow(env, "decrypt", "Wrong number of arguments");
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
if (unlikely(!info[0].IsString() || !info[1].IsString())) {
|
|
625
|
+
return LogErrorAndThrow(env, "decrypt", "Wrong argument types");
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Determine size
|
|
629
|
+
size_t partition_utf8_byte_length, partition_copied_bytes;
|
|
630
|
+
Napi::String partition_id = info[0].As<Napi::String>();
|
|
631
|
+
partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
|
|
632
|
+
if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
|
|
633
|
+
return LogErrorAndThrow(env, "decrypt",
|
|
634
|
+
"Failed to get partition_id utf8 length");
|
|
635
|
+
}
|
|
636
|
+
if (unlikely(partition_utf8_byte_length == 0)) {
|
|
637
|
+
return LogErrorAndThrow(env, "decrypt", "partition_id is empty");
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// Allocate
|
|
641
|
+
char *partition_id_cobhan_buffer;
|
|
642
|
+
std::unique_ptr<char[]> partition_id_cobhan_buffer_unique_ptr;
|
|
643
|
+
if (partition_utf8_byte_length < max_stack_alloc_size) {
|
|
644
|
+
// If the buffer is small enough, allocate it on the stack
|
|
645
|
+
size_t partition_id_cobhan_buffer_size_bytes =
|
|
646
|
+
calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
|
|
647
|
+
debug_log_alloca("decrypt", "partition_id_cobhan_buffer",
|
|
648
|
+
partition_id_cobhan_buffer_size_bytes);
|
|
649
|
+
partition_id_cobhan_buffer =
|
|
650
|
+
(char *)alloca(partition_id_cobhan_buffer_size_bytes);
|
|
651
|
+
} else {
|
|
652
|
+
// Otherwise, allocate it on the heap
|
|
653
|
+
partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
|
|
654
|
+
"partition_id_cobhan_buffer", partition_utf8_byte_length);
|
|
655
|
+
partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
|
|
656
|
+
}
|
|
657
|
+
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
658
|
+
return LogErrorAndThrow(env, "decrypt",
|
|
659
|
+
"Failed to allocate partition_id cobhan buffer");
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// Copy
|
|
663
|
+
partition_id_cobhan_buffer = copy_nstring_to_cbuffer(
|
|
664
|
+
env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
|
|
665
|
+
&partition_copied_bytes);
|
|
666
|
+
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
667
|
+
return LogErrorAndThrow(env, "decrypt",
|
|
668
|
+
"Failed to copy partition_id to cobhan buffer");
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// Determine size
|
|
672
|
+
size_t input_utf8_byte_length;
|
|
673
|
+
Napi::String input = info[1].As<Napi::String>();
|
|
674
|
+
input_utf8_byte_length = nstring_utf8_byte_length(env, input);
|
|
675
|
+
if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
|
|
676
|
+
return LogErrorAndThrow(env, "decrypt", "Failed to get input utf8 length");
|
|
677
|
+
}
|
|
678
|
+
if (unlikely(input_utf8_byte_length == 0)) {
|
|
679
|
+
return LogErrorAndThrow(env, "decrypt", "input is empty");
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (unlikely(verbose_flag)) {
|
|
683
|
+
debug_log("decrypt",
|
|
684
|
+
"input size " + std::to_string(input_utf8_byte_length));
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// Allocate
|
|
688
|
+
char *input_cobhan_buffer;
|
|
689
|
+
std::unique_ptr<char[]> input_cobhan_buffer_unique_ptr;
|
|
690
|
+
if (input_utf8_byte_length < max_stack_alloc_size) {
|
|
691
|
+
// If the buffer is small enough, allocate it on the stack
|
|
692
|
+
size_t input_cobhan_buffer_size_bytes =
|
|
693
|
+
calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
|
|
694
|
+
debug_log_alloca("decrypt", "input_cobhan_buffer",
|
|
695
|
+
input_cobhan_buffer_size_bytes);
|
|
696
|
+
input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
|
|
697
|
+
} else {
|
|
698
|
+
// Otherwise, allocate it on the heap
|
|
699
|
+
input_cobhan_buffer_unique_ptr =
|
|
700
|
+
heap_allocate_cbuffer("input_cobhan_buffer", input_utf8_byte_length);
|
|
701
|
+
input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
|
|
702
|
+
}
|
|
703
|
+
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
704
|
+
return LogErrorAndThrow(env, "decrypt",
|
|
705
|
+
"Failed to allocate input cobhan buffer");
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// Copy
|
|
709
|
+
size_t input_copied_bytes;
|
|
710
|
+
input_cobhan_buffer =
|
|
711
|
+
copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
|
|
712
|
+
input_cobhan_buffer, &input_copied_bytes);
|
|
713
|
+
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
714
|
+
return LogErrorAndThrow(env, "decrypt",
|
|
715
|
+
"Failed to copy input to cobhan buffer");
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
char *output_cobhan_buffer;
|
|
719
|
+
std::unique_ptr<char[]> output_cobhan_buffer_unique_ptr;
|
|
720
|
+
if (input_utf8_byte_length < max_stack_alloc_size) {
|
|
721
|
+
// If the buffer is small enough, allocate it on the stack
|
|
722
|
+
size_t output_cobhan_buffer_size_bytes =
|
|
723
|
+
calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
|
|
724
|
+
debug_log_alloca("decrypt", "output_cobhan_buffer",
|
|
725
|
+
output_cobhan_buffer_size_bytes);
|
|
726
|
+
output_cobhan_buffer = (char *)alloca(output_cobhan_buffer_size_bytes);
|
|
727
|
+
configure_cbuffer(output_cobhan_buffer, input_utf8_byte_length);
|
|
728
|
+
} else {
|
|
729
|
+
// Otherwise, allocate it on the heap
|
|
730
|
+
output_cobhan_buffer_unique_ptr =
|
|
731
|
+
heap_allocate_cbuffer("output_cobhan_buffer", input_utf8_byte_length);
|
|
732
|
+
output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
|
|
733
|
+
}
|
|
734
|
+
if (unlikely(output_cobhan_buffer == nullptr)) {
|
|
735
|
+
return LogErrorAndThrow(env, "decrypt",
|
|
736
|
+
"Failed to allocate cobhan output buffer");
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
if (unlikely(verbose_flag)) {
|
|
740
|
+
debug_log("decrypt", "Calling asherah-cobhan DecryptFromJson");
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr, void*
|
|
744
|
+
// dataPtr);
|
|
745
|
+
GoInt32 result = DecryptFromJson(partition_id_cobhan_buffer,
|
|
746
|
+
input_cobhan_buffer, output_cobhan_buffer);
|
|
747
|
+
|
|
748
|
+
if (unlikely(verbose_flag)) {
|
|
749
|
+
debug_log("decrypt", "Returned from asherah-cobhan DecryptFromJson");
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
if (unlikely(result < 0)) {
|
|
753
|
+
// TODO: Convert this to a proper error message
|
|
754
|
+
return LogErrorAndThrow(env, "decrypt", std::to_string(result));
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
return cbuffer_to_nbuffer(env, output_cobhan_buffer);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
761
|
+
Napi::Env env = info.Env();
|
|
762
|
+
|
|
763
|
+
if (unlikely(verbose_flag)) {
|
|
764
|
+
debug_log("decrypt_string", "called");
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
if (unlikely(setup_state == 0)) {
|
|
768
|
+
return LogErrorAndThrow(env, "decrypt_string", "setup() not called");
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
if (unlikely(info.Length() < 2)) {
|
|
772
|
+
return LogErrorAndThrow(env, "decrypt_string", "Wrong number of arguments");
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if (unlikely(!info[0].IsString() || !info[1].IsString())) {
|
|
776
|
+
return LogErrorAndThrow(env, "decrypt_string", "Wrong argument types");
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// Determine size
|
|
780
|
+
size_t partition_utf8_byte_length;
|
|
781
|
+
Napi::String partition_id = info[0].As<Napi::String>();
|
|
782
|
+
partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
|
|
783
|
+
if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
|
|
784
|
+
return LogErrorAndThrow(env, "decrypt_string",
|
|
785
|
+
"Failed to get partition_id utf8 length");
|
|
786
|
+
}
|
|
787
|
+
if (unlikely(partition_utf8_byte_length == 0)) {
|
|
788
|
+
return LogErrorAndThrow(env, "decrypt_string", "partition_id is empty");
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// Allocate
|
|
792
|
+
char *partition_id_cobhan_buffer;
|
|
793
|
+
std::unique_ptr<char[]> partition_id_cobhan_buffer_unique_ptr;
|
|
794
|
+
if (partition_utf8_byte_length < max_stack_alloc_size) {
|
|
795
|
+
// If the buffer is small enough, allocate it on the stack
|
|
796
|
+
size_t partition_id_cobhan_buffer_size_bytes =
|
|
797
|
+
calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
|
|
798
|
+
debug_log_alloca("decrypt_string", "partition_id_cobhan_buffer",
|
|
799
|
+
partition_id_cobhan_buffer_size_bytes);
|
|
800
|
+
partition_id_cobhan_buffer =
|
|
801
|
+
(char *)alloca(partition_id_cobhan_buffer_size_bytes);
|
|
802
|
+
} else {
|
|
803
|
+
// Otherwise, allocate it on the heap
|
|
804
|
+
partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
|
|
805
|
+
"partition_id_cobhan_buffer", partition_utf8_byte_length);
|
|
806
|
+
partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
|
|
807
|
+
}
|
|
808
|
+
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
809
|
+
return LogErrorAndThrow(env, "decrypt_string",
|
|
810
|
+
"Failed to allocate partitionId cobhan buffer");
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// Copy
|
|
814
|
+
size_t partition_copied_bytes;
|
|
815
|
+
partition_id_cobhan_buffer = copy_nstring_to_cbuffer(
|
|
816
|
+
env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
|
|
817
|
+
&partition_copied_bytes);
|
|
818
|
+
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
819
|
+
return LogErrorAndThrow(env, "decrypt_string",
|
|
820
|
+
"Failed to copy partitionId to cobhan buffer");
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// Determine size
|
|
824
|
+
size_t input_utf8_byte_length;
|
|
825
|
+
Napi::String input = info[1].As<Napi::String>();
|
|
826
|
+
input_utf8_byte_length = nstring_utf8_byte_length(env, input);
|
|
827
|
+
if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
|
|
828
|
+
return LogErrorAndThrow(env, "decrypt_string",
|
|
829
|
+
"Failed to get input utf8 length");
|
|
830
|
+
}
|
|
831
|
+
if (unlikely(input_utf8_byte_length == 0)) {
|
|
832
|
+
return LogErrorAndThrow(env, "decrypt_string", "input is empty");
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// Allocate
|
|
836
|
+
char *input_cobhan_buffer;
|
|
837
|
+
std::unique_ptr<char[]> input_cobhan_buffer_unique_ptr;
|
|
838
|
+
if (input_utf8_byte_length < max_stack_alloc_size) {
|
|
839
|
+
// If the buffer is small enough, allocate it on the stack
|
|
840
|
+
size_t input_cobhan_buffer_size_bytes =
|
|
841
|
+
calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
|
|
842
|
+
debug_log_alloca("decrypt_string", "input_cobhan_buffer",
|
|
843
|
+
input_cobhan_buffer_size_bytes);
|
|
844
|
+
input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
|
|
845
|
+
} else {
|
|
846
|
+
// Otherwise, allocate it on the heap
|
|
847
|
+
input_cobhan_buffer_unique_ptr =
|
|
848
|
+
heap_allocate_cbuffer("input_cobhan_buffer", input_utf8_byte_length);
|
|
849
|
+
input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
|
|
850
|
+
}
|
|
851
|
+
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
852
|
+
return LogErrorAndThrow(env, "decrypt_string",
|
|
853
|
+
"Failed to allocate input cobhan buffer");
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// Copy
|
|
857
|
+
size_t input_copied_bytes;
|
|
858
|
+
input_cobhan_buffer =
|
|
859
|
+
copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
|
|
860
|
+
input_cobhan_buffer, &input_copied_bytes);
|
|
861
|
+
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
862
|
+
return LogErrorAndThrow(env, "decrypt_string",
|
|
863
|
+
"Failed to copy input to cobhan buffer");
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
char *output_cobhan_buffer;
|
|
867
|
+
std::unique_ptr<char[]> output_cobhan_buffer_unique_ptr;
|
|
868
|
+
if (input_utf8_byte_length < max_stack_alloc_size) {
|
|
869
|
+
// If the buffer is small enough, allocate it on the stack
|
|
870
|
+
size_t output_cobhan_buffer_size_bytes =
|
|
871
|
+
calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
|
|
872
|
+
debug_log_alloca("decrypt_string", "output_cobhan_buffer",
|
|
873
|
+
output_cobhan_buffer_size_bytes);
|
|
874
|
+
output_cobhan_buffer = (char *)alloca(output_cobhan_buffer_size_bytes);
|
|
875
|
+
configure_cbuffer(output_cobhan_buffer, input_utf8_byte_length);
|
|
876
|
+
} else {
|
|
877
|
+
// Otherwise, allocate it on the heap
|
|
878
|
+
output_cobhan_buffer_unique_ptr =
|
|
879
|
+
heap_allocate_cbuffer("output_cobhan_buffer", input_utf8_byte_length);
|
|
880
|
+
output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
|
|
881
|
+
}
|
|
882
|
+
if (unlikely(output_cobhan_buffer == nullptr)) {
|
|
883
|
+
return LogErrorAndThrow(env, "decrypt_string",
|
|
884
|
+
"Failed to allocate cobhan output buffer");
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
if (unlikely(verbose_flag)) {
|
|
888
|
+
debug_log("decrypt_string", "Calling asherah-cobhan DecryptFromJson");
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr, void*
|
|
892
|
+
// dataPtr);
|
|
893
|
+
GoInt32 result = DecryptFromJson(partition_id_cobhan_buffer,
|
|
894
|
+
input_cobhan_buffer, output_cobhan_buffer);
|
|
895
|
+
|
|
896
|
+
if (unlikely(verbose_flag)) {
|
|
897
|
+
debug_log("decrypt_string", "Returned from asherah-cobhan DecryptFromJson");
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
if (unlikely(result < 0)) {
|
|
901
|
+
// TODO: Convert this to a proper error message
|
|
902
|
+
return LogErrorAndThrow(env, "decrypt_string", std::to_string(result));
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
Napi::Value output = cbuffer_to_nstring(env, output_cobhan_buffer);
|
|
906
|
+
return output;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
void shutdown(const Napi::CallbackInfo &info) {
|
|
910
|
+
if (unlikely(verbose_flag)) {
|
|
911
|
+
debug_log("shutdown", "called");
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
setup_state = 0;
|
|
915
|
+
|
|
916
|
+
if (unlikely(verbose_flag)) {
|
|
917
|
+
debug_log("shutdown", "Calling asherah-cobhan Shutdown");
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// extern void Shutdown();
|
|
921
|
+
Shutdown();
|
|
922
|
+
|
|
923
|
+
if (unlikely(verbose_flag)) {
|
|
924
|
+
debug_log("shutdown", "Returned from asherah-cobhan Shutdown");
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
void set_max_stack_alloc_item_size(const Napi::CallbackInfo &info) {
|
|
929
|
+
Napi::Env env = info.Env();
|
|
930
|
+
|
|
931
|
+
if (unlikely(verbose_flag)) {
|
|
932
|
+
debug_log("set_max_stack_alloc_item_size", "called");
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
if (unlikely(info.Length() < 1)) {
|
|
936
|
+
LogErrorAndThrow(env, "set_max_stack_alloc_item_size",
|
|
937
|
+
"Wrong number of arguments");
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
Napi::Number item_size = info[0].ToNumber();
|
|
942
|
+
|
|
943
|
+
max_stack_alloc_size = (size_t)item_size.Int32Value();
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
void set_safety_padding_overhead(const Napi::CallbackInfo &info) {
|
|
947
|
+
Napi::Env env = info.Env();
|
|
948
|
+
|
|
949
|
+
if (unlikely(verbose_flag)) {
|
|
950
|
+
debug_log("set_safety_padding_overhead", "called");
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
if (unlikely(info.Length() < 1)) {
|
|
954
|
+
LogErrorAndThrow(env, "set_safety_padding_overhead",
|
|
955
|
+
"Wrong number of arguments");
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
Napi::Number safety_padding_number = info[0].ToNumber();
|
|
960
|
+
|
|
961
|
+
safety_padding_bytes = (size_t)safety_padding_number.Int32Value();
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
965
|
+
exports.Set(Napi::String::New(env, "setup"), Napi::Function::New(env, setup));
|
|
966
|
+
exports.Set(Napi::String::New(env, "encrypt"),
|
|
967
|
+
Napi::Function::New(env, encrypt));
|
|
968
|
+
exports.Set(Napi::String::New(env, "encrypt_string"),
|
|
969
|
+
Napi::Function::New(env, encrypt_string));
|
|
970
|
+
exports.Set(Napi::String::New(env, "decrypt"),
|
|
971
|
+
Napi::Function::New(env, decrypt));
|
|
972
|
+
exports.Set(Napi::String::New(env, "decrypt_string"),
|
|
973
|
+
Napi::Function::New(env, decrypt_string));
|
|
974
|
+
exports.Set(Napi::String::New(env, "set_safety_padding_overhead"),
|
|
975
|
+
Napi::Function::New(env, set_safety_padding_overhead));
|
|
976
|
+
exports.Set(Napi::String::New(env, "set_max_stack_alloc_item_size"),
|
|
977
|
+
Napi::Function::New(env, set_max_stack_alloc_item_size));
|
|
978
|
+
exports.Set(Napi::String::New(env, "shutdown"),
|
|
979
|
+
Napi::Function::New(env, shutdown));
|
|
980
|
+
return exports;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
NODE_API_MODULE(asherah, Init)
|