asherah 1.3.12 → 1.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.gyp +6 -1
- package/package.json +8 -3
- package/src/asherah.cc +87 -301
- package/src/cobhan_napi_interop.cc +3 -0
- package/src/cobhan_napi_interop.h +240 -0
- package/src/hints.h +7 -0
- package/src/logging.cc +2 -0
- package/src/logging.h +38 -0
package/binding.gyp
CHANGED
|
@@ -18,7 +18,12 @@
|
|
|
18
18
|
'defines': [ 'NAPI_CPP_EXCEPTIONS', 'NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS' ],
|
|
19
19
|
'sources': [
|
|
20
20
|
'lib/libasherah.h',
|
|
21
|
-
'src/asherah.cc'
|
|
21
|
+
'src/asherah.cc',
|
|
22
|
+
'src/logging.cc',
|
|
23
|
+
'src/logging.h',
|
|
24
|
+
'src/cobhan_napi_interop.cc',
|
|
25
|
+
'src/cobhan_napi_interop.h',
|
|
26
|
+
'src/hints.h'
|
|
22
27
|
],
|
|
23
28
|
'libraries': [ '../lib/libasherah.a' ]
|
|
24
29
|
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "asherah",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.13",
|
|
4
4
|
"description": "Asherah envelope encryption and key rotation library",
|
|
5
5
|
"exports": {
|
|
6
6
|
"node-addons": "./dist/asherah.node"
|
|
7
7
|
},
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/
|
|
10
|
+
"url": "https://github.com/godaddy/asherah-node.git"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"preinstall": "scripts/download-libraries.sh",
|
|
14
|
-
"install": "
|
|
14
|
+
"install": "scripts/build.sh",
|
|
15
15
|
"test:mocha": "mocha",
|
|
16
16
|
"test": "nyc npm run test:mocha",
|
|
17
17
|
"posttest": "npm run lint",
|
|
@@ -23,6 +23,11 @@
|
|
|
23
23
|
"files": [
|
|
24
24
|
"binding.gyp",
|
|
25
25
|
"src/asherah.cc",
|
|
26
|
+
"src/hints.h",
|
|
27
|
+
"src/logging.h",
|
|
28
|
+
"src/logging.cc",
|
|
29
|
+
"src/cobhan_napi_interop.h",
|
|
30
|
+
"src/cobhan_napi_interop.cc",
|
|
26
31
|
"src/asherah.d.ts",
|
|
27
32
|
"scripts/download-libraries.sh",
|
|
28
33
|
"SHA256SUMS",
|
package/src/asherah.cc
CHANGED
|
@@ -1,242 +1,13 @@
|
|
|
1
1
|
#include "../lib/libasherah.h"
|
|
2
2
|
#include <iostream>
|
|
3
3
|
#define NODE_ADDON_API_DISABLE_DEPRECATED
|
|
4
|
+
#include "cobhan_napi_interop.h"
|
|
5
|
+
#include "hints.h"
|
|
6
|
+
#include "logging.h"
|
|
4
7
|
#include <napi.h>
|
|
5
8
|
|
|
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
9
|
size_t max_stack_alloc_size = 2048;
|
|
17
|
-
|
|
18
10
|
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
11
|
|
|
241
12
|
void setup(const Napi::CallbackInfo &info) {
|
|
242
13
|
Napi::Env env = info.Env();
|
|
@@ -246,12 +17,12 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
246
17
|
}
|
|
247
18
|
|
|
248
19
|
if (unlikely(setup_state == 1)) {
|
|
249
|
-
|
|
20
|
+
log_error_and_throw(env, "setup", "setup called twice");
|
|
250
21
|
return;
|
|
251
22
|
}
|
|
252
23
|
|
|
253
24
|
if (unlikely(info.Length() < 1)) {
|
|
254
|
-
|
|
25
|
+
log_error_and_throw(env, "setup", "Wrong number of arguments");
|
|
255
26
|
return;
|
|
256
27
|
}
|
|
257
28
|
|
|
@@ -267,15 +38,14 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
267
38
|
Napi::Function parse = json.Get("parse").As<Napi::Function>();
|
|
268
39
|
config_json = parse.Call(json, {config}).As<Napi::Object>();
|
|
269
40
|
} else {
|
|
270
|
-
|
|
41
|
+
log_error_and_throw(env, "setup", "Wrong argument type");
|
|
271
42
|
return;
|
|
272
43
|
}
|
|
273
44
|
|
|
274
45
|
Napi::String product_id = config_json.Get("ProductID").As<Napi::String>();
|
|
275
46
|
Napi::String service_name = config_json.Get("ServiceName").As<Napi::String>();
|
|
276
47
|
|
|
277
|
-
est_intermediate_key_overhead =
|
|
278
|
-
product_id.Utf8Value().length() + service_name.Utf8Value().length();
|
|
48
|
+
est_intermediate_key_overhead = product_id.Utf8Value().length() + service_name.Utf8Value().length();
|
|
279
49
|
|
|
280
50
|
Napi::Value verbose = config_json.Get("Verbose");
|
|
281
51
|
if (likely(verbose.IsBoolean())) {
|
|
@@ -290,7 +60,7 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
290
60
|
size_t config_utf8_byte_length;
|
|
291
61
|
config_utf8_byte_length = nstring_utf8_byte_length(env, config);
|
|
292
62
|
if (unlikely(config_utf8_byte_length == (size_t)(-1))) {
|
|
293
|
-
|
|
63
|
+
log_error_and_throw(env, "setup", "Failed to get config utf8 length");
|
|
294
64
|
return;
|
|
295
65
|
}
|
|
296
66
|
|
|
@@ -301,8 +71,10 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
301
71
|
// If the buffer is small enough, allocate it on the stack
|
|
302
72
|
size_t config_cobhan_buffer_size_bytes =
|
|
303
73
|
calculate_cobhan_buffer_size_bytes(config_utf8_byte_length);
|
|
304
|
-
debug_log_alloca("setup", "config_cobhan_buffer",
|
|
74
|
+
debug_log_alloca("setup", "config_cobhan_buffer",
|
|
75
|
+
config_cobhan_buffer_size_bytes);
|
|
305
76
|
config_cobhan_buffer = (char *)alloca(config_cobhan_buffer_size_bytes);
|
|
77
|
+
configure_cbuffer(config_cobhan_buffer, config_utf8_byte_length);
|
|
306
78
|
} else {
|
|
307
79
|
// Otherwise, allocate it on the heap
|
|
308
80
|
config_cobhan_buffer_unique_ptr =
|
|
@@ -310,7 +82,7 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
310
82
|
config_cobhan_buffer = config_cobhan_buffer_unique_ptr.get();
|
|
311
83
|
}
|
|
312
84
|
if (unlikely(config_cobhan_buffer == nullptr)) {
|
|
313
|
-
|
|
85
|
+
log_error_and_throw(env, "setup", "Failed to allocate config cobhan buffer");
|
|
314
86
|
return;
|
|
315
87
|
}
|
|
316
88
|
|
|
@@ -320,7 +92,7 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
320
92
|
copy_nstring_to_cbuffer(env, config, config_utf8_byte_length,
|
|
321
93
|
config_cobhan_buffer, &config_copied_bytes);
|
|
322
94
|
if (unlikely(config_cobhan_buffer == nullptr)) {
|
|
323
|
-
|
|
95
|
+
log_error_and_throw(env, "setup", "Failed to copy config to cobhan buffer");
|
|
324
96
|
return;
|
|
325
97
|
}
|
|
326
98
|
|
|
@@ -337,7 +109,7 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
337
109
|
|
|
338
110
|
if (unlikely(result < 0)) {
|
|
339
111
|
// TODO: Convert this to a proper error message
|
|
340
|
-
|
|
112
|
+
log_error_and_throw(env, "setup", std::to_string(result));
|
|
341
113
|
return;
|
|
342
114
|
}
|
|
343
115
|
setup_state = 1;
|
|
@@ -364,8 +136,7 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
|
|
|
364
136
|
debug_log_alloca("encrypt_to_json", "output_cobhan_buffer",
|
|
365
137
|
output_cobhan_buffer_size_bytes);
|
|
366
138
|
output_cobhan_buffer = (char *)alloca(output_cobhan_buffer_size_bytes);
|
|
367
|
-
configure_cbuffer(output_cobhan_buffer,
|
|
368
|
-
asherah_output_size_bytes + safety_padding_bytes);
|
|
139
|
+
configure_cbuffer(output_cobhan_buffer, asherah_output_size_bytes);
|
|
369
140
|
} else {
|
|
370
141
|
// Otherwise, allocate it on the heap
|
|
371
142
|
output_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
|
|
@@ -373,7 +144,7 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
|
|
|
373
144
|
output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
|
|
374
145
|
}
|
|
375
146
|
if (unlikely(output_cobhan_buffer == nullptr)) {
|
|
376
|
-
return
|
|
147
|
+
return log_error_and_throw(env, "encrypt_to_json",
|
|
377
148
|
"Failed to allocate cobhan output buffer");
|
|
378
149
|
}
|
|
379
150
|
|
|
@@ -392,7 +163,7 @@ Napi::Value encrypt_to_json(Napi::Env &env, size_t partition_bytes,
|
|
|
392
163
|
|
|
393
164
|
if (unlikely(result < 0)) {
|
|
394
165
|
// TODO: Convert this to a proper error message
|
|
395
|
-
return
|
|
166
|
+
return log_error_and_throw(env, "encrypt_to_json", std::to_string(result));
|
|
396
167
|
}
|
|
397
168
|
|
|
398
169
|
Napi::Value output = cbuffer_to_nstring(env, output_cobhan_buffer);
|
|
@@ -407,15 +178,15 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
|
|
|
407
178
|
}
|
|
408
179
|
|
|
409
180
|
if (unlikely(setup_state == 0)) {
|
|
410
|
-
return
|
|
181
|
+
return log_error_and_throw(env, "encrypt", "setup() not called");
|
|
411
182
|
}
|
|
412
183
|
|
|
413
184
|
if (unlikely(info.Length() < 2)) {
|
|
414
|
-
return
|
|
185
|
+
return log_error_and_throw(env, "encrypt", "Wrong number of arguments");
|
|
415
186
|
}
|
|
416
187
|
|
|
417
188
|
if (unlikely(!info[0].IsString() || !info[1].IsBuffer())) {
|
|
418
|
-
return
|
|
189
|
+
return log_error_and_throw(env, "encrypt", "Wrong argument types");
|
|
419
190
|
}
|
|
420
191
|
|
|
421
192
|
// Determine size
|
|
@@ -423,11 +194,11 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
|
|
|
423
194
|
Napi::String partition_id = info[0].As<Napi::String>();
|
|
424
195
|
partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
|
|
425
196
|
if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
|
|
426
|
-
return
|
|
197
|
+
return log_error_and_throw(env, "encrypt",
|
|
427
198
|
"Failed to get partition_id utf8 length");
|
|
428
199
|
}
|
|
429
200
|
if (unlikely(partition_utf8_byte_length == 0)) {
|
|
430
|
-
return
|
|
201
|
+
return log_error_and_throw(env, "encrypt", "partition_id is empty");
|
|
431
202
|
}
|
|
432
203
|
|
|
433
204
|
// Allocate
|
|
@@ -437,8 +208,11 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
|
|
|
437
208
|
// If the buffer is small enough, allocate it on the stack
|
|
438
209
|
size_t partition_id_cobhan_buffer_size_bytes =
|
|
439
210
|
calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
|
|
440
|
-
debug_log_alloca("encrypt", "partition_id_cobhan_buffer",
|
|
441
|
-
|
|
211
|
+
debug_log_alloca("encrypt", "partition_id_cobhan_buffer",
|
|
212
|
+
partition_id_cobhan_buffer_size_bytes);
|
|
213
|
+
partition_id_cobhan_buffer =
|
|
214
|
+
(char *)alloca(partition_id_cobhan_buffer_size_bytes);
|
|
215
|
+
configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
|
|
442
216
|
} else {
|
|
443
217
|
// Otherwise, allocate it on the heap
|
|
444
218
|
partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
|
|
@@ -446,7 +220,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
|
|
|
446
220
|
partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
|
|
447
221
|
}
|
|
448
222
|
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
449
|
-
return
|
|
223
|
+
return log_error_and_throw(env, "encrypt",
|
|
450
224
|
"Failed to allocate partitionId cobhan buffer");
|
|
451
225
|
}
|
|
452
226
|
|
|
@@ -456,7 +230,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
|
|
|
456
230
|
env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
|
|
457
231
|
&partition_copied_bytes);
|
|
458
232
|
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
459
|
-
return
|
|
233
|
+
return log_error_and_throw(env, "encrypt",
|
|
460
234
|
"Failed to copy partitionId to cobhan buffer");
|
|
461
235
|
}
|
|
462
236
|
|
|
@@ -465,7 +239,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
|
|
|
465
239
|
info[1].As<Napi::Buffer<unsigned char>>();
|
|
466
240
|
size_t input_byte_length = input_napi_buffer.ByteLength();
|
|
467
241
|
if (unlikely(input_byte_length == 0)) {
|
|
468
|
-
return
|
|
242
|
+
return log_error_and_throw(env, "encrypt", "input is empty");
|
|
469
243
|
}
|
|
470
244
|
|
|
471
245
|
// Allocate
|
|
@@ -478,6 +252,7 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
|
|
|
478
252
|
debug_log_alloca("encrypt", "input_cobhan_buffer",
|
|
479
253
|
input_cobhan_buffer_size_bytes);
|
|
480
254
|
input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
|
|
255
|
+
configure_cbuffer(input_cobhan_buffer, input_byte_length);
|
|
481
256
|
} else {
|
|
482
257
|
// Otherwise, allocate it on the heap
|
|
483
258
|
input_buffer_unique_ptr =
|
|
@@ -485,14 +260,17 @@ Napi::Value encrypt(const Napi::CallbackInfo &info) {
|
|
|
485
260
|
input_cobhan_buffer = input_buffer_unique_ptr.get();
|
|
486
261
|
}
|
|
487
262
|
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
488
|
-
return
|
|
263
|
+
return log_error_and_throw(
|
|
489
264
|
env, "encrypt", "Failed to allocate cobhan buffer for input buffer");
|
|
490
265
|
}
|
|
491
266
|
|
|
492
267
|
// Copy
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
268
|
+
input_cobhan_buffer =
|
|
269
|
+
copy_nbuffer_to_cbuffer(env, input_napi_buffer, input_cobhan_buffer);
|
|
270
|
+
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
271
|
+
return log_error_and_throw(env, "encrypt",
|
|
272
|
+
"Failed to copy input buffer to cobhan buffer");
|
|
273
|
+
}
|
|
496
274
|
|
|
497
275
|
return encrypt_to_json(env, partition_copied_bytes, input_byte_length,
|
|
498
276
|
partition_id_cobhan_buffer, input_cobhan_buffer);
|
|
@@ -506,15 +284,15 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
506
284
|
}
|
|
507
285
|
|
|
508
286
|
if (unlikely(setup_state == 0)) {
|
|
509
|
-
return
|
|
287
|
+
return log_error_and_throw(env, "encrypt_string", "setup() not called");
|
|
510
288
|
}
|
|
511
289
|
|
|
512
290
|
if (unlikely(info.Length() < 2)) {
|
|
513
|
-
return
|
|
291
|
+
return log_error_and_throw(env, "encrypt_string", "Wrong number of arguments");
|
|
514
292
|
}
|
|
515
293
|
|
|
516
294
|
if (unlikely(!info[0].IsString() || !info[1].IsString())) {
|
|
517
|
-
return
|
|
295
|
+
return log_error_and_throw(env, "encrypt_string", "Wrong argument types");
|
|
518
296
|
}
|
|
519
297
|
|
|
520
298
|
// Determine size
|
|
@@ -522,11 +300,11 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
522
300
|
Napi::String partition_id = info[0].As<Napi::String>();
|
|
523
301
|
partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
|
|
524
302
|
if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
|
|
525
|
-
return
|
|
303
|
+
return log_error_and_throw(env, "encrypt_string",
|
|
526
304
|
"Failed to get partition_id utf8 length");
|
|
527
305
|
}
|
|
528
306
|
if (unlikely(partition_utf8_byte_length == 0)) {
|
|
529
|
-
return
|
|
307
|
+
return log_error_and_throw(env, "encrypt_string", "partition_id is empty");
|
|
530
308
|
}
|
|
531
309
|
|
|
532
310
|
// Allocate
|
|
@@ -538,7 +316,9 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
538
316
|
calculate_cobhan_buffer_size_bytes(partition_utf8_byte_length);
|
|
539
317
|
debug_log_alloca("encrypt_string", "partition_id_cobhan_buffer",
|
|
540
318
|
partition_id_cobhan_buffer_size_bytes);
|
|
541
|
-
partition_id_cobhan_buffer =
|
|
319
|
+
partition_id_cobhan_buffer =
|
|
320
|
+
(char *)alloca(partition_id_cobhan_buffer_size_bytes);
|
|
321
|
+
configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
|
|
542
322
|
} else {
|
|
543
323
|
// Otherwise, allocate it on the heap
|
|
544
324
|
partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
|
|
@@ -546,7 +326,7 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
546
326
|
partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
|
|
547
327
|
}
|
|
548
328
|
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
549
|
-
return
|
|
329
|
+
return log_error_and_throw(env, "encrypt_string",
|
|
550
330
|
"Failed to allocate partitionId cobhan buffer");
|
|
551
331
|
}
|
|
552
332
|
|
|
@@ -556,7 +336,7 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
556
336
|
env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
|
|
557
337
|
&partition_copied_bytes);
|
|
558
338
|
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
559
|
-
return
|
|
339
|
+
return log_error_and_throw(env, "encrypt_string",
|
|
560
340
|
"Failed to copy partitionId to cobhan buffer");
|
|
561
341
|
}
|
|
562
342
|
|
|
@@ -565,11 +345,11 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
565
345
|
Napi::String input = info[1].As<Napi::String>();
|
|
566
346
|
input_utf8_byte_length = nstring_utf8_byte_length(env, input);
|
|
567
347
|
if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
|
|
568
|
-
return
|
|
348
|
+
return log_error_and_throw(env, "encrypt_string",
|
|
569
349
|
"Failed to get input utf8 length");
|
|
570
350
|
}
|
|
571
351
|
if (unlikely(input_utf8_byte_length == 0)) {
|
|
572
|
-
return
|
|
352
|
+
return log_error_and_throw(env, "encrypt_string", "input is empty");
|
|
573
353
|
}
|
|
574
354
|
|
|
575
355
|
// Allocate
|
|
@@ -579,8 +359,10 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
579
359
|
// If the buffer is small enough, allocate it on the stack
|
|
580
360
|
size_t input_cobhan_buffer_size_bytes =
|
|
581
361
|
calculate_cobhan_buffer_size_bytes(input_utf8_byte_length);
|
|
582
|
-
debug_log_alloca("encrypt_string", "input_cobhan_buffer",
|
|
362
|
+
debug_log_alloca("encrypt_string", "input_cobhan_buffer",
|
|
363
|
+
input_cobhan_buffer_size_bytes);
|
|
583
364
|
input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
|
|
365
|
+
configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
|
|
584
366
|
} else {
|
|
585
367
|
// Otherwise, allocate it on the heap
|
|
586
368
|
input_cobhan_buffer_unique_ptr =
|
|
@@ -588,7 +370,7 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
588
370
|
input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
|
|
589
371
|
}
|
|
590
372
|
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
591
|
-
return
|
|
373
|
+
return log_error_and_throw(env, "encrypt_string",
|
|
592
374
|
"Failed to allocate input cobhan buffer");
|
|
593
375
|
}
|
|
594
376
|
|
|
@@ -598,7 +380,7 @@ Napi::Value encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
598
380
|
copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
|
|
599
381
|
input_cobhan_buffer, &input_copied_bytes);
|
|
600
382
|
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
601
|
-
return
|
|
383
|
+
return log_error_and_throw(env, "encrypt_string",
|
|
602
384
|
"Failed to copy input to cobhan buffer");
|
|
603
385
|
}
|
|
604
386
|
|
|
@@ -614,15 +396,15 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
614
396
|
}
|
|
615
397
|
|
|
616
398
|
if (unlikely(setup_state == 0)) {
|
|
617
|
-
return
|
|
399
|
+
return log_error_and_throw(env, "decrypt", "setup() not called");
|
|
618
400
|
}
|
|
619
401
|
|
|
620
402
|
if (unlikely(info.Length() < 2)) {
|
|
621
|
-
return
|
|
403
|
+
return log_error_and_throw(env, "decrypt", "Wrong number of arguments");
|
|
622
404
|
}
|
|
623
405
|
|
|
624
406
|
if (unlikely(!info[0].IsString() || !info[1].IsString())) {
|
|
625
|
-
return
|
|
407
|
+
return log_error_and_throw(env, "decrypt", "Wrong argument types");
|
|
626
408
|
}
|
|
627
409
|
|
|
628
410
|
// Determine size
|
|
@@ -630,11 +412,11 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
630
412
|
Napi::String partition_id = info[0].As<Napi::String>();
|
|
631
413
|
partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
|
|
632
414
|
if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
|
|
633
|
-
return
|
|
415
|
+
return log_error_and_throw(env, "decrypt",
|
|
634
416
|
"Failed to get partition_id utf8 length");
|
|
635
417
|
}
|
|
636
418
|
if (unlikely(partition_utf8_byte_length == 0)) {
|
|
637
|
-
return
|
|
419
|
+
return log_error_and_throw(env, "decrypt", "partition_id is empty");
|
|
638
420
|
}
|
|
639
421
|
|
|
640
422
|
// Allocate
|
|
@@ -648,6 +430,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
648
430
|
partition_id_cobhan_buffer_size_bytes);
|
|
649
431
|
partition_id_cobhan_buffer =
|
|
650
432
|
(char *)alloca(partition_id_cobhan_buffer_size_bytes);
|
|
433
|
+
configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
|
|
651
434
|
} else {
|
|
652
435
|
// Otherwise, allocate it on the heap
|
|
653
436
|
partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
|
|
@@ -655,7 +438,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
655
438
|
partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
|
|
656
439
|
}
|
|
657
440
|
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
658
|
-
return
|
|
441
|
+
return log_error_and_throw(env, "decrypt",
|
|
659
442
|
"Failed to allocate partition_id cobhan buffer");
|
|
660
443
|
}
|
|
661
444
|
|
|
@@ -664,7 +447,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
664
447
|
env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
|
|
665
448
|
&partition_copied_bytes);
|
|
666
449
|
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
667
|
-
return
|
|
450
|
+
return log_error_and_throw(env, "decrypt",
|
|
668
451
|
"Failed to copy partition_id to cobhan buffer");
|
|
669
452
|
}
|
|
670
453
|
|
|
@@ -673,10 +456,10 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
673
456
|
Napi::String input = info[1].As<Napi::String>();
|
|
674
457
|
input_utf8_byte_length = nstring_utf8_byte_length(env, input);
|
|
675
458
|
if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
|
|
676
|
-
return
|
|
459
|
+
return log_error_and_throw(env, "decrypt", "Failed to get input utf8 length");
|
|
677
460
|
}
|
|
678
461
|
if (unlikely(input_utf8_byte_length == 0)) {
|
|
679
|
-
return
|
|
462
|
+
return log_error_and_throw(env, "decrypt", "input is empty");
|
|
680
463
|
}
|
|
681
464
|
|
|
682
465
|
if (unlikely(verbose_flag)) {
|
|
@@ -694,6 +477,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
694
477
|
debug_log_alloca("decrypt", "input_cobhan_buffer",
|
|
695
478
|
input_cobhan_buffer_size_bytes);
|
|
696
479
|
input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
|
|
480
|
+
configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
|
|
697
481
|
} else {
|
|
698
482
|
// Otherwise, allocate it on the heap
|
|
699
483
|
input_cobhan_buffer_unique_ptr =
|
|
@@ -701,7 +485,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
701
485
|
input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
|
|
702
486
|
}
|
|
703
487
|
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
704
|
-
return
|
|
488
|
+
return log_error_and_throw(env, "decrypt",
|
|
705
489
|
"Failed to allocate input cobhan buffer");
|
|
706
490
|
}
|
|
707
491
|
|
|
@@ -711,7 +495,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
711
495
|
copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
|
|
712
496
|
input_cobhan_buffer, &input_copied_bytes);
|
|
713
497
|
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
714
|
-
return
|
|
498
|
+
return log_error_and_throw(env, "decrypt",
|
|
715
499
|
"Failed to copy input to cobhan buffer");
|
|
716
500
|
}
|
|
717
501
|
|
|
@@ -732,7 +516,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
732
516
|
output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
|
|
733
517
|
}
|
|
734
518
|
if (unlikely(output_cobhan_buffer == nullptr)) {
|
|
735
|
-
return
|
|
519
|
+
return log_error_and_throw(env, "decrypt",
|
|
736
520
|
"Failed to allocate cobhan output buffer");
|
|
737
521
|
}
|
|
738
522
|
|
|
@@ -751,7 +535,7 @@ Napi::Value decrypt(const Napi::CallbackInfo &info) {
|
|
|
751
535
|
|
|
752
536
|
if (unlikely(result < 0)) {
|
|
753
537
|
// TODO: Convert this to a proper error message
|
|
754
|
-
return
|
|
538
|
+
return log_error_and_throw(env, "decrypt", std::to_string(result));
|
|
755
539
|
}
|
|
756
540
|
|
|
757
541
|
return cbuffer_to_nbuffer(env, output_cobhan_buffer);
|
|
@@ -765,15 +549,15 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
765
549
|
}
|
|
766
550
|
|
|
767
551
|
if (unlikely(setup_state == 0)) {
|
|
768
|
-
return
|
|
552
|
+
return log_error_and_throw(env, "decrypt_string", "setup() not called");
|
|
769
553
|
}
|
|
770
554
|
|
|
771
555
|
if (unlikely(info.Length() < 2)) {
|
|
772
|
-
return
|
|
556
|
+
return log_error_and_throw(env, "decrypt_string", "Wrong number of arguments");
|
|
773
557
|
}
|
|
774
558
|
|
|
775
559
|
if (unlikely(!info[0].IsString() || !info[1].IsString())) {
|
|
776
|
-
return
|
|
560
|
+
return log_error_and_throw(env, "decrypt_string", "Wrong argument types");
|
|
777
561
|
}
|
|
778
562
|
|
|
779
563
|
// Determine size
|
|
@@ -781,11 +565,11 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
781
565
|
Napi::String partition_id = info[0].As<Napi::String>();
|
|
782
566
|
partition_utf8_byte_length = nstring_utf8_byte_length(env, partition_id);
|
|
783
567
|
if (unlikely(partition_utf8_byte_length == (size_t)(-1))) {
|
|
784
|
-
return
|
|
568
|
+
return log_error_and_throw(env, "decrypt_string",
|
|
785
569
|
"Failed to get partition_id utf8 length");
|
|
786
570
|
}
|
|
787
571
|
if (unlikely(partition_utf8_byte_length == 0)) {
|
|
788
|
-
return
|
|
572
|
+
return log_error_and_throw(env, "decrypt_string", "partition_id is empty");
|
|
789
573
|
}
|
|
790
574
|
|
|
791
575
|
// Allocate
|
|
@@ -799,6 +583,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
799
583
|
partition_id_cobhan_buffer_size_bytes);
|
|
800
584
|
partition_id_cobhan_buffer =
|
|
801
585
|
(char *)alloca(partition_id_cobhan_buffer_size_bytes);
|
|
586
|
+
configure_cbuffer(partition_id_cobhan_buffer, partition_utf8_byte_length);
|
|
802
587
|
} else {
|
|
803
588
|
// Otherwise, allocate it on the heap
|
|
804
589
|
partition_id_cobhan_buffer_unique_ptr = heap_allocate_cbuffer(
|
|
@@ -806,7 +591,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
806
591
|
partition_id_cobhan_buffer = partition_id_cobhan_buffer_unique_ptr.get();
|
|
807
592
|
}
|
|
808
593
|
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
809
|
-
return
|
|
594
|
+
return log_error_and_throw(env, "decrypt_string",
|
|
810
595
|
"Failed to allocate partitionId cobhan buffer");
|
|
811
596
|
}
|
|
812
597
|
|
|
@@ -816,7 +601,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
816
601
|
env, partition_id, partition_utf8_byte_length, partition_id_cobhan_buffer,
|
|
817
602
|
&partition_copied_bytes);
|
|
818
603
|
if (unlikely(partition_id_cobhan_buffer == nullptr)) {
|
|
819
|
-
return
|
|
604
|
+
return log_error_and_throw(env, "decrypt_string",
|
|
820
605
|
"Failed to copy partitionId to cobhan buffer");
|
|
821
606
|
}
|
|
822
607
|
|
|
@@ -825,11 +610,11 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
825
610
|
Napi::String input = info[1].As<Napi::String>();
|
|
826
611
|
input_utf8_byte_length = nstring_utf8_byte_length(env, input);
|
|
827
612
|
if (unlikely(input_utf8_byte_length == (size_t)(-1))) {
|
|
828
|
-
return
|
|
613
|
+
return log_error_and_throw(env, "decrypt_string",
|
|
829
614
|
"Failed to get input utf8 length");
|
|
830
615
|
}
|
|
831
616
|
if (unlikely(input_utf8_byte_length == 0)) {
|
|
832
|
-
return
|
|
617
|
+
return log_error_and_throw(env, "decrypt_string", "input is empty");
|
|
833
618
|
}
|
|
834
619
|
|
|
835
620
|
// Allocate
|
|
@@ -842,6 +627,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
842
627
|
debug_log_alloca("decrypt_string", "input_cobhan_buffer",
|
|
843
628
|
input_cobhan_buffer_size_bytes);
|
|
844
629
|
input_cobhan_buffer = (char *)alloca(input_cobhan_buffer_size_bytes);
|
|
630
|
+
configure_cbuffer(input_cobhan_buffer, input_utf8_byte_length);
|
|
845
631
|
} else {
|
|
846
632
|
// Otherwise, allocate it on the heap
|
|
847
633
|
input_cobhan_buffer_unique_ptr =
|
|
@@ -849,7 +635,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
849
635
|
input_cobhan_buffer = input_cobhan_buffer_unique_ptr.get();
|
|
850
636
|
}
|
|
851
637
|
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
852
|
-
return
|
|
638
|
+
return log_error_and_throw(env, "decrypt_string",
|
|
853
639
|
"Failed to allocate input cobhan buffer");
|
|
854
640
|
}
|
|
855
641
|
|
|
@@ -859,7 +645,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
859
645
|
copy_nstring_to_cbuffer(env, input, input_utf8_byte_length,
|
|
860
646
|
input_cobhan_buffer, &input_copied_bytes);
|
|
861
647
|
if (unlikely(input_cobhan_buffer == nullptr)) {
|
|
862
|
-
return
|
|
648
|
+
return log_error_and_throw(env, "decrypt_string",
|
|
863
649
|
"Failed to copy input to cobhan buffer");
|
|
864
650
|
}
|
|
865
651
|
|
|
@@ -880,7 +666,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
880
666
|
output_cobhan_buffer = output_cobhan_buffer_unique_ptr.get();
|
|
881
667
|
}
|
|
882
668
|
if (unlikely(output_cobhan_buffer == nullptr)) {
|
|
883
|
-
return
|
|
669
|
+
return log_error_and_throw(env, "decrypt_string",
|
|
884
670
|
"Failed to allocate cobhan output buffer");
|
|
885
671
|
}
|
|
886
672
|
|
|
@@ -899,7 +685,7 @@ Napi::Value decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
899
685
|
|
|
900
686
|
if (unlikely(result < 0)) {
|
|
901
687
|
// TODO: Convert this to a proper error message
|
|
902
|
-
return
|
|
688
|
+
return log_error_and_throw(env, "decrypt_string", std::to_string(result));
|
|
903
689
|
}
|
|
904
690
|
|
|
905
691
|
Napi::Value output = cbuffer_to_nstring(env, output_cobhan_buffer);
|
|
@@ -933,7 +719,7 @@ void set_max_stack_alloc_item_size(const Napi::CallbackInfo &info) {
|
|
|
933
719
|
}
|
|
934
720
|
|
|
935
721
|
if (unlikely(info.Length() < 1)) {
|
|
936
|
-
|
|
722
|
+
log_error_and_throw(env, "set_max_stack_alloc_item_size",
|
|
937
723
|
"Wrong number of arguments");
|
|
938
724
|
return;
|
|
939
725
|
}
|
|
@@ -951,7 +737,7 @@ void set_safety_padding_overhead(const Napi::CallbackInfo &info) {
|
|
|
951
737
|
}
|
|
952
738
|
|
|
953
739
|
if (unlikely(info.Length() < 1)) {
|
|
954
|
-
|
|
740
|
+
log_error_and_throw(env, "set_safety_padding_overhead",
|
|
955
741
|
"Wrong number of arguments");
|
|
956
742
|
return;
|
|
957
743
|
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
#ifndef COBHAN_NAPI_INTEROP_H
|
|
2
|
+
#define COBHAN_NAPI_INTEROP_H
|
|
3
|
+
#include <string>
|
|
4
|
+
#define NODE_ADDON_API_DISABLE_DEPRECATED
|
|
5
|
+
#include <napi.h>
|
|
6
|
+
#include "logging.h"
|
|
7
|
+
#include "hints.h"
|
|
8
|
+
|
|
9
|
+
extern size_t est_intermediate_key_overhead;
|
|
10
|
+
extern size_t safety_padding_bytes;
|
|
11
|
+
|
|
12
|
+
const size_t est_encryption_overhead = 48;
|
|
13
|
+
const size_t est_envelope_overhead = 185;
|
|
14
|
+
const double base64_overhead = 1.34;
|
|
15
|
+
|
|
16
|
+
const size_t cobhan_header_size_bytes = 64 / 8;
|
|
17
|
+
|
|
18
|
+
std::string napi_status_to_string(napi_status status) {
|
|
19
|
+
switch (status) {
|
|
20
|
+
case napi_ok:
|
|
21
|
+
return "napi_ok";
|
|
22
|
+
case napi_invalid_arg:
|
|
23
|
+
return "napi_invalid_arg";
|
|
24
|
+
case napi_object_expected:
|
|
25
|
+
return "napi_object_expected";
|
|
26
|
+
case napi_string_expected:
|
|
27
|
+
return "napi_string_expected";
|
|
28
|
+
case napi_name_expected:
|
|
29
|
+
return "napi_name_expected";
|
|
30
|
+
case napi_function_expected:
|
|
31
|
+
return "napi_function_expected";
|
|
32
|
+
case napi_number_expected:
|
|
33
|
+
return "napi_number_expected";
|
|
34
|
+
case napi_boolean_expected:
|
|
35
|
+
return "napi_boolean_expected";
|
|
36
|
+
case napi_array_expected:
|
|
37
|
+
return "napi_array_expected";
|
|
38
|
+
case napi_generic_failure:
|
|
39
|
+
return "napi_generic_failure";
|
|
40
|
+
case napi_pending_exception:
|
|
41
|
+
return "napi_pending_exception";
|
|
42
|
+
case napi_cancelled:
|
|
43
|
+
return "napi_cancelled";
|
|
44
|
+
case napi_escape_called_twice:
|
|
45
|
+
return "napi_escape_called_twice";
|
|
46
|
+
case napi_handle_scope_mismatch:
|
|
47
|
+
return "napi_handle_scope_mismatch";
|
|
48
|
+
case napi_callback_scope_mismatch:
|
|
49
|
+
return "napi_callback_scope_mismatch";
|
|
50
|
+
case napi_queue_full:
|
|
51
|
+
return "napi_queue_full";
|
|
52
|
+
case napi_closing:
|
|
53
|
+
return "napi_closing";
|
|
54
|
+
case napi_bigint_expected:
|
|
55
|
+
return "napi_bigint_expected";
|
|
56
|
+
case napi_date_expected:
|
|
57
|
+
return "napi_date_expected";
|
|
58
|
+
case napi_arraybuffer_expected:
|
|
59
|
+
return "napi_arraybuffer_expected";
|
|
60
|
+
case napi_detachable_arraybuffer_expected:
|
|
61
|
+
return "napi_detachable_arraybuffer_expected";
|
|
62
|
+
case napi_would_deadlock:
|
|
63
|
+
return "napi_would_deadlock";
|
|
64
|
+
default:
|
|
65
|
+
return "Unknown napi_status";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
__attribute__((always_inline)) inline size_t
|
|
70
|
+
cbuffer_byte_length(char *cobhan_buffer) {
|
|
71
|
+
return *((int *)cobhan_buffer);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
__attribute__((always_inline)) inline Napi::Value
|
|
75
|
+
log_error_and_throw(Napi::Env &env, const char *function_name,
|
|
76
|
+
std::string error_msg) {
|
|
77
|
+
error_log(function_name, error_msg);
|
|
78
|
+
Napi::Error::New(env, function_name + (": " + error_msg))
|
|
79
|
+
.ThrowAsJavaScriptException();
|
|
80
|
+
return env.Null();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
__attribute__((always_inline)) inline size_t
|
|
84
|
+
calculate_cobhan_buffer_size_bytes(size_t data_len_bytes) {
|
|
85
|
+
return data_len_bytes + cobhan_header_size_bytes + safety_padding_bytes +
|
|
86
|
+
1; // Add one for possible NULL delimiter due to Node string functions
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
__attribute__((always_inline)) inline size_t
|
|
90
|
+
estimate_asherah_output_size_bytes(size_t data_byte_len,
|
|
91
|
+
size_t partition_byte_len) {
|
|
92
|
+
// Add one rather than using std::ceil to round up
|
|
93
|
+
double est_data_byte_len =
|
|
94
|
+
(double(data_byte_len + est_encryption_overhead) * base64_overhead) + 1;
|
|
95
|
+
|
|
96
|
+
size_t asherah_output_size_bytes =
|
|
97
|
+
size_t(est_envelope_overhead + est_intermediate_key_overhead +
|
|
98
|
+
partition_byte_len + est_data_byte_len + safety_padding_bytes);
|
|
99
|
+
if (unlikely(verbose_flag)) {
|
|
100
|
+
std::string log_msg =
|
|
101
|
+
"estimate_asherah_output_size(" + std::to_string(data_byte_len) + ", " +
|
|
102
|
+
std::to_string(partition_byte_len) +
|
|
103
|
+
") est_data_byte_len: " + std::to_string(est_data_byte_len) +
|
|
104
|
+
" asherah_output_size_bytes: " +
|
|
105
|
+
std::to_string(asherah_output_size_bytes);
|
|
106
|
+
debug_log("estimate_asherah_output_size", log_msg);
|
|
107
|
+
}
|
|
108
|
+
return asherah_output_size_bytes;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
__attribute__((always_inline)) inline void configure_cbuffer(char *buffer,
|
|
112
|
+
size_t length) {
|
|
113
|
+
*((int32_t *)buffer) = length;
|
|
114
|
+
// Reserved for future use
|
|
115
|
+
*((int32_t *)(buffer + sizeof(int32_t))) = 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
__attribute__((always_inline)) inline std::unique_ptr<char[]>
|
|
119
|
+
heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
|
|
120
|
+
size_t cobhan_buffer_size_bytes =
|
|
121
|
+
calculate_cobhan_buffer_size_bytes(size_bytes);
|
|
122
|
+
if (unlikely(verbose_flag)) {
|
|
123
|
+
std::string log_msg =
|
|
124
|
+
"heap_allocate_cbuffer(" + std::to_string(size_bytes) +
|
|
125
|
+
") (heap) cobhan_buffer_size_bytes: " +
|
|
126
|
+
std::to_string(cobhan_buffer_size_bytes) + " for " + variable_name;
|
|
127
|
+
debug_log("allocate_cbuffer", log_msg);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
char *cobhan_buffer = new (std::nothrow) char[cobhan_buffer_size_bytes];
|
|
131
|
+
if (unlikely(cobhan_buffer == nullptr)) {
|
|
132
|
+
std::string error_msg =
|
|
133
|
+
"new[" + std::to_string(cobhan_buffer_size_bytes) + " returned null";
|
|
134
|
+
error_log("allocate_cbuffer", error_msg);
|
|
135
|
+
return nullptr;
|
|
136
|
+
}
|
|
137
|
+
std::unique_ptr<char[]> cobhan_buffer_unique_ptr(cobhan_buffer);
|
|
138
|
+
configure_cbuffer(cobhan_buffer, size_bytes + safety_padding_bytes);
|
|
139
|
+
return cobhan_buffer_unique_ptr;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
__attribute__((always_inline)) inline Napi::Value
|
|
143
|
+
cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
|
|
144
|
+
napi_value output;
|
|
145
|
+
|
|
146
|
+
// Using C function because it allows length delimited input
|
|
147
|
+
napi_status status = napi_create_string_utf8(
|
|
148
|
+
env, ((const char *)cobhan_buffer) + cobhan_header_size_bytes,
|
|
149
|
+
cbuffer_byte_length(cobhan_buffer), &output);
|
|
150
|
+
|
|
151
|
+
if (unlikely(status != napi_ok)) {
|
|
152
|
+
return log_error_and_throw(env, "cbuffer_to_nstring",
|
|
153
|
+
"napi_create_string_utf8 failed: " +
|
|
154
|
+
napi_status_to_string(status));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return Napi::String(env, output);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
__attribute__((always_inline)) inline size_t
|
|
161
|
+
nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
|
|
162
|
+
napi_status status;
|
|
163
|
+
size_t utf8_length;
|
|
164
|
+
|
|
165
|
+
status = napi_get_value_string_utf8(env, str, nullptr, 0, &utf8_length);
|
|
166
|
+
if (unlikely(status != napi_ok)) {
|
|
167
|
+
log_error_and_throw(env, "nstring_utf8_length",
|
|
168
|
+
"napi_get_value_string_utf8 length check failed: " +
|
|
169
|
+
napi_status_to_string(status));
|
|
170
|
+
return (size_t)(-1);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return utf8_length;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
__attribute__((always_inline)) inline char *
|
|
177
|
+
copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
|
|
178
|
+
size_t str_utf8_byte_length, char *cobhan_buffer,
|
|
179
|
+
size_t *byte_length = nullptr) {
|
|
180
|
+
|
|
181
|
+
size_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
|
|
182
|
+
if (cobhan_buffer_size_bytes < str_utf8_byte_length) {
|
|
183
|
+
log_error_and_throw(env, "copy_nstring_to_cbuffer",
|
|
184
|
+
"String too large for cobhan buffer");
|
|
185
|
+
return nullptr;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
napi_status status;
|
|
189
|
+
size_t copied_bytes;
|
|
190
|
+
// NOTE: This implementation relies on the additional byte that is reserved
|
|
191
|
+
// upon allocation for a NULL delimiter as methods like
|
|
192
|
+
// napi_get_value_string_utf8 append a NULL delimiter
|
|
193
|
+
status = napi_get_value_string_utf8(
|
|
194
|
+
env, str, cobhan_buffer + cobhan_header_size_bytes,
|
|
195
|
+
str_utf8_byte_length + 1, &copied_bytes);
|
|
196
|
+
if (unlikely(status != napi_ok)) {
|
|
197
|
+
log_error_and_throw(env, "copy_nstring_to_cbuffer",
|
|
198
|
+
"Napi utf8 string conversion failure: " +
|
|
199
|
+
napi_status_to_string(status));
|
|
200
|
+
return nullptr;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (unlikely(copied_bytes != str_utf8_byte_length)) {
|
|
204
|
+
log_error_and_throw(env, "copy_nstring_to_cbuffer",
|
|
205
|
+
"Did not copy expected number of bytes " +
|
|
206
|
+
std::to_string(str_utf8_byte_length) + " copied " +
|
|
207
|
+
std::to_string(copied_bytes));
|
|
208
|
+
return nullptr;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
configure_cbuffer(cobhan_buffer, copied_bytes);
|
|
212
|
+
|
|
213
|
+
if (byte_length != nullptr)
|
|
214
|
+
*byte_length = copied_bytes;
|
|
215
|
+
return cobhan_buffer;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
__attribute__((always_inline)) inline char *
|
|
219
|
+
copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
|
|
220
|
+
char *cobhan_buffer) {
|
|
221
|
+
size_t nbuffer_byte_length = nbuffer.ByteLength();
|
|
222
|
+
if (cbuffer_byte_length(cobhan_buffer) < nbuffer_byte_length) {
|
|
223
|
+
log_error_and_throw(env, "copy_nbuffer_to_cbuffer",
|
|
224
|
+
"Buffer too large for cobhan buffer");
|
|
225
|
+
return nullptr;
|
|
226
|
+
}
|
|
227
|
+
memcpy(cobhan_buffer + cobhan_header_size_bytes, nbuffer.Data(),
|
|
228
|
+
nbuffer_byte_length);
|
|
229
|
+
configure_cbuffer(cobhan_buffer, nbuffer_byte_length);
|
|
230
|
+
return cobhan_buffer;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
__attribute__((always_inline)) inline Napi::Buffer<unsigned char>
|
|
234
|
+
cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
|
|
235
|
+
return Napi::Buffer<unsigned char>::Copy(
|
|
236
|
+
env, ((unsigned char *)cobhan_buffer) + cobhan_header_size_bytes,
|
|
237
|
+
cbuffer_byte_length(cobhan_buffer));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
#endif
|
package/src/hints.h
ADDED
package/src/logging.cc
ADDED
package/src/logging.h
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#ifndef LOGGING_H
|
|
2
|
+
#define LOGGING_H
|
|
3
|
+
#include <cstdint>
|
|
4
|
+
#include <string>
|
|
5
|
+
#include "hints.h"
|
|
6
|
+
|
|
7
|
+
extern int32_t verbose_flag;
|
|
8
|
+
|
|
9
|
+
__attribute__((always_inline)) inline void debug_log(const char *function_name,
|
|
10
|
+
std::string message) {
|
|
11
|
+
if (unlikely(verbose_flag)) {
|
|
12
|
+
std::cerr << "asherah-node: [DEBUG] " << function_name << ": " << message
|
|
13
|
+
<< std::endl
|
|
14
|
+
<< std::flush;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
__attribute__((always_inline)) inline void
|
|
19
|
+
debug_log_alloca(const char *function_name, const char *variable_name,
|
|
20
|
+
size_t length) {
|
|
21
|
+
if (unlikely(verbose_flag)) {
|
|
22
|
+
std::cerr << "asherah-node: [DEBUG] " << function_name
|
|
23
|
+
<< ": Calling alloca(" << length << ") (stack) for "
|
|
24
|
+
<< variable_name << std::endl
|
|
25
|
+
<< std::flush;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
__attribute__((always_inline)) inline void error_log(const char *function_name,
|
|
30
|
+
std::string message) {
|
|
31
|
+
if (unlikely(verbose_flag)) {
|
|
32
|
+
std::cerr << "asherah-node: [ERROR] " << function_name << ": " << message
|
|
33
|
+
<< std::endl
|
|
34
|
+
<< std::flush;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#endif
|