asherah 1.3.22 → 1.3.24
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 +1 -1
- package/package.json +2 -2
- package/src/asherah.cc +212 -152
- package/src/asherah.h +14 -0
- package/src/cobhan.h +12 -27
- package/src/cobhan_napi_interop.h +88 -121
- package/src/logging.h +10 -0
- package/src/cobhan_napi_interop.cc +0 -2
package/binding.gyp
CHANGED
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
'defines': [ 'NAPI_CPP_EXCEPTIONS', 'NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS', 'NODE_ADDON_API_DISABLE_DEPRECATED', 'NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED' ],
|
|
20
20
|
'sources': [
|
|
21
21
|
'lib/libasherah.h',
|
|
22
|
+
'src/asherah.h',
|
|
22
23
|
'src/asherah.cc',
|
|
23
24
|
'src/logging.cc',
|
|
24
25
|
'src/logging.h',
|
|
25
|
-
'src/cobhan_napi_interop.cc',
|
|
26
26
|
'src/cobhan_napi_interop.h',
|
|
27
27
|
'src/cobhan.h',
|
|
28
28
|
'src/cobhan.cc',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "asherah",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.24",
|
|
4
4
|
"description": "Asherah envelope encryption and key rotation library",
|
|
5
5
|
"exports": {
|
|
6
6
|
"node-addons": "./dist/asherah.node"
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"files": [
|
|
24
24
|
"binding.gyp",
|
|
25
|
+
"src/asherah.h",
|
|
25
26
|
"src/asherah.cc",
|
|
26
27
|
"src/hints.h",
|
|
27
28
|
"src/logging.h",
|
|
28
29
|
"src/logging.cc",
|
|
29
30
|
"src/cobhan_napi_interop.h",
|
|
30
|
-
"src/cobhan_napi_interop.cc",
|
|
31
31
|
"src/cobhan.h",
|
|
32
32
|
"src/cobhan.cc",
|
|
33
33
|
"src/asherah.d.ts",
|
package/src/asherah.cc
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#include "asherah.h"
|
|
1
2
|
#include "../lib/libasherah.h"
|
|
2
3
|
#include "cobhan_napi_interop.h"
|
|
3
4
|
#include "hints.h"
|
|
@@ -6,7 +7,9 @@
|
|
|
6
7
|
#include <mutex>
|
|
7
8
|
#include <napi.h>
|
|
8
9
|
|
|
9
|
-
size_t
|
|
10
|
+
size_t est_intermediate_key_overhead;
|
|
11
|
+
size_t maximum_stack_alloc_size = 2048;
|
|
12
|
+
|
|
10
13
|
int32_t setup_state = 0;
|
|
11
14
|
std::mutex asherah_lock;
|
|
12
15
|
|
|
@@ -14,15 +17,15 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
14
17
|
std::lock_guard<std::mutex> lock(asherah_lock);
|
|
15
18
|
|
|
16
19
|
if (unlikely(verbose_flag)) {
|
|
17
|
-
debug_log(
|
|
20
|
+
debug_log(__func__, "called");
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
if (unlikely(setup_state == 1)) {
|
|
21
|
-
log_error_and_throw(
|
|
24
|
+
log_error_and_throw(__func__, "setup called twice");
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
if (unlikely(info.Length() < 1)) {
|
|
25
|
-
log_error_and_throw(
|
|
28
|
+
log_error_and_throw(__func__, "Wrong number of arguments");
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
Napi::String config;
|
|
@@ -38,7 +41,7 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
38
41
|
Napi::Function parse = json.Get("parse").As<Napi::Function>();
|
|
39
42
|
config_json = parse.Call(json, {config}).As<Napi::Object>();
|
|
40
43
|
} else {
|
|
41
|
-
log_error_and_throw(
|
|
44
|
+
log_error_and_throw(__func__, "Wrong argument type");
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
Napi::String product_id = config_json.Get("ProductID").As<Napi::String>();
|
|
@@ -50,20 +53,20 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
50
53
|
Napi::Value verbose = config_json.Get("Verbose");
|
|
51
54
|
if (likely(verbose.IsBoolean())) {
|
|
52
55
|
verbose_flag = verbose.As<Napi::Boolean>().Value();
|
|
53
|
-
debug_log(
|
|
56
|
+
debug_log(__func__, "verbose_flag: " + std::to_string(verbose_flag));
|
|
54
57
|
} else {
|
|
55
58
|
verbose_flag = 0;
|
|
56
|
-
debug_log(
|
|
59
|
+
debug_log(__func__, "verbose_flag: defaulting to false");
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
char *config_cobhan_buffer;
|
|
60
63
|
size_t config_copied_bytes;
|
|
61
64
|
NAPI_STRING_TO_CBUFFER(env, config, config_cobhan_buffer, config_copied_bytes,
|
|
62
|
-
|
|
65
|
+
maximum_stack_alloc_size, __func__);
|
|
63
66
|
|
|
64
67
|
char *config_canary_ptr = get_canary_ptr(config_cobhan_buffer);
|
|
65
68
|
if (unlikely(!check_canary_ptr(config_canary_ptr))) {
|
|
66
|
-
log_error_and_throw(
|
|
69
|
+
log_error_and_throw(__func__,
|
|
67
70
|
"Failed initial canary check for config_cobhan_buffer");
|
|
68
71
|
}
|
|
69
72
|
|
|
@@ -71,111 +74,37 @@ void setup(const Napi::CallbackInfo &info) {
|
|
|
71
74
|
GoInt32 result = SetupJson(config_cobhan_buffer);
|
|
72
75
|
|
|
73
76
|
if (unlikely(verbose_flag)) {
|
|
74
|
-
debug_log(
|
|
77
|
+
debug_log(__func__, "Returned from asherah-cobhan SetupJson");
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
if (unlikely(!check_canary_ptr(config_canary_ptr))) {
|
|
78
81
|
log_error_and_throw(
|
|
79
|
-
"
|
|
80
|
-
"Failed post-call canary check for config_cobhan_buffer");
|
|
82
|
+
__func__, "Failed post-call canary check for config_cobhan_buffer");
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
if (unlikely(result < 0)) {
|
|
84
|
-
|
|
85
|
-
log_error_and_throw("setup", std::to_string(result));
|
|
86
|
+
log_error_and_throw(__func__, asherah_cobhan_error_to_string(result));
|
|
86
87
|
}
|
|
87
88
|
setup_state = 1;
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
Napi::String encrypt_to_json(Napi::Env &env, size_t partition_bytes,
|
|
91
|
-
size_t data_bytes,
|
|
92
|
-
char *partition_id_cobhan_buffer,
|
|
93
|
-
char *input_cobhan_buffer) {
|
|
94
|
-
|
|
95
|
-
size_t asherah_output_size_bytes =
|
|
96
|
-
estimate_asherah_output_size_bytes(data_bytes, partition_bytes);
|
|
97
|
-
|
|
98
|
-
if (unlikely(verbose_flag)) {
|
|
99
|
-
debug_log("encrypt_to_json", " asherah_output_size_bytes " +
|
|
100
|
-
std::to_string(asherah_output_size_bytes));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
char *output_cobhan_buffer;
|
|
104
|
-
ALLOCATE_CBUFFER(output_cobhan_buffer, asherah_output_size_bytes,
|
|
105
|
-
"encrypt_to_json");
|
|
106
|
-
|
|
107
|
-
char *partition_id_canary_ptr = get_canary_ptr(partition_id_cobhan_buffer);
|
|
108
|
-
if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
|
|
109
|
-
log_error_and_throw(
|
|
110
|
-
"encrypt_to_json",
|
|
111
|
-
"Failed initial canary check for partition_id_cobhan_buffer");
|
|
112
|
-
}
|
|
113
|
-
char *input_canary_ptr = get_canary_ptr(input_cobhan_buffer);
|
|
114
|
-
if (unlikely(!check_canary_ptr(input_canary_ptr))) {
|
|
115
|
-
log_error_and_throw("encrypt_to_json",
|
|
116
|
-
"Failed initial canary check for input_cobhan_buffer");
|
|
117
|
-
}
|
|
118
|
-
char *output_canary_ptr = get_canary_ptr(output_cobhan_buffer);
|
|
119
|
-
if (unlikely(!check_canary_ptr(output_canary_ptr))) {
|
|
120
|
-
log_error_and_throw("encrypt_to_json",
|
|
121
|
-
"Failed initial canary check for output_cobhan_buffer");
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (unlikely(verbose_flag)) {
|
|
125
|
-
debug_log("encrypt_to_json", "Calling asherah-cobhan EncryptToJson");
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// extern GoInt32 EncryptToJson(void* partitionIdPtr, void* dataPtr, void*
|
|
129
|
-
// jsonPtr);
|
|
130
|
-
GoInt32 result = EncryptToJson(partition_id_cobhan_buffer,
|
|
131
|
-
input_cobhan_buffer, output_cobhan_buffer);
|
|
132
|
-
|
|
133
|
-
if (unlikely(verbose_flag)) {
|
|
134
|
-
debug_log("encrypt_to_json", "Returning from asherah-cobhan EncryptToJson");
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
|
|
138
|
-
log_error_and_throw(
|
|
139
|
-
"encrypt_to_json",
|
|
140
|
-
"Failed post-call canary check for partition_id_cobhan_buffer");
|
|
141
|
-
}
|
|
142
|
-
if (unlikely(!check_canary_ptr(input_canary_ptr))) {
|
|
143
|
-
log_error_and_throw(
|
|
144
|
-
"encrypt_to_json",
|
|
145
|
-
"Failed post-call canary check for input_cobhan_buffer");
|
|
146
|
-
}
|
|
147
|
-
if (unlikely(!check_canary_ptr(output_canary_ptr))) {
|
|
148
|
-
log_error_and_throw(
|
|
149
|
-
"encrypt_to_json",
|
|
150
|
-
"Failed post-call canary check for output_cobhan_buffer");
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (unlikely(result < 0)) {
|
|
154
|
-
// TODO: Convert this to a proper error message
|
|
155
|
-
log_error_and_throw("encrypt_to_json", std::to_string(result));
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
Napi::String output = cbuffer_to_nstring(env, output_cobhan_buffer);
|
|
159
|
-
return output;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
91
|
Napi::String encrypt(const Napi::CallbackInfo &info) {
|
|
163
92
|
std::lock_guard<std::mutex> lock(asherah_lock);
|
|
164
93
|
|
|
165
94
|
if (unlikely(verbose_flag)) {
|
|
166
|
-
debug_log(
|
|
95
|
+
debug_log(__func__, "called");
|
|
167
96
|
}
|
|
168
97
|
|
|
169
98
|
if (unlikely(setup_state == 0)) {
|
|
170
|
-
log_error_and_throw(
|
|
99
|
+
log_error_and_throw(__func__, "setup() not called");
|
|
171
100
|
}
|
|
172
101
|
|
|
173
102
|
if (unlikely(info.Length() < 2)) {
|
|
174
|
-
log_error_and_throw(
|
|
103
|
+
log_error_and_throw(__func__, "Wrong number of arguments");
|
|
175
104
|
}
|
|
176
105
|
|
|
177
106
|
if (unlikely(!info[0].IsString() || !info[1].IsBuffer())) {
|
|
178
|
-
log_error_and_throw(
|
|
107
|
+
log_error_and_throw(__func__, "Wrong argument types");
|
|
179
108
|
}
|
|
180
109
|
|
|
181
110
|
Napi::Env env = info.Env();
|
|
@@ -184,21 +113,23 @@ Napi::String encrypt(const Napi::CallbackInfo &info) {
|
|
|
184
113
|
char *partition_id_cobhan_buffer;
|
|
185
114
|
size_t partition_id_copied_bytes;
|
|
186
115
|
NAPI_STRING_TO_CBUFFER(env, partition_id, partition_id_cobhan_buffer,
|
|
187
|
-
partition_id_copied_bytes,
|
|
116
|
+
partition_id_copied_bytes, maximum_stack_alloc_size,
|
|
117
|
+
__func__);
|
|
188
118
|
|
|
189
119
|
Napi::Buffer<unsigned char> input_napi_buffer =
|
|
190
120
|
info[1].As<Napi::Buffer<unsigned char>>();
|
|
191
121
|
char *input_cobhan_buffer;
|
|
192
122
|
size_t input_copied_bytes;
|
|
193
123
|
NAPI_BUFFER_TO_CBUFFER(env, input_napi_buffer, input_cobhan_buffer,
|
|
194
|
-
input_copied_bytes,
|
|
124
|
+
input_copied_bytes, maximum_stack_alloc_size,
|
|
125
|
+
__func__);
|
|
195
126
|
|
|
196
127
|
Napi::String output =
|
|
197
128
|
encrypt_to_json(env, partition_id_copied_bytes, input_copied_bytes,
|
|
198
129
|
partition_id_cobhan_buffer, input_cobhan_buffer);
|
|
199
130
|
|
|
200
131
|
if (unlikely(verbose_flag)) {
|
|
201
|
-
debug_log(
|
|
132
|
+
debug_log(__func__, "finished");
|
|
202
133
|
}
|
|
203
134
|
|
|
204
135
|
return output;
|
|
@@ -208,19 +139,19 @@ Napi::String encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
208
139
|
std::lock_guard<std::mutex> lock(asherah_lock);
|
|
209
140
|
|
|
210
141
|
if (unlikely(verbose_flag)) {
|
|
211
|
-
debug_log(
|
|
142
|
+
debug_log(__func__, "called");
|
|
212
143
|
}
|
|
213
144
|
|
|
214
145
|
if (unlikely(setup_state == 0)) {
|
|
215
|
-
log_error_and_throw(
|
|
146
|
+
log_error_and_throw(__func__, "setup() not called");
|
|
216
147
|
}
|
|
217
148
|
|
|
218
149
|
if (unlikely(info.Length() < 2)) {
|
|
219
|
-
log_error_and_throw(
|
|
150
|
+
log_error_and_throw(__func__, "Wrong number of arguments");
|
|
220
151
|
}
|
|
221
152
|
|
|
222
153
|
if (unlikely(!info[0].IsString() || !info[1].IsString())) {
|
|
223
|
-
log_error_and_throw(
|
|
154
|
+
log_error_and_throw(__func__, "Wrong argument types");
|
|
224
155
|
}
|
|
225
156
|
|
|
226
157
|
Napi::Env env = info.Env();
|
|
@@ -229,22 +160,91 @@ Napi::String encrypt_string(const Napi::CallbackInfo &info) {
|
|
|
229
160
|
char *partition_id_cobhan_buffer;
|
|
230
161
|
size_t partition_id_copied_bytes;
|
|
231
162
|
NAPI_STRING_TO_CBUFFER(env, partition_id, partition_id_cobhan_buffer,
|
|
232
|
-
partition_id_copied_bytes,
|
|
163
|
+
partition_id_copied_bytes, maximum_stack_alloc_size,
|
|
164
|
+
__func__);
|
|
233
165
|
|
|
234
166
|
Napi::String input = info[1].As<Napi::String>();
|
|
235
167
|
char *input_cobhan_buffer;
|
|
236
168
|
size_t input_copied_bytes;
|
|
237
169
|
NAPI_STRING_TO_CBUFFER(env, input, input_cobhan_buffer, input_copied_bytes,
|
|
238
|
-
|
|
170
|
+
maximum_stack_alloc_size, __func__);
|
|
239
171
|
|
|
240
172
|
Napi::String output =
|
|
241
173
|
encrypt_to_json(env, partition_id_copied_bytes, input_copied_bytes,
|
|
242
174
|
partition_id_cobhan_buffer, input_cobhan_buffer);
|
|
243
175
|
|
|
244
176
|
if (unlikely(verbose_flag)) {
|
|
245
|
-
debug_log(
|
|
177
|
+
debug_log(__func__, "finished");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return output;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
Napi::String encrypt_to_json(Napi::Env &env, size_t partition_bytes,
|
|
184
|
+
size_t data_bytes,
|
|
185
|
+
char *partition_id_cobhan_buffer,
|
|
186
|
+
char *input_cobhan_buffer) {
|
|
187
|
+
|
|
188
|
+
size_t asherah_output_size_bytes =
|
|
189
|
+
estimate_asherah_output_size_bytes(data_bytes, partition_bytes);
|
|
190
|
+
|
|
191
|
+
if (unlikely(verbose_flag)) {
|
|
192
|
+
debug_log(__func__, " asherah_output_size_bytes " +
|
|
193
|
+
std::to_string(asherah_output_size_bytes));
|
|
246
194
|
}
|
|
247
195
|
|
|
196
|
+
char *output_cobhan_buffer;
|
|
197
|
+
ALLOCATE_CBUFFER(output_cobhan_buffer, asherah_output_size_bytes,
|
|
198
|
+
maximum_stack_alloc_size, __func__);
|
|
199
|
+
|
|
200
|
+
char *partition_id_canary_ptr = get_canary_ptr(partition_id_cobhan_buffer);
|
|
201
|
+
if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
|
|
202
|
+
log_error_and_throw(
|
|
203
|
+
__func__, "Failed initial canary check for partition_id_cobhan_buffer");
|
|
204
|
+
}
|
|
205
|
+
char *input_canary_ptr = get_canary_ptr(input_cobhan_buffer);
|
|
206
|
+
if (unlikely(!check_canary_ptr(input_canary_ptr))) {
|
|
207
|
+
log_error_and_throw(__func__,
|
|
208
|
+
"Failed initial canary check for input_cobhan_buffer");
|
|
209
|
+
}
|
|
210
|
+
char *output_canary_ptr = get_canary_ptr(output_cobhan_buffer);
|
|
211
|
+
if (unlikely(!check_canary_ptr(output_canary_ptr))) {
|
|
212
|
+
log_error_and_throw(__func__,
|
|
213
|
+
"Failed initial canary check for output_cobhan_buffer");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (unlikely(verbose_flag)) {
|
|
217
|
+
debug_log(__func__, "Calling asherah-cobhan EncryptToJson");
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// extern GoInt32 EncryptToJson(void* partitionIdPtr, void* dataPtr, void*
|
|
221
|
+
// jsonPtr);
|
|
222
|
+
GoInt32 result = EncryptToJson(partition_id_cobhan_buffer,
|
|
223
|
+
input_cobhan_buffer, output_cobhan_buffer);
|
|
224
|
+
|
|
225
|
+
if (unlikely(verbose_flag)) {
|
|
226
|
+
debug_log(__func__, "Returning from asherah-cobhan EncryptToJson");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
|
|
230
|
+
log_error_and_throw(
|
|
231
|
+
__func__,
|
|
232
|
+
"Failed post-call canary check for partition_id_cobhan_buffer");
|
|
233
|
+
}
|
|
234
|
+
if (unlikely(!check_canary_ptr(input_canary_ptr))) {
|
|
235
|
+
log_error_and_throw(
|
|
236
|
+
__func__, "Failed post-call canary check for input_cobhan_buffer");
|
|
237
|
+
}
|
|
238
|
+
if (unlikely(!check_canary_ptr(output_canary_ptr))) {
|
|
239
|
+
log_error_and_throw(
|
|
240
|
+
__func__, "Failed post-call canary check for output_cobhan_buffer");
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (unlikely(result < 0)) {
|
|
244
|
+
log_error_and_throw(__func__, asherah_cobhan_error_to_string(result));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
Napi::String output = cbuffer_to_nstring(env, output_cobhan_buffer);
|
|
248
248
|
return output;
|
|
249
249
|
}
|
|
250
250
|
|
|
@@ -252,19 +252,19 @@ Napi::Buffer<unsigned char> decrypt(const Napi::CallbackInfo &info) {
|
|
|
252
252
|
std::lock_guard<std::mutex> lock(asherah_lock);
|
|
253
253
|
|
|
254
254
|
if (unlikely(verbose_flag)) {
|
|
255
|
-
debug_log(
|
|
255
|
+
debug_log(__func__, "called");
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
if (unlikely(setup_state == 0)) {
|
|
259
|
-
log_error_and_throw(
|
|
259
|
+
log_error_and_throw(__func__, "setup() not called");
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
if (unlikely(info.Length() < 2)) {
|
|
263
|
-
log_error_and_throw(
|
|
263
|
+
log_error_and_throw(__func__, "Wrong number of arguments");
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
if (unlikely(!info[0].IsString() || !info[1].IsString())) {
|
|
267
|
-
log_error_and_throw(
|
|
267
|
+
log_error_and_throw(__func__, "Wrong argument types");
|
|
268
268
|
}
|
|
269
269
|
|
|
270
270
|
Napi::Env env = info.Env();
|
|
@@ -273,36 +273,37 @@ Napi::Buffer<unsigned char> decrypt(const Napi::CallbackInfo &info) {
|
|
|
273
273
|
char *partition_id_cobhan_buffer;
|
|
274
274
|
size_t partition_id_copied_bytes;
|
|
275
275
|
NAPI_STRING_TO_CBUFFER(env, partition_id, partition_id_cobhan_buffer,
|
|
276
|
-
partition_id_copied_bytes,
|
|
276
|
+
partition_id_copied_bytes, maximum_stack_alloc_size,
|
|
277
|
+
__func__);
|
|
277
278
|
|
|
278
279
|
Napi::String input = info[1].As<Napi::String>();
|
|
279
280
|
char *input_cobhan_buffer;
|
|
280
281
|
size_t input_copied_bytes;
|
|
281
282
|
NAPI_STRING_TO_CBUFFER(env, input, input_cobhan_buffer, input_copied_bytes,
|
|
282
|
-
|
|
283
|
+
maximum_stack_alloc_size, __func__);
|
|
283
284
|
|
|
284
285
|
char *output_cobhan_buffer;
|
|
285
|
-
ALLOCATE_CBUFFER(output_cobhan_buffer, input_copied_bytes,
|
|
286
|
+
ALLOCATE_CBUFFER(output_cobhan_buffer, input_copied_bytes,
|
|
287
|
+
maximum_stack_alloc_size, __func__);
|
|
286
288
|
|
|
287
289
|
char *partition_id_canary_ptr = get_canary_ptr(partition_id_cobhan_buffer);
|
|
288
290
|
if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
|
|
289
291
|
log_error_and_throw(
|
|
290
|
-
"
|
|
291
|
-
"Failed initial canary check for partition_id_cobhan_buffer");
|
|
292
|
+
__func__, "Failed initial canary check for partition_id_cobhan_buffer");
|
|
292
293
|
}
|
|
293
294
|
char *input_canary_ptr = get_canary_ptr(input_cobhan_buffer);
|
|
294
295
|
if (unlikely(!check_canary_ptr(input_canary_ptr))) {
|
|
295
|
-
log_error_and_throw(
|
|
296
|
+
log_error_and_throw(__func__,
|
|
296
297
|
"Failed initial canary check for input_cobhan_buffer");
|
|
297
298
|
}
|
|
298
299
|
char *output_canary_ptr = get_canary_ptr(output_cobhan_buffer);
|
|
299
300
|
if (unlikely(!check_canary_ptr(output_canary_ptr))) {
|
|
300
|
-
log_error_and_throw(
|
|
301
|
+
log_error_and_throw(__func__,
|
|
301
302
|
"Failed initial canary check for output_cobhan_buffer");
|
|
302
303
|
}
|
|
303
304
|
|
|
304
305
|
if (unlikely(verbose_flag)) {
|
|
305
|
-
debug_log(
|
|
306
|
+
debug_log(__func__, "Calling asherah-cobhan DecryptFromJson");
|
|
306
307
|
}
|
|
307
308
|
|
|
308
309
|
// extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr, void*
|
|
@@ -311,35 +312,32 @@ Napi::Buffer<unsigned char> decrypt(const Napi::CallbackInfo &info) {
|
|
|
311
312
|
input_cobhan_buffer, output_cobhan_buffer);
|
|
312
313
|
|
|
313
314
|
if (unlikely(verbose_flag)) {
|
|
314
|
-
debug_log(
|
|
315
|
+
debug_log(__func__, "Returned from asherah-cobhan DecryptFromJson");
|
|
315
316
|
}
|
|
316
317
|
|
|
317
318
|
if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
|
|
318
319
|
log_error_and_throw(
|
|
319
|
-
|
|
320
|
+
__func__,
|
|
320
321
|
"Failed post-call canary check for partition_id_cobhan_buffer");
|
|
321
322
|
}
|
|
322
323
|
if (unlikely(!check_canary_ptr(input_canary_ptr))) {
|
|
323
324
|
log_error_and_throw(
|
|
324
|
-
"
|
|
325
|
-
"Failed post-call canary check for input_cobhan_buffer");
|
|
325
|
+
__func__, "Failed post-call canary check for input_cobhan_buffer");
|
|
326
326
|
}
|
|
327
327
|
if (unlikely(!check_canary_ptr(output_canary_ptr))) {
|
|
328
328
|
log_error_and_throw(
|
|
329
|
-
"
|
|
330
|
-
"Failed post-call canary check for output_cobhan_buffer");
|
|
329
|
+
__func__, "Failed post-call canary check for output_cobhan_buffer");
|
|
331
330
|
}
|
|
332
331
|
|
|
333
332
|
if (unlikely(result < 0)) {
|
|
334
|
-
|
|
335
|
-
log_error_and_throw("decrypt", std::to_string(result));
|
|
333
|
+
log_error_and_throw(__func__, asherah_cobhan_error_to_string(result));
|
|
336
334
|
}
|
|
337
335
|
|
|
338
336
|
Napi::Buffer<unsigned char> output =
|
|
339
337
|
cbuffer_to_nbuffer(env, output_cobhan_buffer);
|
|
340
338
|
|
|
341
339
|
if (unlikely(verbose_flag)) {
|
|
342
|
-
debug_log(
|
|
340
|
+
debug_log(__func__, "finished");
|
|
343
341
|
}
|
|
344
342
|
|
|
345
343
|
return output;
|
|
@@ -349,19 +347,19 @@ Napi::String decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
349
347
|
std::lock_guard<std::mutex> lock(asherah_lock);
|
|
350
348
|
|
|
351
349
|
if (unlikely(verbose_flag)) {
|
|
352
|
-
debug_log(
|
|
350
|
+
debug_log(__func__, "called");
|
|
353
351
|
}
|
|
354
352
|
|
|
355
353
|
if (unlikely(setup_state == 0)) {
|
|
356
|
-
log_error_and_throw(
|
|
354
|
+
log_error_and_throw(__func__, "setup() not called");
|
|
357
355
|
}
|
|
358
356
|
|
|
359
357
|
if (unlikely(info.Length() < 2)) {
|
|
360
|
-
log_error_and_throw(
|
|
358
|
+
log_error_and_throw(__func__, "Wrong number of arguments");
|
|
361
359
|
}
|
|
362
360
|
|
|
363
361
|
if (unlikely(!info[0].IsString() || !info[1].IsString())) {
|
|
364
|
-
log_error_and_throw(
|
|
362
|
+
log_error_and_throw(__func__, "Wrong argument types");
|
|
365
363
|
}
|
|
366
364
|
|
|
367
365
|
Napi::Env env = info.Env();
|
|
@@ -370,36 +368,37 @@ Napi::String decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
370
368
|
char *partition_id_cobhan_buffer;
|
|
371
369
|
size_t partition_id_copied_bytes;
|
|
372
370
|
NAPI_STRING_TO_CBUFFER(env, partition_id, partition_id_cobhan_buffer,
|
|
373
|
-
partition_id_copied_bytes,
|
|
371
|
+
partition_id_copied_bytes, maximum_stack_alloc_size,
|
|
372
|
+
__func__);
|
|
374
373
|
|
|
375
374
|
Napi::String input = info[1].As<Napi::String>();
|
|
376
375
|
char *input_cobhan_buffer;
|
|
377
376
|
size_t input_copied_bytes;
|
|
378
377
|
NAPI_STRING_TO_CBUFFER(env, input, input_cobhan_buffer, input_copied_bytes,
|
|
379
|
-
|
|
378
|
+
maximum_stack_alloc_size, __func__);
|
|
380
379
|
|
|
381
380
|
char *output_cobhan_buffer;
|
|
382
|
-
ALLOCATE_CBUFFER(output_cobhan_buffer, input_copied_bytes,
|
|
381
|
+
ALLOCATE_CBUFFER(output_cobhan_buffer, input_copied_bytes,
|
|
382
|
+
maximum_stack_alloc_size, __func__);
|
|
383
383
|
|
|
384
384
|
char *partition_id_canary_ptr = get_canary_ptr(partition_id_cobhan_buffer);
|
|
385
385
|
if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
|
|
386
386
|
log_error_and_throw(
|
|
387
|
-
"
|
|
388
|
-
"Failed initial canary check for partition_id_cobhan_buffer");
|
|
387
|
+
__func__, "Failed initial canary check for partition_id_cobhan_buffer");
|
|
389
388
|
}
|
|
390
389
|
char *input_canary_ptr = get_canary_ptr(input_cobhan_buffer);
|
|
391
390
|
if (unlikely(!check_canary_ptr(input_canary_ptr))) {
|
|
392
|
-
log_error_and_throw(
|
|
391
|
+
log_error_and_throw(__func__,
|
|
393
392
|
"Failed initial canary check for input_cobhan_buffer");
|
|
394
393
|
}
|
|
395
394
|
char *output_canary_ptr = get_canary_ptr(output_cobhan_buffer);
|
|
396
395
|
if (unlikely(!check_canary_ptr(output_canary_ptr))) {
|
|
397
|
-
log_error_and_throw(
|
|
396
|
+
log_error_and_throw(__func__,
|
|
398
397
|
"Failed initial canary check for output_cobhan_buffer");
|
|
399
398
|
}
|
|
400
399
|
|
|
401
400
|
if (unlikely(verbose_flag)) {
|
|
402
|
-
debug_log(
|
|
401
|
+
debug_log(__func__, "Calling asherah-cobhan DecryptFromJson");
|
|
403
402
|
}
|
|
404
403
|
|
|
405
404
|
// extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr, void*
|
|
@@ -408,34 +407,31 @@ Napi::String decrypt_string(const Napi::CallbackInfo &info) {
|
|
|
408
407
|
input_cobhan_buffer, output_cobhan_buffer);
|
|
409
408
|
|
|
410
409
|
if (unlikely(verbose_flag)) {
|
|
411
|
-
debug_log(
|
|
410
|
+
debug_log(__func__, "Returned from asherah-cobhan DecryptFromJson");
|
|
412
411
|
}
|
|
413
412
|
|
|
414
413
|
if (unlikely(!check_canary_ptr(partition_id_canary_ptr))) {
|
|
415
414
|
log_error_and_throw(
|
|
416
|
-
|
|
415
|
+
__func__,
|
|
417
416
|
"Failed post-call canary check for partition_id_cobhan_buffer");
|
|
418
417
|
}
|
|
419
418
|
if (unlikely(!check_canary_ptr(input_canary_ptr))) {
|
|
420
419
|
log_error_and_throw(
|
|
421
|
-
"
|
|
422
|
-
"Failed post-call canary check for input_cobhan_buffer");
|
|
420
|
+
__func__, "Failed post-call canary check for input_cobhan_buffer");
|
|
423
421
|
}
|
|
424
422
|
if (unlikely(!check_canary_ptr(output_canary_ptr))) {
|
|
425
423
|
log_error_and_throw(
|
|
426
|
-
"
|
|
427
|
-
"Failed post-call canary check for output_cobhan_buffer");
|
|
424
|
+
__func__, "Failed post-call canary check for output_cobhan_buffer");
|
|
428
425
|
}
|
|
429
426
|
|
|
430
427
|
if (unlikely(result < 0)) {
|
|
431
|
-
|
|
432
|
-
log_error_and_throw("decrypt_string", std::to_string(result));
|
|
428
|
+
log_error_and_throw(__func__, asherah_cobhan_error_to_string(result));
|
|
433
429
|
}
|
|
434
430
|
|
|
435
431
|
Napi::String output = cbuffer_to_nstring(env, output_cobhan_buffer);
|
|
436
432
|
|
|
437
433
|
if (unlikely(verbose_flag)) {
|
|
438
|
-
debug_log(
|
|
434
|
+
debug_log(__func__, "finished");
|
|
439
435
|
}
|
|
440
436
|
|
|
441
437
|
return output;
|
|
@@ -445,20 +441,20 @@ void shutdown(const Napi::CallbackInfo &info) {
|
|
|
445
441
|
std::lock_guard<std::mutex> lock(asherah_lock);
|
|
446
442
|
|
|
447
443
|
if (unlikely(verbose_flag)) {
|
|
448
|
-
debug_log(
|
|
444
|
+
debug_log(__func__, "called");
|
|
449
445
|
}
|
|
450
446
|
|
|
451
447
|
setup_state = 0;
|
|
452
448
|
|
|
453
449
|
if (unlikely(verbose_flag)) {
|
|
454
|
-
debug_log(
|
|
450
|
+
debug_log(__func__, "Calling asherah-cobhan Shutdown");
|
|
455
451
|
}
|
|
456
452
|
|
|
457
453
|
// extern void Shutdown();
|
|
458
454
|
Shutdown();
|
|
459
455
|
|
|
460
456
|
if (unlikely(verbose_flag)) {
|
|
461
|
-
debug_log(
|
|
457
|
+
debug_log(__func__, "Returned from asherah-cobhan Shutdown");
|
|
462
458
|
}
|
|
463
459
|
}
|
|
464
460
|
|
|
@@ -466,29 +462,27 @@ void set_max_stack_alloc_item_size(const Napi::CallbackInfo &info) {
|
|
|
466
462
|
std::lock_guard<std::mutex> lock(asherah_lock);
|
|
467
463
|
|
|
468
464
|
if (unlikely(verbose_flag)) {
|
|
469
|
-
debug_log(
|
|
465
|
+
debug_log(__func__, "called");
|
|
470
466
|
}
|
|
471
467
|
|
|
472
468
|
if (unlikely(info.Length() < 1)) {
|
|
473
|
-
log_error_and_throw("
|
|
474
|
-
"Wrong number of arguments");
|
|
469
|
+
log_error_and_throw(__func__, "Wrong number of arguments");
|
|
475
470
|
}
|
|
476
471
|
|
|
477
472
|
Napi::Number item_size = info[0].ToNumber();
|
|
478
473
|
|
|
479
|
-
|
|
474
|
+
maximum_stack_alloc_size = (size_t)item_size.Int32Value();
|
|
480
475
|
}
|
|
481
476
|
|
|
482
477
|
void set_safety_padding_overhead(const Napi::CallbackInfo &info) {
|
|
483
478
|
std::lock_guard<std::mutex> lock(asherah_lock);
|
|
484
479
|
|
|
485
480
|
if (unlikely(verbose_flag)) {
|
|
486
|
-
debug_log(
|
|
481
|
+
debug_log(__func__, "called");
|
|
487
482
|
}
|
|
488
483
|
|
|
489
484
|
if (unlikely(info.Length() < 1)) {
|
|
490
|
-
log_error_and_throw("
|
|
491
|
-
"Wrong number of arguments");
|
|
485
|
+
log_error_and_throw(__func__, "Wrong number of arguments");
|
|
492
486
|
}
|
|
493
487
|
|
|
494
488
|
Napi::Number safety_padding_number = info[0].ToNumber();
|
|
@@ -496,6 +490,72 @@ void set_safety_padding_overhead(const Napi::CallbackInfo &info) {
|
|
|
496
490
|
set_safety_padding_bytes((size_t)safety_padding_number.Int32Value());
|
|
497
491
|
}
|
|
498
492
|
|
|
493
|
+
__attribute__((always_inline)) inline size_t
|
|
494
|
+
estimate_asherah_output_size_bytes(size_t data_byte_len,
|
|
495
|
+
size_t partition_byte_len) {
|
|
496
|
+
const size_t est_encryption_overhead = 48;
|
|
497
|
+
const size_t est_envelope_overhead = 185;
|
|
498
|
+
const double base64_overhead = 1.34;
|
|
499
|
+
|
|
500
|
+
// Add one rather than using std::ceil to round up
|
|
501
|
+
double est_data_byte_len =
|
|
502
|
+
(double(data_byte_len + est_encryption_overhead) * base64_overhead) + 1;
|
|
503
|
+
|
|
504
|
+
size_t asherah_output_size_bytes =
|
|
505
|
+
size_t(est_envelope_overhead + est_intermediate_key_overhead +
|
|
506
|
+
partition_byte_len + est_data_byte_len);
|
|
507
|
+
if (unlikely(verbose_flag)) {
|
|
508
|
+
std::string log_msg =
|
|
509
|
+
"estimate_asherah_output_size(" + std::to_string(data_byte_len) + ", " +
|
|
510
|
+
std::to_string(partition_byte_len) +
|
|
511
|
+
") est_data_byte_len: " + std::to_string(est_data_byte_len) +
|
|
512
|
+
" asherah_output_size_bytes: " +
|
|
513
|
+
std::to_string(asherah_output_size_bytes);
|
|
514
|
+
debug_log(__func__, log_msg);
|
|
515
|
+
}
|
|
516
|
+
return asherah_output_size_bytes;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
__attribute__((always_inline)) inline const char *
|
|
520
|
+
asherah_cobhan_error_to_string(int32_t error) {
|
|
521
|
+
switch (error) {
|
|
522
|
+
case 0:
|
|
523
|
+
return "Success";
|
|
524
|
+
case -1:
|
|
525
|
+
return "Cobhan error: NULL pointer";
|
|
526
|
+
case -2:
|
|
527
|
+
return "Cobhan error: Buffer too large";
|
|
528
|
+
case -3:
|
|
529
|
+
return "Cobhan error: Buffer too small";
|
|
530
|
+
case -4:
|
|
531
|
+
return "Cobhan error: Copy failed";
|
|
532
|
+
case -5:
|
|
533
|
+
return "Cobhan error: JSON decode failed";
|
|
534
|
+
case -6:
|
|
535
|
+
return "Cobhan error: JSON encode failed";
|
|
536
|
+
case -7:
|
|
537
|
+
return "Cobhan error: Invalid UTF-8";
|
|
538
|
+
case -8:
|
|
539
|
+
return "Cobhan error: Read temp file failed";
|
|
540
|
+
case -9:
|
|
541
|
+
return "Cobhan error: Write temp file failed";
|
|
542
|
+
case -100:
|
|
543
|
+
return "Asherah error: Not initialized";
|
|
544
|
+
case -101:
|
|
545
|
+
return "Asherah error: Already initialized";
|
|
546
|
+
case -102:
|
|
547
|
+
return "Asherah error: Failed to get session";
|
|
548
|
+
case -103:
|
|
549
|
+
return "Asherah error: Encrypt operation failed";
|
|
550
|
+
case -104:
|
|
551
|
+
return "Asherah error: Decrypt operation failed";
|
|
552
|
+
case -105:
|
|
553
|
+
return "Asherah error: Invalid configuration";
|
|
554
|
+
default:
|
|
555
|
+
return "Unknown error";
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
499
559
|
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
500
560
|
exports.Set(Napi::String::New(env, "setup"), Napi::Function::New(env, setup));
|
|
501
561
|
exports.Set(Napi::String::New(env, "encrypt"),
|
package/src/asherah.h
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#ifndef ASHERAH_H
|
|
2
|
+
#define ASHERAH_H
|
|
3
|
+
#include <cstdint>
|
|
4
|
+
#include <napi.h>
|
|
5
|
+
#include <stddef.h>
|
|
6
|
+
|
|
7
|
+
size_t estimate_asherah_output_size_bytes(size_t data_byte_len,
|
|
8
|
+
size_t partition_byte_len);
|
|
9
|
+
const char *asherah_cobhan_error_to_string(int32_t error);
|
|
10
|
+
Napi::String encrypt_to_json(Napi::Env &env, size_t partition_bytes,
|
|
11
|
+
size_t data_bytes,
|
|
12
|
+
char *partition_id_cobhan_buffer,
|
|
13
|
+
char *input_cobhan_buffer);
|
|
14
|
+
#endif
|
package/src/cobhan.h
CHANGED
|
@@ -37,9 +37,8 @@ calculate_cobhan_buffer_allocation_size(size_t data_len_bytes) {
|
|
|
37
37
|
__attribute__((always_inline)) inline void
|
|
38
38
|
configure_cbuffer(char *cobhan_buffer, size_t length) {
|
|
39
39
|
if (unlikely(verbose_flag)) {
|
|
40
|
-
debug_log(
|
|
41
|
-
|
|
42
|
-
std::to_string(length) + ")");
|
|
40
|
+
debug_log(__func__, "configure_cbuffer(" + format_ptr(cobhan_buffer) +
|
|
41
|
+
", " + std::to_string(length) + ")");
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
*((int32_t *)cobhan_buffer) = length;
|
|
@@ -48,22 +47,9 @@ configure_cbuffer(char *cobhan_buffer, size_t length) {
|
|
|
48
47
|
|
|
49
48
|
// Write canary values
|
|
50
49
|
char *data_ptr = cbuffer_data_ptr(cobhan_buffer);
|
|
51
|
-
#ifdef LOG_CANARY_WRITES
|
|
52
|
-
if (unlikely(verbose_flag)) {
|
|
53
|
-
debug_log("configure_cbuffer",
|
|
54
|
-
"Writing first canary at " + format_ptr(data_ptr + length + 1));
|
|
55
|
-
}
|
|
56
|
-
#endif
|
|
57
50
|
|
|
58
51
|
// First canary value is a int32_t 0 which gives us four NULLs
|
|
59
52
|
*((int32_t *)(data_ptr + length + 1)) = 0;
|
|
60
|
-
#ifdef LOG_CANARY_WRITES
|
|
61
|
-
if (unlikely(verbose_flag)) {
|
|
62
|
-
debug_log("configure_cbuffer",
|
|
63
|
-
"Writing second canary at " +
|
|
64
|
-
format_ptr(data_ptr + length + 1 + sizeof(int32_t)));
|
|
65
|
-
}
|
|
66
|
-
#endif
|
|
67
53
|
|
|
68
54
|
// Second canary value is a int32_t 0xdeadbeef
|
|
69
55
|
*((int32_t *)(data_ptr + length + 1 + sizeof(int32_t))) = canary_constant;
|
|
@@ -80,7 +66,7 @@ __attribute__((always_inline)) inline bool check_canary_ptr(char *canary_ptr) {
|
|
|
80
66
|
if (zero_value != 0) {
|
|
81
67
|
std::string error_msg =
|
|
82
68
|
"Canary check failed: " + std::to_string(zero_value) + " != 0";
|
|
83
|
-
error_log(
|
|
69
|
+
error_log(__func__, error_msg);
|
|
84
70
|
return false;
|
|
85
71
|
}
|
|
86
72
|
int32_t canary_value = *((int32_t *)(canary_ptr + sizeof(int32_t)));
|
|
@@ -88,7 +74,7 @@ __attribute__((always_inline)) inline bool check_canary_ptr(char *canary_ptr) {
|
|
|
88
74
|
std::string error_msg =
|
|
89
75
|
"Canary check failed: " + std::to_string(canary_value) +
|
|
90
76
|
" != " + std::to_string(canary_constant);
|
|
91
|
-
error_log(
|
|
77
|
+
error_log(__func__, error_msg);
|
|
92
78
|
return false;
|
|
93
79
|
}
|
|
94
80
|
return true;
|
|
@@ -98,12 +84,9 @@ __attribute__((always_inline)) inline std::unique_ptr<char[]>
|
|
|
98
84
|
heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
|
|
99
85
|
size_t cobhan_buffer_allocation_size =
|
|
100
86
|
calculate_cobhan_buffer_allocation_size(size_bytes);
|
|
87
|
+
|
|
101
88
|
if (unlikely(verbose_flag)) {
|
|
102
|
-
|
|
103
|
-
"heap_allocate_cbuffer(" + std::to_string(size_bytes) +
|
|
104
|
-
") (heap) cobhan_buffer_allocation_size: " +
|
|
105
|
-
std::to_string(cobhan_buffer_allocation_size) + " for " + variable_name;
|
|
106
|
-
debug_log("allocate_cbuffer", log_msg);
|
|
89
|
+
debug_log_new(__func__, variable_name, cobhan_buffer_allocation_size);
|
|
107
90
|
}
|
|
108
91
|
|
|
109
92
|
char *cobhan_buffer = new (std::nothrow) char[cobhan_buffer_allocation_size];
|
|
@@ -111,7 +94,7 @@ heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
|
|
|
111
94
|
std::string error_msg = "new[" +
|
|
112
95
|
std::to_string(cobhan_buffer_allocation_size) +
|
|
113
96
|
"] returned null";
|
|
114
|
-
error_log(
|
|
97
|
+
error_log(__func__, error_msg);
|
|
115
98
|
return nullptr;
|
|
116
99
|
}
|
|
117
100
|
std::unique_ptr<char[]> cobhan_buffer_unique_ptr(cobhan_buffer);
|
|
@@ -120,7 +103,7 @@ heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
|
|
|
120
103
|
}
|
|
121
104
|
|
|
122
105
|
#define ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, buffer_size, unique_ptr, \
|
|
123
|
-
function_name)
|
|
106
|
+
max_stack_alloc_size, function_name) \
|
|
124
107
|
do { \
|
|
125
108
|
if (buffer_size < max_stack_alloc_size) { \
|
|
126
109
|
/* If the buffer is small enough, allocate it on the stack */ \
|
|
@@ -142,9 +125,11 @@ heap_allocate_cbuffer(const char *variable_name, size_t size_bytes) {
|
|
|
142
125
|
} \
|
|
143
126
|
} while (0);
|
|
144
127
|
|
|
145
|
-
#define ALLOCATE_CBUFFER(cobhan_buffer, buffer_size,
|
|
128
|
+
#define ALLOCATE_CBUFFER(cobhan_buffer, buffer_size, max_stack_alloc_size, \
|
|
129
|
+
function_name) \
|
|
146
130
|
std::unique_ptr<char[]> cobhan_buffer##_unique_ptr; \
|
|
147
131
|
ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, buffer_size, \
|
|
148
|
-
cobhan_buffer##_unique_ptr,
|
|
132
|
+
cobhan_buffer##_unique_ptr, \
|
|
133
|
+
max_stack_alloc_size, function_name);
|
|
149
134
|
|
|
150
135
|
#endif
|
|
@@ -6,84 +6,7 @@
|
|
|
6
6
|
#include <napi.h>
|
|
7
7
|
#include <string>
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const size_t est_encryption_overhead = 48;
|
|
12
|
-
const size_t est_envelope_overhead = 185;
|
|
13
|
-
const double base64_overhead = 1.34;
|
|
14
|
-
|
|
15
|
-
std::string napi_status_to_string(napi_status status) {
|
|
16
|
-
switch (status) {
|
|
17
|
-
case napi_ok:
|
|
18
|
-
return "napi_ok";
|
|
19
|
-
case napi_invalid_arg:
|
|
20
|
-
return "napi_invalid_arg";
|
|
21
|
-
case napi_object_expected:
|
|
22
|
-
return "napi_object_expected";
|
|
23
|
-
case napi_string_expected:
|
|
24
|
-
return "napi_string_expected";
|
|
25
|
-
case napi_name_expected:
|
|
26
|
-
return "napi_name_expected";
|
|
27
|
-
case napi_function_expected:
|
|
28
|
-
return "napi_function_expected";
|
|
29
|
-
case napi_number_expected:
|
|
30
|
-
return "napi_number_expected";
|
|
31
|
-
case napi_boolean_expected:
|
|
32
|
-
return "napi_boolean_expected";
|
|
33
|
-
case napi_array_expected:
|
|
34
|
-
return "napi_array_expected";
|
|
35
|
-
case napi_generic_failure:
|
|
36
|
-
return "napi_generic_failure";
|
|
37
|
-
case napi_pending_exception:
|
|
38
|
-
return "napi_pending_exception";
|
|
39
|
-
case napi_cancelled:
|
|
40
|
-
return "napi_cancelled";
|
|
41
|
-
case napi_escape_called_twice:
|
|
42
|
-
return "napi_escape_called_twice";
|
|
43
|
-
case napi_handle_scope_mismatch:
|
|
44
|
-
return "napi_handle_scope_mismatch";
|
|
45
|
-
case napi_callback_scope_mismatch:
|
|
46
|
-
return "napi_callback_scope_mismatch";
|
|
47
|
-
case napi_queue_full:
|
|
48
|
-
return "napi_queue_full";
|
|
49
|
-
case napi_closing:
|
|
50
|
-
return "napi_closing";
|
|
51
|
-
case napi_bigint_expected:
|
|
52
|
-
return "napi_bigint_expected";
|
|
53
|
-
case napi_date_expected:
|
|
54
|
-
return "napi_date_expected";
|
|
55
|
-
case napi_arraybuffer_expected:
|
|
56
|
-
return "napi_arraybuffer_expected";
|
|
57
|
-
case napi_detachable_arraybuffer_expected:
|
|
58
|
-
return "napi_detachable_arraybuffer_expected";
|
|
59
|
-
case napi_would_deadlock:
|
|
60
|
-
return "napi_would_deadlock";
|
|
61
|
-
default:
|
|
62
|
-
return "Unknown napi_status";
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
__attribute__((always_inline)) inline size_t
|
|
67
|
-
estimate_asherah_output_size_bytes(size_t data_byte_len,
|
|
68
|
-
size_t partition_byte_len) {
|
|
69
|
-
// Add one rather than using std::ceil to round up
|
|
70
|
-
double est_data_byte_len =
|
|
71
|
-
(double(data_byte_len + est_encryption_overhead) * base64_overhead) + 1;
|
|
72
|
-
|
|
73
|
-
size_t asherah_output_size_bytes =
|
|
74
|
-
size_t(est_envelope_overhead + est_intermediate_key_overhead +
|
|
75
|
-
partition_byte_len + est_data_byte_len);
|
|
76
|
-
if (unlikely(verbose_flag)) {
|
|
77
|
-
std::string log_msg =
|
|
78
|
-
"estimate_asherah_output_size(" + std::to_string(data_byte_len) + ", " +
|
|
79
|
-
std::to_string(partition_byte_len) +
|
|
80
|
-
") est_data_byte_len: " + std::to_string(est_data_byte_len) +
|
|
81
|
-
" asherah_output_size_bytes: " +
|
|
82
|
-
std::to_string(asherah_output_size_bytes);
|
|
83
|
-
debug_log("estimate_asherah_output_size", log_msg);
|
|
84
|
-
}
|
|
85
|
-
return asherah_output_size_bytes;
|
|
86
|
-
}
|
|
9
|
+
std::string napi_status_to_string(napi_status status);
|
|
87
10
|
|
|
88
11
|
__attribute__((always_inline)) inline size_t
|
|
89
12
|
nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
|
|
@@ -92,9 +15,8 @@ nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
|
|
|
92
15
|
|
|
93
16
|
status = napi_get_value_string_utf8(env, str, nullptr, 0, &utf8_length);
|
|
94
17
|
if (unlikely(status != napi_ok)) {
|
|
95
|
-
error_log("
|
|
96
|
-
|
|
97
|
-
napi_status_to_string(status));
|
|
18
|
+
error_log(__func__, "napi_get_value_string_utf8 length check failed: " +
|
|
19
|
+
napi_status_to_string(status));
|
|
98
20
|
return (size_t)(-1);
|
|
99
21
|
}
|
|
100
22
|
|
|
@@ -104,21 +26,21 @@ nstring_utf8_byte_length(Napi::Env &env, Napi::String &str) {
|
|
|
104
26
|
__attribute__((always_inline)) inline char *
|
|
105
27
|
copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
|
|
106
28
|
size_t str_utf8_byte_length, char *cobhan_buffer,
|
|
107
|
-
size_t *byte_length
|
|
29
|
+
size_t *byte_length) {
|
|
108
30
|
|
|
109
31
|
size_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
|
|
110
32
|
if (unlikely(cobhan_buffer_size_bytes <= 0)) {
|
|
111
|
-
error_log(
|
|
33
|
+
error_log(__func__, "Invalid cobhan buffer byte length");
|
|
112
34
|
return nullptr;
|
|
113
35
|
}
|
|
114
36
|
|
|
115
37
|
if (cobhan_buffer_size_bytes < str_utf8_byte_length) {
|
|
116
|
-
error_log(
|
|
38
|
+
error_log(__func__, "String too large for cobhan buffer");
|
|
117
39
|
return nullptr;
|
|
118
40
|
}
|
|
119
41
|
|
|
120
42
|
if (unlikely(verbose_flag)) {
|
|
121
|
-
debug_log(
|
|
43
|
+
debug_log(__func__,
|
|
122
44
|
"Copying " + std::to_string(str_utf8_byte_length) + " bytes to " +
|
|
123
45
|
format_ptr(cbuffer_data_ptr(cobhan_buffer)) + " - " +
|
|
124
46
|
format_ptr((cbuffer_data_ptr(cobhan_buffer) +
|
|
@@ -133,24 +55,21 @@ copy_nstring_to_cbuffer(Napi::Env &env, Napi::String &str,
|
|
|
133
55
|
status = napi_get_value_string_utf8(env, str, cbuffer_data_ptr(cobhan_buffer),
|
|
134
56
|
str_utf8_byte_length + 1, &copied_bytes);
|
|
135
57
|
if (unlikely(status != napi_ok)) {
|
|
136
|
-
error_log("
|
|
137
|
-
|
|
138
|
-
napi_status_to_string(status));
|
|
58
|
+
error_log(__func__, "Napi utf8 string conversion failure: " +
|
|
59
|
+
napi_status_to_string(status));
|
|
139
60
|
return nullptr;
|
|
140
61
|
}
|
|
141
62
|
|
|
142
63
|
if (unlikely(copied_bytes != str_utf8_byte_length)) {
|
|
143
|
-
error_log("
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
std::to_string(copied_bytes));
|
|
64
|
+
error_log(__func__, "Did not copy expected number of bytes " +
|
|
65
|
+
std::to_string(str_utf8_byte_length) + " copied " +
|
|
66
|
+
std::to_string(copied_bytes));
|
|
147
67
|
return nullptr;
|
|
148
68
|
}
|
|
149
69
|
|
|
150
70
|
configure_cbuffer(cobhan_buffer, copied_bytes);
|
|
151
71
|
|
|
152
|
-
|
|
153
|
-
*byte_length = copied_bytes;
|
|
72
|
+
*byte_length = copied_bytes;
|
|
154
73
|
return cobhan_buffer;
|
|
155
74
|
}
|
|
156
75
|
|
|
@@ -160,8 +79,7 @@ cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
|
|
|
160
79
|
|
|
161
80
|
int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
|
|
162
81
|
if (cobhan_buffer_size_bytes <= 0) {
|
|
163
|
-
log_error_and_throw("
|
|
164
|
-
"Invalid cobhan buffer byte length");
|
|
82
|
+
log_error_and_throw(__func__, "Invalid cobhan buffer byte length");
|
|
165
83
|
}
|
|
166
84
|
|
|
167
85
|
// Using C function because it allows length delimited input
|
|
@@ -169,9 +87,8 @@ cbuffer_to_nstring(Napi::Env &env, char *cobhan_buffer) {
|
|
|
169
87
|
env, cbuffer_data_ptr(cobhan_buffer), cobhan_buffer_size_bytes, &output);
|
|
170
88
|
|
|
171
89
|
if (unlikely(status != napi_ok)) {
|
|
172
|
-
log_error_and_throw("
|
|
173
|
-
|
|
174
|
-
napi_status_to_string(status));
|
|
90
|
+
log_error_and_throw(__func__, "napi_create_string_utf8 failed: " +
|
|
91
|
+
napi_status_to_string(status));
|
|
175
92
|
}
|
|
176
93
|
|
|
177
94
|
return Napi::String(env, output);
|
|
@@ -181,28 +98,16 @@ __attribute__((always_inline)) inline Napi::Buffer<unsigned char>
|
|
|
181
98
|
cbuffer_to_nbuffer(Napi::Env &env, char *cobhan_buffer) {
|
|
182
99
|
int32_t cobhan_buffer_byte_length = cbuffer_byte_length(cobhan_buffer);
|
|
183
100
|
if (unlikely(cobhan_buffer_byte_length <= 0)) {
|
|
184
|
-
log_error_and_throw("
|
|
185
|
-
"Invalid cobhan buffer byte length");
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (unlikely(verbose_flag)) {
|
|
189
|
-
debug_log("cbuffer_to_nbuffer",
|
|
190
|
-
"cbuffer_byte_length: " +
|
|
191
|
-
std::to_string(cobhan_buffer_byte_length));
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (unlikely(cobhan_buffer_byte_length <= 0)) {
|
|
195
|
-
log_error_and_throw("cbuffer_to_nbuffer",
|
|
196
|
-
"Invalid cobhan buffer byte length");
|
|
101
|
+
log_error_and_throw(__func__, "Invalid cobhan buffer byte length");
|
|
197
102
|
}
|
|
198
103
|
|
|
199
104
|
Napi::Buffer<unsigned char> nbuffer = Napi::Buffer<unsigned char>::Copy(
|
|
200
105
|
env, (const unsigned char *)cbuffer_data_ptr(cobhan_buffer),
|
|
201
106
|
cobhan_buffer_byte_length);
|
|
202
107
|
|
|
203
|
-
if (unlikely(
|
|
204
|
-
|
|
205
|
-
|
|
108
|
+
if (unlikely(nbuffer.ByteLength() != (size_t)cobhan_buffer_byte_length)) {
|
|
109
|
+
log_error_and_throw(__func__,
|
|
110
|
+
"Failed to copy cobhan buffer to napi buffer");
|
|
206
111
|
}
|
|
207
112
|
|
|
208
113
|
return nbuffer;
|
|
@@ -214,16 +119,25 @@ copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
|
|
|
214
119
|
|
|
215
120
|
int32_t cobhan_buffer_size_bytes = cbuffer_byte_length(cobhan_buffer);
|
|
216
121
|
if (unlikely(cobhan_buffer_size_bytes <= 0)) {
|
|
217
|
-
error_log(
|
|
122
|
+
error_log(__func__, "Invalid cobhan buffer byte length");
|
|
218
123
|
return nullptr;
|
|
219
124
|
}
|
|
220
125
|
|
|
221
126
|
size_t nbuffer_byte_length = nbuffer.ByteLength();
|
|
222
127
|
if (nbuffer_byte_length > INT32_MAX ||
|
|
223
128
|
cobhan_buffer_size_bytes < (int32_t)nbuffer_byte_length) {
|
|
224
|
-
error_log(
|
|
129
|
+
error_log(__func__, "Buffer too large for cobhan buffer");
|
|
225
130
|
return nullptr;
|
|
226
131
|
}
|
|
132
|
+
|
|
133
|
+
if (unlikely(verbose_flag)) {
|
|
134
|
+
debug_log(__func__,
|
|
135
|
+
"Copying " + std::to_string(nbuffer_byte_length) + " bytes to " +
|
|
136
|
+
format_ptr(cbuffer_data_ptr(cobhan_buffer)) + " - " +
|
|
137
|
+
format_ptr(
|
|
138
|
+
(cbuffer_data_ptr(cobhan_buffer) + nbuffer_byte_length)));
|
|
139
|
+
}
|
|
140
|
+
|
|
227
141
|
memcpy(cbuffer_data_ptr(cobhan_buffer), nbuffer.Data(), nbuffer_byte_length);
|
|
228
142
|
configure_cbuffer(cobhan_buffer, nbuffer_byte_length);
|
|
229
143
|
return cobhan_buffer;
|
|
@@ -232,7 +146,7 @@ copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
|
|
|
232
146
|
// These are macros due to the use of alloca()
|
|
233
147
|
|
|
234
148
|
#define NAPI_STRING_TO_CBUFFER(env, napi_string, cobhan_buffer, bytes_copied, \
|
|
235
|
-
function_name)
|
|
149
|
+
max_stack_alloc_size, function_name) \
|
|
236
150
|
std::unique_ptr<char[]> napi_string##_unique_ptr; \
|
|
237
151
|
do { \
|
|
238
152
|
/* Determine size */ \
|
|
@@ -247,7 +161,8 @@ copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
|
|
|
247
161
|
} \
|
|
248
162
|
/* Allocate */ \
|
|
249
163
|
ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, napi_string##_utf8_byte_length, \
|
|
250
|
-
napi_string##_unique_ptr,
|
|
164
|
+
napi_string##_unique_ptr, \
|
|
165
|
+
max_stack_alloc_size, function_name); \
|
|
251
166
|
/* Copy */ \
|
|
252
167
|
cobhan_buffer = copy_nstring_to_cbuffer(env, napi_string, \
|
|
253
168
|
napi_string##_utf8_byte_length, \
|
|
@@ -259,7 +174,7 @@ copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
|
|
|
259
174
|
} while (0);
|
|
260
175
|
|
|
261
176
|
#define NAPI_BUFFER_TO_CBUFFER(env, napi_buffer, cobhan_buffer, bytes_copied, \
|
|
262
|
-
function_name)
|
|
177
|
+
max_stack_alloc_size, function_name) \
|
|
263
178
|
std::unique_ptr<char[]> napi_buffer##_unique_ptr; \
|
|
264
179
|
do { \
|
|
265
180
|
/* Determine size */ \
|
|
@@ -269,7 +184,8 @@ copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
|
|
|
269
184
|
} \
|
|
270
185
|
/* Allocate */ \
|
|
271
186
|
ALLOCATE_CBUFFER_UNIQUE_PTR(cobhan_buffer, napi_buffer##_byte_length, \
|
|
272
|
-
napi_buffer##_unique_ptr,
|
|
187
|
+
napi_buffer##_unique_ptr, \
|
|
188
|
+
max_stack_alloc_size, function_name); \
|
|
273
189
|
/* Copy */ \
|
|
274
190
|
cobhan_buffer = copy_nbuffer_to_cbuffer(env, napi_buffer, cobhan_buffer); \
|
|
275
191
|
if (unlikely(cobhan_buffer == nullptr)) { \
|
|
@@ -279,4 +195,55 @@ copy_nbuffer_to_cbuffer(Napi::Env &env, Napi::Buffer<unsigned char> &nbuffer,
|
|
|
279
195
|
bytes_copied = napi_buffer##_byte_length; \
|
|
280
196
|
} while (0);
|
|
281
197
|
|
|
198
|
+
std::string napi_status_to_string(napi_status status) {
|
|
199
|
+
switch (status) {
|
|
200
|
+
case napi_ok:
|
|
201
|
+
return "napi_ok";
|
|
202
|
+
case napi_invalid_arg:
|
|
203
|
+
return "napi_invalid_arg";
|
|
204
|
+
case napi_object_expected:
|
|
205
|
+
return "napi_object_expected";
|
|
206
|
+
case napi_string_expected:
|
|
207
|
+
return "napi_string_expected";
|
|
208
|
+
case napi_name_expected:
|
|
209
|
+
return "napi_name_expected";
|
|
210
|
+
case napi_function_expected:
|
|
211
|
+
return "napi_function_expected";
|
|
212
|
+
case napi_number_expected:
|
|
213
|
+
return "napi_number_expected";
|
|
214
|
+
case napi_boolean_expected:
|
|
215
|
+
return "napi_boolean_expected";
|
|
216
|
+
case napi_array_expected:
|
|
217
|
+
return "napi_array_expected";
|
|
218
|
+
case napi_generic_failure:
|
|
219
|
+
return "napi_generic_failure";
|
|
220
|
+
case napi_pending_exception:
|
|
221
|
+
return "napi_pending_exception";
|
|
222
|
+
case napi_cancelled:
|
|
223
|
+
return "napi_cancelled";
|
|
224
|
+
case napi_escape_called_twice:
|
|
225
|
+
return "napi_escape_called_twice";
|
|
226
|
+
case napi_handle_scope_mismatch:
|
|
227
|
+
return "napi_handle_scope_mismatch";
|
|
228
|
+
case napi_callback_scope_mismatch:
|
|
229
|
+
return "napi_callback_scope_mismatch";
|
|
230
|
+
case napi_queue_full:
|
|
231
|
+
return "napi_queue_full";
|
|
232
|
+
case napi_closing:
|
|
233
|
+
return "napi_closing";
|
|
234
|
+
case napi_bigint_expected:
|
|
235
|
+
return "napi_bigint_expected";
|
|
236
|
+
case napi_date_expected:
|
|
237
|
+
return "napi_date_expected";
|
|
238
|
+
case napi_arraybuffer_expected:
|
|
239
|
+
return "napi_arraybuffer_expected";
|
|
240
|
+
case napi_detachable_arraybuffer_expected:
|
|
241
|
+
return "napi_detachable_arraybuffer_expected";
|
|
242
|
+
case napi_would_deadlock:
|
|
243
|
+
return "napi_would_deadlock";
|
|
244
|
+
default:
|
|
245
|
+
return "Unknown napi_status";
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
282
249
|
#endif
|
package/src/logging.h
CHANGED
|
@@ -38,6 +38,16 @@ debug_log_alloca(const char *function_name, const char *variable_name,
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
__attribute__((always_inline)) inline void
|
|
42
|
+
debug_log_new(const char *function_name, const char *variable_name,
|
|
43
|
+
size_t length) {
|
|
44
|
+
if (unlikely(verbose_flag)) {
|
|
45
|
+
std::cerr << "asherah-node: [DEBUG] " << function_name << ": Calling new["
|
|
46
|
+
<< length << "] (heap) for " << variable_name << std::endl
|
|
47
|
+
<< std::flush;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
41
51
|
__attribute__((always_inline)) inline void error_log(const char *function_name,
|
|
42
52
|
const char *message) {
|
|
43
53
|
if (unlikely(verbose_flag)) {
|