edhoc 1.2.1 → 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 CHANGED
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "target_name": "bindings",
8
8
  'defines': [
9
- 'NAPI_CPP_EXCEPTIONS=1',
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': 'YES',
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.
@@ -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
- auto exception = std::current_exception();
59
- if (exception) {
60
- promise.set_exception(exception);
61
- } else {
62
- promise.set_value(defaultValue);
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
- throw Napi::TypeError::New(value.Env(), "Input value must be a number");
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.1",
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>",
@@ -22,7 +22,7 @@
22
22
  "scripts": {
23
23
  "debug": "npx node-gyp build --debug",
24
24
  "install": "node-gyp-build",
25
- "postinstall": "patch-package",
25
+ "prepare": "patch-package",
26
26
  "lint": "eslint .",
27
27
  "prebuildify": "prebuildify --napi --target 17.0.0 --force --strip --verbose",
28
28
  "prebuildify-cross": "prebuildify-cross --napi --target 17.0.0 --force --strip --verbose",
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
- try {
20
- composedMessage.resize(kInitialBufferSize);
21
- size_t composedMessageLength = 0;
19
+ composedMessage.resize(kInitialBufferSize);
20
+ size_t composedMessageLength = 0;
22
21
 
23
- int ret = EDHOC_ERROR_GENERIC_ERROR;
24
- switch (messageNumber) {
25
- case EDHOC_MSG_1:
26
- ret = edhoc_message_1_compose(&context, composedMessage.data(), composedMessage.size(), &composedMessageLength);
27
- break;
28
- case EDHOC_MSG_2:
29
- ret = edhoc_message_2_compose(&context, composedMessage.data(), composedMessage.size(), &composedMessageLength);
30
- break;
31
- case EDHOC_MSG_3:
32
- ret = edhoc_message_3_compose(&context, composedMessage.data(), composedMessage.size(), &composedMessageLength);
33
- break;
34
- case EDHOC_MSG_4:
35
- ret = edhoc_message_4_compose(&context, composedMessage.data(), composedMessage.size(), &composedMessageLength);
36
- break;
37
- default:
38
- SetError(kErrorInvalidMessageNumber);
39
- return;
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
- if (ret != EDHOC_SUCCESS) {
45
- char errorMessage[kErrorBufferSize];
46
- std::snprintf(errorMessage, kErrorBufferSize, kErrorMessageFormat, messageNumber + 1, ret);
47
- SetError(errorMessage);
48
- }
41
+ composedMessage.resize(composedMessageLength);
49
42
 
50
- } catch (const std::exception& e) {
51
- SetError(e.what());
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
- deferred.Resolve(Napi::Buffer<uint8_t>::Copy(env, composedMessage.data(), composedMessage.size()));
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
- deferred.Reject(error.Value());
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
- throw std::runtime_error(kInvalidInputDataErrorKid);
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
- throw std::runtime_error(kInvalidInputDataErrorKid);
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
- throw std::runtime_error(kInvalidInputDataErrorX509Chain);
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
- throw std::runtime_error(kInvalidInputDataErrorX509Hash);
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
- auto successHandler = [this, &promise, &credentials](Napi::Env env, Napi::Value result) {
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
- throw std::runtime_error(kInvalidInputCredentialTypeError);
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
- throw std::runtime_error(kUnsupportedCredentialTypeError);
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, &user_context, &successHandler, &promise](Napi::Env env,
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 = {static_cast<const UserContext*>(user_context)->parent.Value()};
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
- auto successHandler = [this, &promise, &credentials, &public_key_reference, &public_key_length](Napi::Env env,
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
- throw std::runtime_error(kInvalidInputCredentialTypeError);
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
- throw std::runtime_error(kUnsupportedCredentialTypeError);
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, &user_context, &credentials, &successHandler, &promise](Napi::Env env,
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
- throw std::runtime_error(kUnsupportedCredentialTypeError);
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 = {static_cast<const UserContext*>(user_context)->parent.Value(), resultObject};
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
  };