asherah 3.0.16 → 4.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -171
- package/index.d.ts +102 -0
- package/npm/index.js +188 -0
- package/package.json +23 -78
- package/.asherah-version +0 -1
- package/LICENSE +0 -21
- package/SHA256SUMS +0 -12
- package/SHA256SUMS-darwin +0 -12
- package/binding.gyp +0 -36
- package/scripts/build.sh +0 -16
- package/scripts/download-libraries.sh +0 -322
- package/src/asherah.cc +0 -792
- package/src/asherah.d.ts +0 -65
- package/src/asherah_async_worker.h +0 -60
- package/src/cobhan_buffer.h +0 -260
- package/src/cobhan_buffer_napi.h +0 -218
- package/src/hints.h +0 -7
- package/src/logging.h +0 -49
- package/src/logging_napi.cc +0 -115
- package/src/logging_napi.h +0 -41
- package/src/logging_stderr.cc +0 -60
- package/src/logging_stderr.h +0 -23
- package/src/napi_utils.h +0 -164
- package/src/scoped_allocate.h +0 -50
package/src/asherah.d.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// noinspection JSUnusedGlobalSymbols,DuplicatedCode
|
|
2
|
-
|
|
3
|
-
/// <reference types="node" />
|
|
4
|
-
export type AsherahConfig = {
|
|
5
|
-
/** The name of this service (Required) */
|
|
6
|
-
ServiceName: string;
|
|
7
|
-
/** The name of the product that owns this service (Required) */
|
|
8
|
-
ProductID: string;
|
|
9
|
-
/** The amount of time a key is considered valid */
|
|
10
|
-
ExpireAfter: number | null;
|
|
11
|
-
/** The amount of time before cached keys are considered stale */
|
|
12
|
-
CheckInterval: number | null;
|
|
13
|
-
/** Determines the type of metastore to use for persisting keys (Required) { "rdbms", "dynamodb", "memory" } */
|
|
14
|
-
Metastore: string;
|
|
15
|
-
/** The database connection string (Required if metastore=rdbms) */
|
|
16
|
-
ConnectionString: string | null;
|
|
17
|
-
/** Required for Aurora sessions using write forwarding { "eventual", "global", "session" } */
|
|
18
|
-
ReplicaReadConsistency: string | null;
|
|
19
|
-
/** An optional endpoint URL (hostname only or fully qualified URI) (only supported by metastore=dynamodb) */
|
|
20
|
-
DynamoDBEndpoint: string | null;
|
|
21
|
-
/** The AWS region for DynamoDB requests (defaults to globally configured region) (only supported by metastore=dynamodb) */
|
|
22
|
-
DynamoDBRegion: string | null;
|
|
23
|
-
/** The table name for DynamoDB (only supported by metastore=dynamodb) */
|
|
24
|
-
DynamoDBTableName: string | null;
|
|
25
|
-
/** Define the maximum number of sessions to cache (Default 1000) */
|
|
26
|
-
SessionCacheMaxSize: number | null;
|
|
27
|
-
/** The amount of time a session will remain cached (Default 2h) */
|
|
28
|
-
SessionCacheDuration: number | null;
|
|
29
|
-
/** Configures the master key management service (Default kms) { "aws", "static" } */
|
|
30
|
-
KMS: string | null;
|
|
31
|
-
/** Dictionary of REGION: ARN (required if kms=aws) */
|
|
32
|
-
RegionMap: {
|
|
33
|
-
[name: string]: string;
|
|
34
|
-
} | null;
|
|
35
|
-
/** The preferred AWS region (required if kms=aws) */
|
|
36
|
-
PreferredRegion: string | null;
|
|
37
|
-
/** Configure the metastore to use regional suffixes (only supported by metastore=dynamodb) */
|
|
38
|
-
EnableRegionSuffix: boolean | null;
|
|
39
|
-
/** Enable shared session caching */
|
|
40
|
-
EnableSessionCaching: boolean | null;
|
|
41
|
-
/** Enable verbose logging output */
|
|
42
|
-
Verbose: boolean | null;
|
|
43
|
-
/** Disable the zero-copy optimization for the cobhan buffer protocol */
|
|
44
|
-
DisableZeroCopy: boolean | null;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
type LogHookCallback = (level: number, message: string) => void;
|
|
48
|
-
|
|
49
|
-
export declare function setup(config: AsherahConfig): void;
|
|
50
|
-
export declare function setup_async(config: AsherahConfig): Promise;
|
|
51
|
-
export declare function shutdown(): void;
|
|
52
|
-
export declare function shutdown_async(): Promise;
|
|
53
|
-
export declare function decrypt(partitionId: string, dataRowRecord: string): Buffer;
|
|
54
|
-
export declare function decrypt_async(partitionId: string, dataRowRecord: string): Promise<Buffer>;
|
|
55
|
-
export declare function encrypt(partitionId: string, data: Buffer): string;
|
|
56
|
-
export declare function encrypt_async(partitionId: string, data: Buffer): Promise<string>;
|
|
57
|
-
export declare function decrypt_string(partitionId: string, dataRowRecord: string): string;
|
|
58
|
-
export declare function decrypt_string_async(partitionId: string, dataRowRecord: string): Promise<string>;
|
|
59
|
-
export declare function encrypt_string(partitionId: string, data: string): string;
|
|
60
|
-
export declare function encrypt_string_async(partitionId: string, data: string): Promise<string>;
|
|
61
|
-
export declare function set_max_stack_alloc_item_size(max_item_size: number): void;
|
|
62
|
-
export declare function set_safety_padding_overhead(safety_padding_overhead: number): void;
|
|
63
|
-
export declare function set_log_hook(logHook: LogHookCallback): void;
|
|
64
|
-
export declare function get_setup_status(): boolean;
|
|
65
|
-
export declare function setenv(environment: string): void;
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
#ifndef ASHERAH_ASYNC_WORKER_H
|
|
2
|
-
#define ASHERAH_ASYNC_WORKER_H
|
|
3
|
-
|
|
4
|
-
#include <napi.h>
|
|
5
|
-
#include <stdexcept>
|
|
6
|
-
|
|
7
|
-
class Asherah;
|
|
8
|
-
|
|
9
|
-
template <typename ResultType>
|
|
10
|
-
class AsherahAsyncWorker : public Napi::AsyncWorker {
|
|
11
|
-
public:
|
|
12
|
-
Napi::Promise Promise() { return deferred.Promise(); }
|
|
13
|
-
|
|
14
|
-
AsherahAsyncWorker(Napi::Env env, Asherah *instance)
|
|
15
|
-
: Napi::AsyncWorker(env), asherah(instance), deferred(env) {}
|
|
16
|
-
|
|
17
|
-
protected:
|
|
18
|
-
Asherah *asherah;
|
|
19
|
-
ResultType result;
|
|
20
|
-
|
|
21
|
-
virtual ResultType ExecuteTask() = 0;
|
|
22
|
-
virtual Napi::Value OnOKTask(Napi::Env &env) = 0;
|
|
23
|
-
virtual Napi::Value OnErrorTask(Napi::Env &, Napi::Error const &error) {
|
|
24
|
-
return error.Value();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
private:
|
|
28
|
-
Napi::Promise::Deferred deferred;
|
|
29
|
-
|
|
30
|
-
void Execute() final {
|
|
31
|
-
try {
|
|
32
|
-
result = ExecuteTask();
|
|
33
|
-
} catch (const std::exception &ex) {
|
|
34
|
-
SetError(ex.what());
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
void OnOK() final {
|
|
39
|
-
Napi::Env env = Env();
|
|
40
|
-
Napi::HandleScope scope(env);
|
|
41
|
-
try {
|
|
42
|
-
auto value = OnOKTask(env);
|
|
43
|
-
deferred.Resolve(value);
|
|
44
|
-
} catch (const std::exception &e) {
|
|
45
|
-
deferred.Reject(Napi::Error::New(Env(), e.what()).Value());
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
void OnError(Napi::Error const &error) final {
|
|
50
|
-
Napi::Env env = Env();
|
|
51
|
-
Napi::HandleScope scope(Env());
|
|
52
|
-
try {
|
|
53
|
-
deferred.Reject(OnErrorTask(env, error));
|
|
54
|
-
} catch (const std::exception &e) {
|
|
55
|
-
deferred.Reject(Napi::Error::New(Env(), e.what()).Value());
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
#endif // ASHERAH_ASYNC_WORKER_H
|
package/src/cobhan_buffer.h
DELETED
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
#ifndef COBHAN_BUFFER_H
|
|
2
|
-
#define COBHAN_BUFFER_H
|
|
3
|
-
|
|
4
|
-
#include <cstdint> // for int32_t
|
|
5
|
-
#include <cstring> // for std::memcpy
|
|
6
|
-
#include <iostream> // for std::terminate
|
|
7
|
-
#include <limits> // for std::numeric_limits
|
|
8
|
-
#include <sstream> // for std::ostringstream
|
|
9
|
-
#include <stdexcept> // for std::runtime_error, std::invalid_argument
|
|
10
|
-
#include <string> // for std::string
|
|
11
|
-
|
|
12
|
-
#ifdef _WIN32
|
|
13
|
-
#include <windows.h> // for SecureZeroMemory
|
|
14
|
-
#else
|
|
15
|
-
#include <string.h> // for explicit_bzero
|
|
16
|
-
#endif
|
|
17
|
-
|
|
18
|
-
class CobhanBuffer {
|
|
19
|
-
public:
|
|
20
|
-
// Used for requesting a new heap-based buffer allocation that can handle
|
|
21
|
-
// data_len_bytes of data
|
|
22
|
-
explicit CobhanBuffer(size_t data_len_bytes) {
|
|
23
|
-
if (data_len_bytes > max_int32_size) {
|
|
24
|
-
throw std::invalid_argument(
|
|
25
|
-
"Requested data length exceeds maximum allowable size");
|
|
26
|
-
}
|
|
27
|
-
allocation_size = DataSizeToAllocationSize(data_len_bytes);
|
|
28
|
-
cbuffer = new char[allocation_size];
|
|
29
|
-
ownership = true;
|
|
30
|
-
initialize(data_len_bytes);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Used for passing a stack-based buffer allocation that hasn't been
|
|
34
|
-
// initialized yet
|
|
35
|
-
explicit CobhanBuffer(char *cbuffer, size_t allocation_size)
|
|
36
|
-
: cbuffer(cbuffer), allocation_size(allocation_size), ownership(false) {
|
|
37
|
-
if (allocation_size > max_int32_size) {
|
|
38
|
-
throw std::invalid_argument(
|
|
39
|
-
"Allocation size exceeds maximum allowable size");
|
|
40
|
-
}
|
|
41
|
-
initialize();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Move constructor
|
|
45
|
-
CobhanBuffer(CobhanBuffer &&other) noexcept { moveFrom(std::move(other)); }
|
|
46
|
-
|
|
47
|
-
// Move assignment operator
|
|
48
|
-
CobhanBuffer &operator=(CobhanBuffer &&other) noexcept {
|
|
49
|
-
if (this != &other) {
|
|
50
|
-
cleanup();
|
|
51
|
-
moveFrom(std::move(other));
|
|
52
|
-
}
|
|
53
|
-
return *this;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Implicit cast to void*
|
|
57
|
-
operator void *() const { // NOLINT(*-explicit-constructor)
|
|
58
|
-
return static_cast<void *>(cbuffer);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
[[nodiscard]] char *get_data_ptr() const { return data_ptr; }
|
|
62
|
-
|
|
63
|
-
[[nodiscard]] size_t get_data_len_bytes() const { return *data_len_ptr; }
|
|
64
|
-
|
|
65
|
-
void secure_wipe_data() {
|
|
66
|
-
if (data_ptr && get_data_len_bytes() > 0) {
|
|
67
|
-
#ifdef _WIN32
|
|
68
|
-
// Windows secure zero
|
|
69
|
-
SecureZeroMemory(data_ptr, get_data_len_bytes());
|
|
70
|
-
#elif defined(__linux__) && defined(__GLIBC__)
|
|
71
|
-
// Linux with glibc has explicit_bzero
|
|
72
|
-
explicit_bzero(data_ptr, get_data_len_bytes());
|
|
73
|
-
#else
|
|
74
|
-
// Fallback - volatile to prevent optimization
|
|
75
|
-
volatile char *p = data_ptr;
|
|
76
|
-
size_t len = get_data_len_bytes();
|
|
77
|
-
while (len--) *p++ = 0;
|
|
78
|
-
#endif
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
~CobhanBuffer() {
|
|
83
|
-
verify_canaries();
|
|
84
|
-
cleanup();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
[[nodiscard]] __attribute__((unused)) std::string DebugPrintStdErr() const {
|
|
88
|
-
auto debug_string = std::string(get_data_ptr(), get_data_len_bytes());
|
|
89
|
-
std::ostringstream debug_output;
|
|
90
|
-
debug_output << "CobhanBuffer { " << std::endl
|
|
91
|
-
<< "data_len_bytes=" << get_data_len_bytes() << std::endl
|
|
92
|
-
<< ", allocation_size=" << get_allocation_size() << std::endl
|
|
93
|
-
<< ", data_ptr=" << static_cast<void *>(get_data_ptr())
|
|
94
|
-
<< std::endl
|
|
95
|
-
<< ", canary1=" << static_cast<void *>(canary1_ptr)
|
|
96
|
-
<< std::endl
|
|
97
|
-
<< ", canary2=" << static_cast<void *>(canary2_ptr)
|
|
98
|
-
<< std::endl
|
|
99
|
-
<< ", ownership=" << ownership << std::endl
|
|
100
|
-
<< ", string=[" << debug_string << "]" << std::endl
|
|
101
|
-
<< ", string_length=" << debug_string.length() << std::endl
|
|
102
|
-
<< "}" << std::endl
|
|
103
|
-
<< std::flush;
|
|
104
|
-
return debug_output.str();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
static size_t DataSizeToAllocationSize(size_t data_len_bytes) {
|
|
108
|
-
size_t allocation =
|
|
109
|
-
data_len_bytes + cobhan_header_size_bytes +
|
|
110
|
-
canary_size_bytes // Add space for canary value
|
|
111
|
-
+ safety_padding_bytes; // Add safety padding if configured
|
|
112
|
-
if (allocation > max_int32_size) {
|
|
113
|
-
throw std::invalid_argument(
|
|
114
|
-
"Calculated allocation size exceeds maximum allowable size");
|
|
115
|
-
}
|
|
116
|
-
return allocation;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
static size_t AllocationSizeToMaxDataSize(size_t allocation_len_bytes) {
|
|
120
|
-
size_t data_len_bytes = allocation_len_bytes - cobhan_header_size_bytes -
|
|
121
|
-
canary_size_bytes - safety_padding_bytes;
|
|
122
|
-
if (data_len_bytes > max_int32_size) {
|
|
123
|
-
throw std::invalid_argument(
|
|
124
|
-
"Calculated data size exceeds maximum allowable size");
|
|
125
|
-
}
|
|
126
|
-
return data_len_bytes;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
protected:
|
|
130
|
-
void verify_canaries() const {
|
|
131
|
-
if (*canary1_ptr != 0) {
|
|
132
|
-
std::cerr << "Canary 1 corrupted! Expected: 0, Found: " << *canary1_ptr
|
|
133
|
-
<< std::endl
|
|
134
|
-
<< std::flush;
|
|
135
|
-
std::cerr << "CobhanBuffer: Memory corruption detected: Canary values "
|
|
136
|
-
"are corrupted. Terminating process."
|
|
137
|
-
<< std::endl
|
|
138
|
-
<< std::flush;
|
|
139
|
-
std::terminate();
|
|
140
|
-
}
|
|
141
|
-
if (*canary2_ptr != canary_constant) {
|
|
142
|
-
std::cerr << "Canary 2 corrupted! Expected: 0xdeadbeef, Found: "
|
|
143
|
-
<< *canary2_ptr << std::endl
|
|
144
|
-
<< std::flush;
|
|
145
|
-
std::cerr << "CobhanBuffer: Memory corruption detected: Canary values "
|
|
146
|
-
"are corrupted. Terminating process."
|
|
147
|
-
<< std::endl
|
|
148
|
-
<< std::flush;
|
|
149
|
-
std::terminate();
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
[[nodiscard]] size_t get_allocation_size() const { return allocation_size; }
|
|
154
|
-
|
|
155
|
-
void set_data_len_bytes(size_t data_len_bytes) {
|
|
156
|
-
if (data_len_bytes > max_int32_size) {
|
|
157
|
-
throw std::invalid_argument(
|
|
158
|
-
"Requested data length exceeds maximum allowable size");
|
|
159
|
-
}
|
|
160
|
-
if (data_len_bytes > allocation_size) {
|
|
161
|
-
throw std::invalid_argument(
|
|
162
|
-
"Requested data length exceeds allocation size");
|
|
163
|
-
}
|
|
164
|
-
*data_len_ptr = static_cast<int32_t>(data_len_bytes);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
private:
|
|
168
|
-
// Assumes cbuffer and allocation_size are already set
|
|
169
|
-
void initialize(size_t data_len_bytes = 0) {
|
|
170
|
-
// Save pointer to data
|
|
171
|
-
data_ptr = cbuffer + cobhan_header_size_bytes;
|
|
172
|
-
// First int32_t is the data length
|
|
173
|
-
data_len_ptr = reinterpret_cast<int32_t *>(cbuffer);
|
|
174
|
-
// Second int32_t is reserved for future use
|
|
175
|
-
auto reserved_ptr = reinterpret_cast<int32_t *>(cbuffer + sizeof(int32_t));
|
|
176
|
-
// First canary value is an int32_t 0 which gives us four NULLs
|
|
177
|
-
canary1_ptr = reinterpret_cast<int32_t *>(cbuffer + allocation_size -
|
|
178
|
-
canary_size_bytes);
|
|
179
|
-
// Second canary value is an int32_t 0xdeadbeef
|
|
180
|
-
canary2_ptr = canary1_ptr + 1;
|
|
181
|
-
|
|
182
|
-
// Calculate the data length
|
|
183
|
-
if (data_len_bytes == 0) {
|
|
184
|
-
data_len_bytes = AllocationSizeToMaxDataSize(allocation_size);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (data_len_bytes > max_int32_size) {
|
|
188
|
-
throw std::invalid_argument("Data length exceeds maximum allowable size");
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Write Cobhan header values
|
|
192
|
-
*data_len_ptr = static_cast<int32_t>(data_len_bytes);
|
|
193
|
-
|
|
194
|
-
// Reserved for future use
|
|
195
|
-
*reserved_ptr = 0;
|
|
196
|
-
|
|
197
|
-
// Write canary values
|
|
198
|
-
*canary1_ptr = 0;
|
|
199
|
-
*canary2_ptr = canary_constant;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
void moveFrom(CobhanBuffer &&other) {
|
|
203
|
-
other.verify_canaries();
|
|
204
|
-
|
|
205
|
-
if (other.ownership) {
|
|
206
|
-
// Transfer ownership of the existing buffer
|
|
207
|
-
cbuffer = other.cbuffer;
|
|
208
|
-
allocation_size = other.allocation_size;
|
|
209
|
-
ownership = true;
|
|
210
|
-
data_ptr = other.data_ptr;
|
|
211
|
-
data_len_ptr = other.data_len_ptr;
|
|
212
|
-
canary1_ptr = other.canary1_ptr;
|
|
213
|
-
canary2_ptr = other.canary2_ptr;
|
|
214
|
-
|
|
215
|
-
// Reset the other object to prevent it from deallocating the buffer
|
|
216
|
-
other.cbuffer = nullptr;
|
|
217
|
-
other.allocation_size = 0;
|
|
218
|
-
other.ownership = false;
|
|
219
|
-
} else {
|
|
220
|
-
// Allocate a new buffer and copy the contents
|
|
221
|
-
allocation_size = other.allocation_size;
|
|
222
|
-
if (allocation_size > max_int32_size) {
|
|
223
|
-
throw std::invalid_argument(
|
|
224
|
-
"Allocation size exceeds maximum allowable size");
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
cbuffer = new char[allocation_size];
|
|
228
|
-
std::memcpy(cbuffer, other.cbuffer, allocation_size);
|
|
229
|
-
ownership = true;
|
|
230
|
-
initialize(*other.data_len_ptr);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
void cleanup() {
|
|
235
|
-
if (ownership) {
|
|
236
|
-
delete[] cbuffer;
|
|
237
|
-
}
|
|
238
|
-
cbuffer = nullptr;
|
|
239
|
-
allocation_size = 0;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
char *cbuffer = nullptr;
|
|
243
|
-
size_t allocation_size = 0;
|
|
244
|
-
bool ownership = false;
|
|
245
|
-
int32_t *data_len_ptr = nullptr;
|
|
246
|
-
char *data_ptr = nullptr;
|
|
247
|
-
int32_t *canary1_ptr = nullptr;
|
|
248
|
-
int32_t *canary2_ptr = nullptr;
|
|
249
|
-
|
|
250
|
-
static constexpr int32_t canary_constant = static_cast<int32_t>(0xdeadbeef);
|
|
251
|
-
static constexpr size_t cobhan_header_size_bytes =
|
|
252
|
-
sizeof(int32_t) * 2; // 2x int32_t headers
|
|
253
|
-
static constexpr size_t canary_size_bytes =
|
|
254
|
-
sizeof(int32_t) * 2; // Two int32_t canaries
|
|
255
|
-
static constexpr size_t safety_padding_bytes = 8;
|
|
256
|
-
static constexpr size_t max_int32_size =
|
|
257
|
-
static_cast<size_t>(std::numeric_limits<int32_t>::max());
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
#endif // COBHAN_BUFFER_H
|
package/src/cobhan_buffer_napi.h
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
#ifndef COBHAN_BUFFER_NAPI_H
|
|
2
|
-
#define COBHAN_BUFFER_NAPI_H
|
|
3
|
-
|
|
4
|
-
#include "cobhan_buffer.h"
|
|
5
|
-
#include "napi_utils.h"
|
|
6
|
-
#include <napi.h>
|
|
7
|
-
#include <stdexcept>
|
|
8
|
-
|
|
9
|
-
class CobhanBufferNapi : public CobhanBuffer {
|
|
10
|
-
public:
|
|
11
|
-
// Constructor from a Napi::String
|
|
12
|
-
CobhanBufferNapi(const Napi::Env &env, const Napi::String &napiString)
|
|
13
|
-
: CobhanBuffer(NapiUtils::GetUtf8StringLength(env, napiString) + 1),
|
|
14
|
-
env(env) { // Add one for possible NULL delimiter due to Node
|
|
15
|
-
// string functions
|
|
16
|
-
copy_from_string(napiString);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Constructor from Napi::Buffer<unsigned char>
|
|
20
|
-
explicit CobhanBufferNapi(const Napi::Env &env,
|
|
21
|
-
const Napi::Buffer<unsigned char> &napiBuffer)
|
|
22
|
-
: CobhanBuffer(napiBuffer.ByteLength()), env(env) {
|
|
23
|
-
std::memcpy(get_data_ptr(), napiBuffer.Data(), napiBuffer.ByteLength());
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Constructor from Napi::Value
|
|
27
|
-
explicit CobhanBufferNapi(const Napi::Env &env, const Napi::Value &napiValue)
|
|
28
|
-
: CobhanBuffer(ValueToDataSize(env, napiValue)), env(env) {
|
|
29
|
-
if (napiValue.IsString()) {
|
|
30
|
-
copy_from_string(napiValue.As<Napi::String>());
|
|
31
|
-
} else if (napiValue.IsBuffer()) {
|
|
32
|
-
auto napiBuffer = napiValue.As<Napi::Buffer<unsigned char>>();
|
|
33
|
-
std::memcpy(get_data_ptr(), napiBuffer.Data(), napiBuffer.Length());
|
|
34
|
-
} else {
|
|
35
|
-
NapiUtils::ThrowException(
|
|
36
|
-
env, "Expected a Napi::String or Napi::Buffer<unsigned "
|
|
37
|
-
"char> as the value.");
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Constructor from a Napi::String to an externally allocated buffer
|
|
42
|
-
CobhanBufferNapi(const Napi::Env &env,
|
|
43
|
-
const Napi::Buffer<unsigned char> &napiBuffer, char *cbuffer,
|
|
44
|
-
size_t allocation_size)
|
|
45
|
-
: CobhanBuffer(cbuffer, allocation_size), env(env) {
|
|
46
|
-
std::memcpy(get_data_ptr(), napiBuffer.Data(), napiBuffer.Length());
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Constructor from a Napi::String to an externally allocated buffer
|
|
50
|
-
CobhanBufferNapi(const Napi::Env &env, const Napi::String &napiString,
|
|
51
|
-
char *cbuffer, size_t allocation_size)
|
|
52
|
-
: CobhanBuffer(cbuffer, allocation_size), env(env) {
|
|
53
|
-
copy_from_string(napiString);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Constructor from a Napi::String to an externally allocated buffer
|
|
57
|
-
CobhanBufferNapi(const Napi::Env &env, const Napi::Value &napiValue,
|
|
58
|
-
char *cbuffer, size_t allocation_size)
|
|
59
|
-
: CobhanBuffer(cbuffer, allocation_size), env(env) {
|
|
60
|
-
if (napiValue.IsString()) {
|
|
61
|
-
copy_from_string(napiValue.As<Napi::String>());
|
|
62
|
-
} else if (napiValue.IsBuffer()) {
|
|
63
|
-
auto napiBuffer = napiValue.As<Napi::Buffer<unsigned char>>();
|
|
64
|
-
std::memcpy(get_data_ptr(), napiBuffer.Data(), napiBuffer.Length());
|
|
65
|
-
} else {
|
|
66
|
-
NapiUtils::ThrowException(
|
|
67
|
-
env, "Expected a Napi::String or Napi::Buffer<unsigned "
|
|
68
|
-
"char> as the value.");
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Constructor from size_t representing data length in bytes (not allocation
|
|
73
|
-
// size)
|
|
74
|
-
explicit CobhanBufferNapi(const Napi::Env &env, size_t data_len_bytes)
|
|
75
|
-
: CobhanBuffer(data_len_bytes), env(env) {}
|
|
76
|
-
|
|
77
|
-
// Constructor from externally allocated char* and size_t representing
|
|
78
|
-
// allocation size in bytes
|
|
79
|
-
explicit CobhanBufferNapi(const Napi::Env &env, char *cbuffer,
|
|
80
|
-
size_t allocation_size)
|
|
81
|
-
: CobhanBuffer(cbuffer, allocation_size), env(env) {}
|
|
82
|
-
|
|
83
|
-
// Move constructor
|
|
84
|
-
CobhanBufferNapi(CobhanBufferNapi &&other) noexcept
|
|
85
|
-
: CobhanBuffer(std::move(other)), env(other.env) {}
|
|
86
|
-
|
|
87
|
-
// Move assignment operator
|
|
88
|
-
CobhanBufferNapi &operator=(CobhanBufferNapi &&other) noexcept {
|
|
89
|
-
if (this != &other) {
|
|
90
|
-
CobhanBuffer::operator=(std::move(other));
|
|
91
|
-
}
|
|
92
|
-
return *this;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Returns a Napi::String from the buffer using napi_create_string_utf8
|
|
96
|
-
[[nodiscard]] Napi::String ToString() const {
|
|
97
|
-
napi_value napiStr;
|
|
98
|
-
napi_status status = napi_create_string_utf8(
|
|
99
|
-
env, get_data_ptr(), get_data_len_bytes(), &napiStr);
|
|
100
|
-
|
|
101
|
-
if (status != napi_ok) {
|
|
102
|
-
napi_throw_error(env, nullptr,
|
|
103
|
-
"Failed to create Napi::String from CobhanBuffer");
|
|
104
|
-
return {};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return {env, napiStr};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Returns a Napi::Buffer<unsigned char> from the buffer
|
|
111
|
-
[[nodiscard]] Napi::Buffer<unsigned char> ToBuffer() const {
|
|
112
|
-
auto buffer = Napi::Buffer<unsigned char>::Copy(
|
|
113
|
-
env, reinterpret_cast<unsigned char *>(get_data_ptr()),
|
|
114
|
-
get_data_len_bytes());
|
|
115
|
-
return buffer;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Public method to calculate the required allocation size for a Napi::String
|
|
119
|
-
static size_t StringToAllocationSize(const Napi::Env &env,
|
|
120
|
-
const Napi::String &napiString) {
|
|
121
|
-
size_t str_len = NapiUtils::GetUtf8StringLength(env, napiString);
|
|
122
|
-
return DataSizeToAllocationSize(str_len) +
|
|
123
|
-
1; // Add one for possible NULL delimiter due to Node string
|
|
124
|
-
// functions
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Public method to calculate the required allocation size for a
|
|
128
|
-
// Napi::Buffer<unsigned char>
|
|
129
|
-
static size_t
|
|
130
|
-
BufferToAllocationSize(const Napi::Env &,
|
|
131
|
-
const Napi::Buffer<unsigned char> &napiBuffer) {
|
|
132
|
-
return DataSizeToAllocationSize(napiBuffer.Length());
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Public method to calculate the required allocation size for a Napi::Value
|
|
136
|
-
// (either Napi::String or Napi::Buffer<unsigned char>)
|
|
137
|
-
static size_t ValueToAllocationSize(const Napi::Env &env,
|
|
138
|
-
const Napi::Value &value) {
|
|
139
|
-
if (value.IsString()) {
|
|
140
|
-
return StringToAllocationSize(env, value.As<Napi::String>());
|
|
141
|
-
} else if (value.IsBuffer()) {
|
|
142
|
-
return BufferToAllocationSize(env,
|
|
143
|
-
value.As<Napi::Buffer<unsigned char>>());
|
|
144
|
-
} else {
|
|
145
|
-
NapiUtils::ThrowException(
|
|
146
|
-
env, "Expected a Napi::String or Napi::Buffer<unsigned "
|
|
147
|
-
"char> as the value.");
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
static size_t ValueToDataSize(const Napi::Env &env,
|
|
152
|
-
const Napi::Value &value) {
|
|
153
|
-
if (value.IsString()) {
|
|
154
|
-
return NapiUtils::GetUtf8StringLength(env, value.As<Napi::String>()) + 1;
|
|
155
|
-
} else if (value.IsBuffer()) {
|
|
156
|
-
return value.As<Napi::Buffer<unsigned char>>().ByteLength();
|
|
157
|
-
} else {
|
|
158
|
-
NapiUtils::ThrowException(
|
|
159
|
-
env, "Expected a Napi::String or Napi::Buffer<unsigned "
|
|
160
|
-
"char> as the value.");
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
private:
|
|
165
|
-
Napi::Env env;
|
|
166
|
-
|
|
167
|
-
void copy_from_string(const Napi::String &napiString) {
|
|
168
|
-
size_t str_len = NapiUtils::GetUtf8StringLength(env, napiString);
|
|
169
|
-
// Add one for NULL delimiter due to napi_get_value_string_utf8
|
|
170
|
-
size_t allocation_size =
|
|
171
|
-
CobhanBuffer::DataSizeToAllocationSize(str_len) + 1;
|
|
172
|
-
|
|
173
|
-
if (allocation_size > get_allocation_size()) {
|
|
174
|
-
NapiUtils::ThrowException(
|
|
175
|
-
env,
|
|
176
|
-
"Buffer allocation size is insufficient to hold the Napi::String.");
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Bytes written is the number of bytes copied, excluding the NULL
|
|
180
|
-
size_t bytes_written;
|
|
181
|
-
napi_status status = napi_get_value_string_utf8(
|
|
182
|
-
env, napiString, get_data_ptr(), str_len + 1, &bytes_written);
|
|
183
|
-
if (status != napi_ok || bytes_written != str_len) {
|
|
184
|
-
NapiUtils::ThrowException(
|
|
185
|
-
env, "Failed to copy Napi::String into CobhanBuffer. Status: " +
|
|
186
|
-
std::to_string(status) +
|
|
187
|
-
", Bytes Written: " + std::to_string(bytes_written));
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Update our data length to the actual string length
|
|
191
|
-
set_data_len_bytes(str_len);
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
// Specialized class for buffers containing sensitive data
|
|
196
|
-
class SensitiveCobhanBufferNapi : public CobhanBufferNapi {
|
|
197
|
-
public:
|
|
198
|
-
using CobhanBufferNapi::CobhanBufferNapi; // Inherit all constructors
|
|
199
|
-
|
|
200
|
-
// Move constructor - needed for async workers
|
|
201
|
-
SensitiveCobhanBufferNapi(SensitiveCobhanBufferNapi &&other) noexcept
|
|
202
|
-
: CobhanBufferNapi(std::move(other)) {}
|
|
203
|
-
|
|
204
|
-
// Also allow moving from base class (for async worker initialization)
|
|
205
|
-
SensitiveCobhanBufferNapi(CobhanBufferNapi &&other) noexcept
|
|
206
|
-
: CobhanBufferNapi(std::move(other)) {}
|
|
207
|
-
|
|
208
|
-
~SensitiveCobhanBufferNapi() {
|
|
209
|
-
// TODO: Fix for async operations - currently breaks async tests
|
|
210
|
-
// because data gets wiped before async operation completes
|
|
211
|
-
// Only wipe if we still own data (haven't been moved from)
|
|
212
|
-
// if (get_data_ptr() != nullptr) {
|
|
213
|
-
// secure_wipe_data();
|
|
214
|
-
// }
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
#endif // COBHAN_BUFFER_NAPI_H
|
package/src/hints.h
DELETED
package/src/logging.h
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
#pragma clang diagnostic push
|
|
2
|
-
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
|
|
3
|
-
|
|
4
|
-
#ifndef LOGGING_H
|
|
5
|
-
#define LOGGING_H
|
|
6
|
-
|
|
7
|
-
#include <cstddef> // size_t
|
|
8
|
-
#include <cstdint> // int32_t
|
|
9
|
-
#include <sstream> // std::ostringstream
|
|
10
|
-
#include <string> // std::string
|
|
11
|
-
|
|
12
|
-
class Logger {
|
|
13
|
-
public:
|
|
14
|
-
[[maybe_unused]] void set_verbose_flag(int32_t verbose) { verbose_flag = verbose != 0; };
|
|
15
|
-
|
|
16
|
-
virtual void debug_log(const char *function_name,
|
|
17
|
-
const char *message) const = 0;
|
|
18
|
-
virtual void debug_log(const char *function_name,
|
|
19
|
-
const std::string &message) const = 0;
|
|
20
|
-
virtual void debug_log_alloca(const char *function_name,
|
|
21
|
-
const char *variable_name,
|
|
22
|
-
size_t length) const = 0;
|
|
23
|
-
|
|
24
|
-
virtual void debug_log_new(const char *function_name,
|
|
25
|
-
const char *variable_name,
|
|
26
|
-
size_t length) const = 0;
|
|
27
|
-
|
|
28
|
-
virtual void error_log(const char *function_name,
|
|
29
|
-
const char *message) const = 0;
|
|
30
|
-
virtual void error_log(const char *function_name,
|
|
31
|
-
const std::string &message) const = 0;
|
|
32
|
-
|
|
33
|
-
__attribute__((always_inline)) inline static std::string
|
|
34
|
-
format_ptr(const void *ptr) {
|
|
35
|
-
std::ostringstream ss;
|
|
36
|
-
ss << "0x" << std::hex << (intptr_t)ptr;
|
|
37
|
-
return ss.str();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
protected:
|
|
41
|
-
bool verbose_flag = false;
|
|
42
|
-
std::string system_name;
|
|
43
|
-
|
|
44
|
-
explicit Logger(std::string system_name) : system_name(std::move(system_name)) {}
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
#endif // LOGGING_H
|
|
48
|
-
|
|
49
|
-
#pragma clang diagnostic pop
|