edhoc 1.2.2 → 1.2.3
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 +2 -2
- package/include/EdhocCredentialManager.h +1 -1
- package/include/UserContext.h +1 -0
- package/include/Utils.h +10 -9
- package/package.json +1 -1
- package/prebuilds/android-arm/edhoc.armv7.node +0 -0
- package/prebuilds/android-arm64/edhoc.armv8.node +0 -0
- package/prebuilds/darwin-arm64/edhoc.node +0 -0
- package/prebuilds/darwin-x64/edhoc.node +0 -0
- package/prebuilds/linux-arm/edhoc.armv6.node +0 -0
- package/prebuilds/linux-arm/edhoc.armv7.node +0 -0
- package/prebuilds/linux-arm64/edhoc.armv8.node +0 -0
- package/prebuilds/linux-x64/edhoc.glibc.node +0 -0
- package/prebuilds/linux-x64/edhoc.musl.node +0 -0
- package/prebuilds/win32-ia32/edhoc.node +0 -0
- package/prebuilds/win32-x64/edhoc.node +0 -0
- package/src/EdhocComposeAsyncWorker.cpp +39 -32
- package/src/EdhocCredentialManager.cpp +33 -17
- package/src/EdhocCryptoManager.cpp +118 -73
- package/src/EdhocEadManager.cpp +2 -2
- package/src/EdhocExportOscoreAsyncWorker.cpp +24 -18
- package/src/EdhocKeyExporterAsyncWorker.cpp +19 -11
- package/src/EdhocKeyUpdateAsyncWorker.cpp +18 -10
- package/src/EdhocProcessAsyncWorker.cpp +75 -68
- package/src/LibEDHOC.cpp +24 -14
- package/src/Utils.cpp +8 -13
- package/test/errors.test.ts +129 -0
package/binding.gyp
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
{
|
|
7
7
|
"target_name": "bindings",
|
|
8
8
|
'defines': [
|
|
9
|
-
'
|
|
9
|
+
'NAPI_DISABLE_CPP_EXCEPTIONS=1',
|
|
10
10
|
'CONFIG_LIBEDHOC_ENABLE=1',
|
|
11
11
|
'CONFIG_LIBEDHOC_MAX_NR_OF_CIPHER_SUITES=9',
|
|
12
12
|
'CONFIG_LIBEDHOC_MAX_LEN_OF_CONN_ID=7',
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
'cflags!': [ '-fno-exceptions', '-std=c99' ],
|
|
39
39
|
'cflags_cc!': [ '-fno-exceptions', '-std=c++20' ],
|
|
40
40
|
'xcode_settings': {
|
|
41
|
-
'GCC_ENABLE_CPP_EXCEPTIONS': '
|
|
41
|
+
'GCC_ENABLE_CPP_EXCEPTIONS': 'NO',
|
|
42
42
|
'CLANG_CXX_LIBRARY': 'libc++',
|
|
43
43
|
'CLANG_CXX_LANGUAGE_STANDARD': 'c++20',
|
|
44
44
|
'MACOSX_DEPLOYMENT_TARGET': '12'
|
|
@@ -93,7 +93,7 @@ class EdhocCredentialManager {
|
|
|
93
93
|
Napi::ObjectReference credentialManagerRef; ///< Reference to the JS object
|
|
94
94
|
Napi::ThreadSafeFunction fetchTsfn; ///< Thread-safe function for FetchCredentials
|
|
95
95
|
Napi::ThreadSafeFunction verifyTsfn; ///< Thread-safe function for VerifyCredentials
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
/**
|
|
98
98
|
* @brief Assosciates the thread-safe function with the JS object function.
|
|
99
99
|
* @param name The name of the function in the JS credential manager object.
|
package/include/UserContext.h
CHANGED
|
@@ -67,6 +67,7 @@ class UserContext {
|
|
|
67
67
|
|
|
68
68
|
Napi::ThreadSafeFunction logger; ///< The logger for the UserContext
|
|
69
69
|
Napi::ObjectReference parent; ///< The parent object reference for the UserContext
|
|
70
|
+
Napi::Error error; ///< The last error for the UserContext
|
|
70
71
|
|
|
71
72
|
protected:
|
|
72
73
|
std::shared_ptr<EdhocCryptoManager> cryptoManager; ///< The crypto manager
|
package/include/Utils.h
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
#include <cstdint>
|
|
7
7
|
#include <future>
|
|
8
|
+
#include <iostream>
|
|
8
9
|
#include <string>
|
|
9
10
|
#include <vector>
|
|
10
|
-
|
|
11
11
|
extern "C" {
|
|
12
12
|
#include "edhoc.h"
|
|
13
13
|
}
|
|
@@ -53,14 +53,15 @@ class Utils {
|
|
|
53
53
|
* @return A lambda function that sets the exception on the promise.
|
|
54
54
|
*/
|
|
55
55
|
template <typename T>
|
|
56
|
-
static ErrorHandler CreatePromiseErrorHandler(std::promise<T>& promise, T defaultValue) {
|
|
57
|
-
return [&promise, defaultValue](Napi::Env env, Napi::Error error) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
static ErrorHandler CreatePromiseErrorHandler(std::promise<T>& promise, T defaultValue, Napi::Error& lastError) {
|
|
57
|
+
return [&promise, defaultValue, &lastError](Napi::Env env, Napi::Error error) {
|
|
58
|
+
if (!error.IsEmpty()) {
|
|
59
|
+
error.ThrowAsJavaScriptException();
|
|
60
|
+
}
|
|
61
|
+
if (env.IsExceptionPending()) {
|
|
62
|
+
lastError = env.GetAndClearPendingException();
|
|
63
63
|
}
|
|
64
|
+
promise.set_value(defaultValue);
|
|
64
65
|
};
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -94,7 +95,7 @@ class Utils {
|
|
|
94
95
|
template <typename EnumType>
|
|
95
96
|
static EnumType ConvertToEnum(const Napi::Value& value) {
|
|
96
97
|
if (!value.IsNumber()) {
|
|
97
|
-
|
|
98
|
+
Napi::TypeError::New(value.Env(), "Input value must be a number").ThrowAsJavaScriptException();
|
|
98
99
|
}
|
|
99
100
|
return static_cast<EnumType>(value.As<Napi::Number>().Int32Value());
|
|
100
101
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "edhoc",
|
|
3
3
|
"description": "A Node.js implementation of EDHOC (Ephemeral Diffie-Hellman Over COSE) protocol for lightweight authenticated key exchange in IoT and other constrained environments.",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.3",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"author": "Marek Serafin <marek@serafin.email>",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -16,54 +16,61 @@ EdhocComposeAsyncWorker::EdhocComposeAsyncWorker(Napi::Env& env,
|
|
|
16
16
|
callback(std::move(callback)) {}
|
|
17
17
|
|
|
18
18
|
void EdhocComposeAsyncWorker::Execute() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
size_t composedMessageLength = 0;
|
|
19
|
+
composedMessage.resize(kInitialBufferSize);
|
|
20
|
+
size_t composedMessageLength = 0;
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
composedMessage.resize(composedMessageLength);
|
|
22
|
+
int ret = EDHOC_ERROR_GENERIC_ERROR;
|
|
23
|
+
switch (messageNumber) {
|
|
24
|
+
case EDHOC_MSG_1:
|
|
25
|
+
ret = edhoc_message_1_compose(&context, composedMessage.data(), composedMessage.size(), &composedMessageLength);
|
|
26
|
+
break;
|
|
27
|
+
case EDHOC_MSG_2:
|
|
28
|
+
ret = edhoc_message_2_compose(&context, composedMessage.data(), composedMessage.size(), &composedMessageLength);
|
|
29
|
+
break;
|
|
30
|
+
case EDHOC_MSG_3:
|
|
31
|
+
ret = edhoc_message_3_compose(&context, composedMessage.data(), composedMessage.size(), &composedMessageLength);
|
|
32
|
+
break;
|
|
33
|
+
case EDHOC_MSG_4:
|
|
34
|
+
ret = edhoc_message_4_compose(&context, composedMessage.data(), composedMessage.size(), &composedMessageLength);
|
|
35
|
+
break;
|
|
36
|
+
default:
|
|
37
|
+
SetError(kErrorInvalidMessageNumber);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
43
40
|
|
|
44
|
-
|
|
45
|
-
char errorMessage[kErrorBufferSize];
|
|
46
|
-
std::snprintf(errorMessage, kErrorBufferSize, kErrorMessageFormat, messageNumber + 1, ret);
|
|
47
|
-
SetError(errorMessage);
|
|
48
|
-
}
|
|
41
|
+
composedMessage.resize(composedMessageLength);
|
|
49
42
|
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
if (ret != EDHOC_SUCCESS) {
|
|
44
|
+
char errorMessage[kErrorBufferSize];
|
|
45
|
+
std::snprintf(errorMessage, kErrorBufferSize, kErrorMessageFormat, messageNumber + 1, ret);
|
|
46
|
+
SetError(errorMessage);
|
|
52
47
|
}
|
|
53
48
|
}
|
|
54
49
|
|
|
55
50
|
void EdhocComposeAsyncWorker::OnOK() {
|
|
56
51
|
Napi::Env env = Env();
|
|
57
52
|
Napi::HandleScope scope(env);
|
|
58
|
-
|
|
53
|
+
|
|
59
54
|
callback(env);
|
|
55
|
+
|
|
56
|
+
if (env.IsExceptionPending()) {
|
|
57
|
+
deferred.Reject(env.GetAndClearPendingException().Value());
|
|
58
|
+
} else {
|
|
59
|
+
deferred.Resolve(Napi::Buffer<uint8_t>::Copy(env, composedMessage.data(), composedMessage.size()));
|
|
60
|
+
}
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
void EdhocComposeAsyncWorker::OnError(const Napi::Error& error) {
|
|
63
64
|
Napi::Env env = Env();
|
|
64
65
|
Napi::HandleScope scope(env);
|
|
65
|
-
|
|
66
|
+
|
|
66
67
|
callback(env);
|
|
68
|
+
|
|
69
|
+
if (env.IsExceptionPending()) {
|
|
70
|
+
deferred.Reject(env.GetAndClearPendingException().Value());
|
|
71
|
+
} else {
|
|
72
|
+
deferred.Reject(error.Value());
|
|
73
|
+
}
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
Napi::Promise EdhocComposeAsyncWorker::GetPromise() {
|
|
@@ -36,7 +36,7 @@ static constexpr const char* kVerify = "verify";
|
|
|
36
36
|
void convert_js_to_edhoc_kid(const Napi::Object& jsObject, struct edhoc_auth_creds* credentials) {
|
|
37
37
|
Napi::Object kidObj = jsObject.Get(kKid).As<Napi::Object>();
|
|
38
38
|
if (!kidObj.Has(kIsCBOR) || !kidObj.Has(kKid) || !kidObj.Has(kCredentials)) {
|
|
39
|
-
|
|
39
|
+
Napi::TypeError::New(jsObject.Env(), kInvalidInputDataErrorKid).ThrowAsJavaScriptException();
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
credentials->label = EDHOC_COSE_HEADER_KID;
|
|
@@ -58,7 +58,7 @@ void convert_js_to_edhoc_kid(const Napi::Object& jsObject, struct edhoc_auth_cre
|
|
|
58
58
|
credentials->key_id.key_id_bstr_length = buffer.Length();
|
|
59
59
|
memcpy(credentials->key_id.key_id_bstr, buffer.Data(), buffer.Length());
|
|
60
60
|
} else {
|
|
61
|
-
|
|
61
|
+
Napi::TypeError::New(jsObject.Env(), kInvalidInputDataErrorKid).ThrowAsJavaScriptException();
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
Napi::Buffer<uint8_t> credBuffer = kidObj.Get(kCredentials).As<Napi::Buffer<uint8_t>>();
|
|
@@ -73,7 +73,7 @@ void convert_js_to_edhoc_kid(const Napi::Object& jsObject, struct edhoc_auth_cre
|
|
|
73
73
|
void convert_js_to_edhoc_x5chain(const Napi::Object& jsObject, struct edhoc_auth_creds* credentials) {
|
|
74
74
|
Napi::Object x5chainObj = jsObject.Get(kX5chain).As<Napi::Object>();
|
|
75
75
|
if (!x5chainObj.Has(kCertificates)) {
|
|
76
|
-
|
|
76
|
+
Napi::TypeError::New(jsObject.Env(), kInvalidInputDataErrorX509Chain).ThrowAsJavaScriptException();
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
credentials->label = EDHOC_COSE_HEADER_X509_CHAIN;
|
|
@@ -95,7 +95,7 @@ void convert_js_to_edhoc_x5chain(const Napi::Object& jsObject, struct edhoc_auth
|
|
|
95
95
|
void convert_js_to_edhoc_x5t(const Napi::Object& jsObject, struct edhoc_auth_creds* credentials) {
|
|
96
96
|
Napi::Object x5tObj = jsObject.Get(kX5t).As<Napi::Object>();
|
|
97
97
|
if (!x5tObj.Has(kCertificate) || !x5tObj.Has(kHash) || !x5tObj.Has(kHashAlgorithm)) {
|
|
98
|
-
|
|
98
|
+
Napi::TypeError::New(jsObject.Env(), kInvalidInputDataErrorX509Hash).ThrowAsJavaScriptException();
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
credentials->label = EDHOC_COSE_HEADER_X509_HASH;
|
|
@@ -212,13 +212,15 @@ int EdhocCredentialManager::callFetchCredentials(const void* user_context, struc
|
|
|
212
212
|
std::promise<int> promise;
|
|
213
213
|
std::future<int> future = promise.get_future();
|
|
214
214
|
|
|
215
|
-
|
|
215
|
+
UserContext* context = static_cast<UserContext*>(const_cast<void*>(user_context));
|
|
216
|
+
auto successHandler = [this, &promise, &credentials, &context](Napi::Env env, Napi::Value result) {
|
|
216
217
|
Napi::HandleScope scope(env);
|
|
217
218
|
auto credsObj = result.As<Napi::Object>();
|
|
218
219
|
credentialReferences.push_back(Napi::Persistent(credsObj));
|
|
219
220
|
|
|
220
221
|
if (credsObj.IsObject() == false || credsObj.Has(kFormat) == false) {
|
|
221
|
-
|
|
222
|
+
context->error = Napi::Error::New(env, kInvalidInputCredentialTypeError);
|
|
223
|
+
return promise.set_value(EDHOC_ERROR_GENERIC_ERROR);
|
|
222
224
|
}
|
|
223
225
|
int label = credsObj.Get(kFormat).As<Napi::Number>().Int32Value();
|
|
224
226
|
|
|
@@ -234,22 +236,27 @@ int EdhocCredentialManager::callFetchCredentials(const void* user_context, struc
|
|
|
234
236
|
break;
|
|
235
237
|
case EDHOC_COSE_ANY:
|
|
236
238
|
default:
|
|
237
|
-
|
|
239
|
+
context->error = Napi::Error::New(env, kUnsupportedCredentialTypeError);
|
|
240
|
+
return promise.set_value(EDHOC_ERROR_GENERIC_ERROR);
|
|
238
241
|
}
|
|
239
242
|
|
|
240
243
|
if (credsObj.Has(kPrivateKeyId) && !credsObj.Get(kPrivateKeyId).IsNull()) {
|
|
241
244
|
Napi::Buffer<uint8_t> privKeyIdBuffer = credsObj.Get(kPrivateKeyId).As<Napi::Buffer<uint8_t>>();
|
|
242
245
|
memcpy(credentials->priv_key_id, privKeyIdBuffer.Data(), privKeyIdBuffer.Length());
|
|
243
246
|
}
|
|
247
|
+
else {
|
|
248
|
+
context->error = Napi::Error::New(env, kInvalidInputCredentialTypeError);
|
|
249
|
+
return promise.set_value(EDHOC_ERROR_GENERIC_ERROR);
|
|
250
|
+
}
|
|
244
251
|
|
|
245
252
|
promise.set_value(EDHOC_SUCCESS);
|
|
246
253
|
};
|
|
247
254
|
|
|
248
|
-
auto blockingCallHandler = [this, &
|
|
255
|
+
auto blockingCallHandler = [this, &context, &successHandler, &promise](Napi::Env env,
|
|
249
256
|
Napi::Function jsCallback) {
|
|
250
257
|
Napi::HandleScope scope(env);
|
|
251
|
-
std::vector<napi_value> arguments = {
|
|
252
|
-
auto errorHandler = Utils::CreatePromiseErrorHandler<int>(promise, EDHOC_ERROR_GENERIC_ERROR);
|
|
258
|
+
std::vector<napi_value> arguments = {context->parent.Value()};
|
|
259
|
+
auto errorHandler = Utils::CreatePromiseErrorHandler<int>(promise, EDHOC_ERROR_GENERIC_ERROR, context->error);
|
|
253
260
|
Utils::InvokeJSFunctionWithPromiseHandling(env, credentialManagerRef.Value(), jsCallback, arguments, successHandler,
|
|
254
261
|
errorHandler);
|
|
255
262
|
};
|
|
@@ -267,13 +274,16 @@ int EdhocCredentialManager::callVerifyCredentials(const void* user_context,
|
|
|
267
274
|
std::promise<int> promise;
|
|
268
275
|
std::future<int> future = promise.get_future();
|
|
269
276
|
|
|
270
|
-
|
|
277
|
+
UserContext* context = static_cast<UserContext*>(const_cast<void*>(user_context));
|
|
278
|
+
|
|
279
|
+
auto successHandler = [this, &promise, &credentials, &public_key_reference, &public_key_length, &context](Napi::Env env,
|
|
271
280
|
Napi::Value result) {
|
|
272
281
|
Napi::HandleScope scope(env);
|
|
273
282
|
Napi::Object credsObj = result.As<Napi::Object>();
|
|
274
283
|
credentialReferences.push_back(Napi::Persistent(credsObj));
|
|
275
284
|
if (credsObj.IsObject() == false) {
|
|
276
|
-
|
|
285
|
+
context->error = Napi::Error::New(env, kInvalidInputCredentialTypeError);
|
|
286
|
+
return promise.set_value(EDHOC_ERROR_GENERIC_ERROR);
|
|
277
287
|
}
|
|
278
288
|
|
|
279
289
|
int label = credsObj.Get(kFormat).As<Napi::Number>().Int32Value();
|
|
@@ -288,7 +298,8 @@ int EdhocCredentialManager::callVerifyCredentials(const void* user_context,
|
|
|
288
298
|
convert_js_to_edhoc_x5t(credsObj, credentials);
|
|
289
299
|
break;
|
|
290
300
|
default:
|
|
291
|
-
|
|
301
|
+
context->error = Napi::Error::New(env, kUnsupportedCredentialTypeError);
|
|
302
|
+
return promise.set_value(EDHOC_ERROR_GENERIC_ERROR);
|
|
292
303
|
}
|
|
293
304
|
|
|
294
305
|
if (credsObj.Has(kPublicKey) && !credsObj.Get(kPublicKey).IsNull()) {
|
|
@@ -296,11 +307,15 @@ int EdhocCredentialManager::callVerifyCredentials(const void* user_context,
|
|
|
296
307
|
*public_key_reference = publicKeyBuffer.Data();
|
|
297
308
|
*public_key_length = publicKeyBuffer.Length();
|
|
298
309
|
}
|
|
310
|
+
else {
|
|
311
|
+
context->error = Napi::Error::New(env, kInvalidInputCredentialTypeError);
|
|
312
|
+
return promise.set_value(EDHOC_ERROR_GENERIC_ERROR);
|
|
313
|
+
}
|
|
299
314
|
|
|
300
315
|
promise.set_value(EDHOC_SUCCESS);
|
|
301
316
|
};
|
|
302
317
|
|
|
303
|
-
auto blockingCallHandler = [this, &
|
|
318
|
+
auto blockingCallHandler = [this, &context, &credentials, &successHandler, &promise](Napi::Env env,
|
|
304
319
|
Napi::Function jsCallback) {
|
|
305
320
|
Napi::HandleScope scope(env);
|
|
306
321
|
Napi::Object resultObject = Napi::Object::New(env);
|
|
@@ -317,11 +332,12 @@ int EdhocCredentialManager::callVerifyCredentials(const void* user_context,
|
|
|
317
332
|
resultObject.Set(kX5t, convert_edhoc_x5t_to_js(env, credentials->x509_hash));
|
|
318
333
|
break;
|
|
319
334
|
default:
|
|
320
|
-
|
|
335
|
+
context->error = Napi::Error::New(env, kUnsupportedCredentialTypeError);
|
|
336
|
+
return promise.set_value(EDHOC_ERROR_GENERIC_ERROR);
|
|
321
337
|
}
|
|
322
338
|
|
|
323
|
-
std::vector<napi_value> arguments = {
|
|
324
|
-
auto errorHandler = Utils::CreatePromiseErrorHandler<int>(promise, EDHOC_ERROR_GENERIC_ERROR);
|
|
339
|
+
std::vector<napi_value> arguments = {context->parent.Value(), resultObject};
|
|
340
|
+
auto errorHandler = Utils::CreatePromiseErrorHandler<int>(promise, EDHOC_ERROR_GENERIC_ERROR, context->error);
|
|
325
341
|
Utils::InvokeJSFunctionWithPromiseHandling(env, credentialManagerRef.Value(), jsCallback, arguments, successHandler,
|
|
326
342
|
errorHandler);
|
|
327
343
|
};
|