Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 50 additions & 19 deletions src/asherah.cc
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,16 @@ class Asherah : public Napi::Addon<Asherah> {
try {
Napi::String partition_id_string;
Napi::Value input_value;
size_t partition_id_length;

BeginEncryptToJson(env, __func__, info, partition_id_string, input_value);
BeginEncryptToJson(env, __func__, info, partition_id_string, input_value,
partition_id_length);

#ifdef USE_SCOPED_ALLOCATE_BUFFER
char *partition_id_cbuffer;
size_t partition_id_cbuffer_size =
CobhanBufferNapi::StringToAllocationSize(env, partition_id_string);
CobhanBufferNapi::StringToAllocationSize(env, partition_id_string,
partition_id_length);
SCOPED_ALLOCATE_BUFFER(partition_id_cbuffer, partition_id_cbuffer_size,
maximum_stack_alloc_size, __func__);

Expand All @@ -177,7 +180,8 @@ class Asherah : public Napi::Addon<Asherah> {
CobhanBufferNapi input(env, input_value, input_cbuffer,
input_cbuffer_size);
#else
CobhanBufferNapi partition_id(env, partition_id_string);
CobhanBufferNapi partition_id(env, partition_id_string,
partition_id_length);
CobhanBufferNapi input(env, input_value);
#endif

Expand Down Expand Up @@ -218,9 +222,12 @@ class Asherah : public Napi::Addon<Asherah> {
try {
Napi::String partition_id_string;
Napi::Value input_value;
BeginEncryptToJson(env, __func__, info, partition_id_string, input_value);
size_t partition_id_length;
BeginEncryptToJson(env, __func__, info, partition_id_string, input_value,
partition_id_length);

CobhanBufferNapi partition_id(env, partition_id_string);
CobhanBufferNapi partition_id(env, partition_id_string,
partition_id_length);
CobhanBufferNapi input(env, input_value);

size_t partition_id_data_len_bytes = partition_id.get_data_len_bytes();
Expand Down Expand Up @@ -250,14 +257,16 @@ class Asherah : public Napi::Addon<Asherah> {
try {
Napi::String partition_id_string;
Napi::Value input_value;
size_t partition_id_length;

BeginDecryptFromJson(env, __func__, info, partition_id_string,
input_value);
input_value, partition_id_length);

#ifdef USE_SCOPED_ALLOCATE_BUFFER
char *partition_id_cbuffer;
size_t partition_id_cbuffer_size =
CobhanBufferNapi::StringToAllocationSize(env, partition_id_string);
CobhanBufferNapi::StringToAllocationSize(env, partition_id_string,
partition_id_length);
SCOPED_ALLOCATE_BUFFER(partition_id_cbuffer, partition_id_cbuffer_size,
maximum_stack_alloc_size, __func__);

Expand All @@ -280,7 +289,8 @@ class Asherah : public Napi::Addon<Asherah> {
maximum_stack_alloc_size, __func__);
CobhanBufferNapi output(env, output_cobhan_buffer, output_size_bytes);
#else
CobhanBufferNapi partition_id(env, partition_id_string);
CobhanBufferNapi partition_id(env, partition_id_string,
partition_id_length);
CobhanBufferNapi input(env, input_value);
CobhanBufferNapi output(env, input.get_data_len_bytes());
#endif
Expand Down Expand Up @@ -309,10 +319,12 @@ class Asherah : public Napi::Addon<Asherah> {
try {
Napi::String partition_id_string;
Napi::Value input_value;
size_t partition_id_length;
BeginDecryptFromJson(env, __func__, info, partition_id_string,
input_value);
input_value, partition_id_length);

CobhanBufferNapi partition_id(env, partition_id_string);
CobhanBufferNapi partition_id(env, partition_id_string,
partition_id_length);
CobhanBufferNapi input(env, input_value);

CobhanBufferNapi output(env, input.get_data_len_bytes());
Expand All @@ -338,13 +350,15 @@ class Asherah : public Napi::Addon<Asherah> {

Napi::String partition_id_string;
Napi::Value input_value;
size_t partition_id_length;
BeginDecryptFromJson(env, __func__, info, partition_id_string,
input_value);
input_value, partition_id_length);

#ifdef USE_SCOPED_ALLOCATE_BUFFER
char *partition_id_cbuffer;
size_t partition_id_cbuffer_size =
CobhanBufferNapi::StringToAllocationSize(env, partition_id_string);
CobhanBufferNapi::StringToAllocationSize(env, partition_id_string,
partition_id_length);
SCOPED_ALLOCATE_BUFFER(partition_id_cbuffer, partition_id_cbuffer_size,
maximum_stack_alloc_size, __func__);

Expand All @@ -362,7 +376,8 @@ class Asherah : public Napi::Addon<Asherah> {

CobhanBufferNapi output(env, input.get_data_len_bytes());
#else
CobhanBufferNapi partition_id(env, partition_id_string);
CobhanBufferNapi partition_id(env, partition_id_string,
partition_id_length);
CobhanBufferNapi input(env, input_value);
CobhanBufferNapi output(env, input.get_data_len_bytes());
#endif
Expand All @@ -388,10 +403,12 @@ class Asherah : public Napi::Addon<Asherah> {

Napi::String partition_id_string;
Napi::Value input_value;
size_t partition_id_length;
BeginDecryptFromJson(env, __func__, info, partition_id_string,
input_value);
input_value, partition_id_length);

CobhanBufferNapi partition_id(env, partition_id_string);
CobhanBufferNapi partition_id(env, partition_id_string,
partition_id_length);
CobhanBufferNapi input(env, input_value);

CobhanBufferNapi output(env, input.get_data_len_bytes());
Expand Down Expand Up @@ -549,13 +566,20 @@ class Asherah : public Napi::Addon<Asherah> {

void BeginEncryptToJson(const Napi::Env &env, const char *func_name,
const Napi::CallbackInfo &info,
Napi::String &partition_id, Napi::Value &input) {
Napi::String &partition_id, Napi::Value &input,
size_t &partition_id_length) {
RequireAsherahSetup(env, func_name);

NapiUtils::RequireParameterCount(info, 2);

partition_id = NapiUtils::RequireParameterString(env, func_name, info[0]);
partition_id = NapiUtils::RequireParameterStringWithLength(
env, func_name, info[0], partition_id_length);
input = NapiUtils::RequireParameterStringOrBuffer(env, func_name, info[1]);

if (partition_id_length == 0) {
NapiUtils::ThrowException(env, std::string(func_name) +
": Partition ID cannot be empty");
}
}

void EndEncryptToJson(Napi::Env env, CobhanBufferNapi &output, GoInt32 result,
Expand All @@ -575,13 +599,20 @@ class Asherah : public Napi::Addon<Asherah> {

void BeginDecryptFromJson(const Napi::Env &env, const char *func_name,
const Napi::CallbackInfo &info,
Napi::String &partition_id, Napi::Value &input) {
Napi::String &partition_id, Napi::Value &input,
size_t &partition_id_length) {
RequireAsherahSetup(env, func_name);

NapiUtils::RequireParameterCount(info, 2);

partition_id = NapiUtils::RequireParameterString(env, func_name, info[0]);
partition_id = NapiUtils::RequireParameterStringWithLength(
env, func_name, info[0], partition_id_length);
input = NapiUtils::RequireParameterStringOrBuffer(env, func_name, info[1]);

if (partition_id_length == 0) {
NapiUtils::ThrowException(env, std::string(func_name) +
": Partition ID cannot be empty");
}
}

void EndDecryptFromJson(Napi::Env &env, CobhanBufferNapi &output,
Expand Down
15 changes: 11 additions & 4 deletions src/cobhan_buffer_napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
class CobhanBufferNapi : public CobhanBuffer {
public:
// Constructor from a Napi::String
CobhanBufferNapi(const Napi::Env &env, const Napi::String &napiString)
: CobhanBuffer(NapiUtils::GetUtf8StringLength(env, napiString) + 1),
CobhanBufferNapi(const Napi::Env &env, const Napi::String &napiString,
int64_t utf8_length = -1)
: CobhanBuffer((utf8_length >= 0
? static_cast<size_t>(utf8_length)
: NapiUtils::GetUtf8StringLength(env, napiString)) +
1),
env(env) { // Add one for possible NULL delimiter due to Node
// string functions
copy_from_string(napiString);
Expand Down Expand Up @@ -117,8 +121,11 @@ class CobhanBufferNapi : public CobhanBuffer {

// Public method to calculate the required allocation size for a Napi::String
static size_t StringToAllocationSize(const Napi::Env &env,
const Napi::String &napiString) {
size_t str_len = NapiUtils::GetUtf8StringLength(env, napiString);
const Napi::String &napiString,
int64_t utf8_length = -1) {
size_t str_len = (utf8_length >= 0)
? static_cast<size_t>(utf8_length)
: NapiUtils::GetUtf8StringLength(env, napiString);
return DataSizeToAllocationSize(str_len) +
1; // Add one for possible NULL delimiter due to Node string
// functions
Expand Down
10 changes: 10 additions & 0 deletions src/napi_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ class NapiUtils {
}
}

// Version that also returns the UTF-8 length to avoid redundant calls
static Napi::String RequireParameterStringWithLength(const Napi::Env &env,
const char *func_name,
Napi::Value value,
size_t &utf8_length) {
Napi::String str = RequireParameterString(env, func_name, value);
utf8_length = GetUtf8StringLength(env, str);
return str;
}

__attribute__((unused)) static Napi::Buffer<unsigned char>
RequireParameterBuffer(const Napi::Env &env, const char *func_name,
Napi::Value value) {
Expand Down
60 changes: 60 additions & 0 deletions test/asherah.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,22 @@ describe('Asherah', function () {
await bad_encrypt_buffers_empty_async(test_verbose, true, default_max_stack_alloc_item_size);
});

it('Bad Empty Partition ID Encrypt Sync', async function () {
await bad_empty_partition_id_encrypt_sync(test_verbose, true, default_max_stack_alloc_item_size);
});

it('Bad Empty Partition ID Encrypt Async', async function () {
await bad_empty_partition_id_encrypt_async(test_verbose, true, default_max_stack_alloc_item_size);
});

it('Bad Empty Partition ID Decrypt Sync', async function () {
await bad_empty_partition_id_decrypt_sync(test_verbose, true, default_max_stack_alloc_item_size);
});

it('Bad Empty Partition ID Decrypt Async', async function () {
await bad_empty_partition_id_decrypt_async(test_verbose, true, default_max_stack_alloc_item_size);
});

// Test using heap only
register_sync_roundtrip_tests(simple_secret, test_verbose, false, force_use_heap);
register_sync_roundtrip_tests(simple_secret, test_verbose, true, force_use_heap);
Expand Down Expand Up @@ -479,6 +495,50 @@ async function bad_encrypt_buffers_empty_async(verbose: boolean, session_cache:
}
}

async function bad_empty_partition_id_encrypt_sync(verbose: boolean, session_cache: boolean, max_stack_alloc_item_size: number): Promise<void> {
await asherah_setup_static_memory_async(verbose, session_cache, max_stack_alloc_item_size);
try {
assert.throws(() => {
encrypt_string('', 'test data');
}, Error);
} finally {
await asherah_shutdown_async();
}
}

async function bad_empty_partition_id_encrypt_async(verbose: boolean, session_cache: boolean, max_stack_alloc_item_size: number): Promise<void> {
await asherah_setup_static_memory_async(verbose, session_cache, max_stack_alloc_item_size);
try {
await assert_throws_async(async () => {
await encrypt_string_async('', 'test data');
}, 'Should throw error if partition ID is empty');
} finally {
await asherah_shutdown_async();
}
}

async function bad_empty_partition_id_decrypt_sync(verbose: boolean, session_cache: boolean, max_stack_alloc_item_size: number): Promise<void> {
await asherah_setup_static_memory_async(verbose, session_cache, max_stack_alloc_item_size);
try {
assert.throws(() => {
decrypt_string('', 'some-encrypted-data');
}, Error);
} finally {
await asherah_shutdown_async();
}
}

async function bad_empty_partition_id_decrypt_async(verbose: boolean, session_cache: boolean, max_stack_alloc_item_size: number): Promise<void> {
await asherah_setup_static_memory_async(verbose, session_cache, max_stack_alloc_item_size);
try {
await assert_throws_async(async () => {
await decrypt_string_async('', 'some-encrypted-data');
}, 'Should throw error if partition ID is empty');
} finally {
await asherah_shutdown_async();
}
}

function get_test_name(prefix: string, verbose: boolean, session_cache: boolean, max_stack_alloc_item_size: number): string {
return prefix + ' (' + (max_stack_alloc_item_size == 0 ? 'heap' : 'stack ' + max_stack_alloc_item_size) + ') Cache: ' + session_cache + ' Verbose: ' + verbose;
}
Loading