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
|
@@ -11,29 +11,37 @@ EdhocKeyUpdateAsyncWorker::EdhocKeyUpdateAsyncWorker(Napi::Env& env,
|
|
|
11
11
|
callback(std::move(callback)) {}
|
|
12
12
|
|
|
13
13
|
void EdhocKeyUpdateAsyncWorker::Execute() {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
SetError("Failed to update key.");
|
|
19
|
-
}
|
|
20
|
-
} catch (const std::exception& e) {
|
|
21
|
-
SetError(e.what());
|
|
14
|
+
int ret = edhoc_export_key_update(&context, contextBuffer.data(), contextBuffer.size());
|
|
15
|
+
|
|
16
|
+
if (ret != EDHOC_SUCCESS) {
|
|
17
|
+
SetError("Failed to update key.");
|
|
22
18
|
}
|
|
23
19
|
}
|
|
24
20
|
|
|
25
21
|
void EdhocKeyUpdateAsyncWorker::OnOK() {
|
|
26
22
|
Napi::Env env = Env();
|
|
27
23
|
Napi::HandleScope scope(env);
|
|
28
|
-
|
|
24
|
+
|
|
29
25
|
callback(env);
|
|
26
|
+
|
|
27
|
+
if (env.IsExceptionPending()) {
|
|
28
|
+
deferred.Reject(env.GetAndClearPendingException().Value());
|
|
29
|
+
} else {
|
|
30
|
+
deferred.Resolve(env.Undefined());
|
|
31
|
+
}
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
void EdhocKeyUpdateAsyncWorker::OnError(const Napi::Error& error) {
|
|
33
35
|
Napi::Env env = Env();
|
|
34
36
|
Napi::HandleScope scope(env);
|
|
35
|
-
|
|
37
|
+
|
|
36
38
|
callback(env);
|
|
39
|
+
|
|
40
|
+
if (env.IsExceptionPending()) {
|
|
41
|
+
deferred.Reject(env.GetAndClearPendingException().Value());
|
|
42
|
+
} else {
|
|
43
|
+
deferred.Reject(error.Value());
|
|
44
|
+
}
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
Napi::Promise EdhocKeyUpdateAsyncWorker::GetPromise() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include "EdhocProcessAsyncWorker.h"
|
|
2
2
|
|
|
3
|
+
#include <iostream>
|
|
3
4
|
static constexpr const char* kErrorInvalidMessageNumber = "Invalid message number";
|
|
4
5
|
static constexpr const char* kErrorMessageFormat = "Failed to process EDHOC message %d. Error code: %d";
|
|
5
6
|
static constexpr const char* kErrorWrongSelectedCipherSuiteFormat =
|
|
@@ -20,81 +21,76 @@ EdhocProcessAsyncWorker::EdhocProcessAsyncWorker(Napi::Env& env,
|
|
|
20
21
|
peerCipherSuites() {}
|
|
21
22
|
|
|
22
23
|
void EdhocProcessAsyncWorker::Execute() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
24
|
+
uint8_t* message = messageBuffer.data();
|
|
25
|
+
size_t message_length = messageBuffer.size();
|
|
26
|
+
|
|
27
|
+
int ret = EDHOC_ERROR_GENERIC_ERROR;
|
|
28
|
+
switch (messageNumber) {
|
|
29
|
+
case EDHOC_MSG_1:
|
|
30
|
+
ret = edhoc_message_1_process(&context, message, message_length);
|
|
31
|
+
break;
|
|
32
|
+
case EDHOC_MSG_2:
|
|
33
|
+
ret = edhoc_message_2_process(&context, message, message_length);
|
|
34
|
+
break;
|
|
35
|
+
case EDHOC_MSG_3:
|
|
36
|
+
ret = edhoc_message_3_process(&context, message, message_length);
|
|
37
|
+
break;
|
|
38
|
+
case EDHOC_MSG_4:
|
|
39
|
+
ret = edhoc_message_4_process(&context, message, message_length);
|
|
40
|
+
break;
|
|
41
|
+
default:
|
|
42
|
+
SetError(kErrorInvalidMessageNumber);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
46
|
+
if (ret != EDHOC_SUCCESS) {
|
|
47
|
+
enum edhoc_error_code error_code = EDHOC_ERROR_CODE_SUCCESS;
|
|
48
|
+
ret = edhoc_error_get_code(&context, &error_code);
|
|
49
|
+
switch (error_code) {
|
|
50
|
+
case EDHOC_ERROR_CODE_WRONG_SELECTED_CIPHER_SUITE: {
|
|
51
|
+
size_t csuites_len = 0;
|
|
52
|
+
int32_t csuites[10] = {0};
|
|
53
|
+
size_t peer_csuites_len = 0;
|
|
54
|
+
int32_t peer_csuites[10] = {0};
|
|
55
|
+
|
|
56
|
+
ret = edhoc_error_get_cipher_suites(&context, csuites, ARRAY_SIZE(csuites), &csuites_len, peer_csuites,
|
|
57
|
+
ARRAY_SIZE(peer_csuites), &peer_csuites_len);
|
|
58
|
+
if (ret == EDHOC_SUCCESS) {
|
|
59
|
+
std::string suites_str = "[";
|
|
60
|
+
for (size_t i = 0; i < csuites_len; i++) {
|
|
61
|
+
suites_str += std::to_string(csuites[i]);
|
|
62
|
+
if (i < csuites_len - 1) {
|
|
63
|
+
suites_str += ", ";
|
|
65
64
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
65
|
+
}
|
|
66
|
+
suites_str += "*]";
|
|
67
|
+
|
|
68
|
+
std::string peer_suites_str = "[";
|
|
69
|
+
for (size_t i = 0; i < peer_csuites_len; i++) {
|
|
70
|
+
peer_suites_str += std::to_string(peer_csuites[i]);
|
|
71
|
+
if (i < peer_csuites_len - 1) {
|
|
72
|
+
peer_suites_str += ", ";
|
|
74
73
|
}
|
|
75
|
-
|
|
74
|
+
}
|
|
75
|
+
peer_suites_str += "*]";
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
peerCipherSuites.assign(peer_csuites, peer_csuites + peer_csuites_len);
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
break;
|
|
79
|
+
char errorMessage[kErrorBufferSize];
|
|
80
|
+
std::snprintf(errorMessage, kErrorBufferSize, kErrorWrongSelectedCipherSuiteFormat, suites_str.c_str(),
|
|
81
|
+
peer_suites_str.c_str());
|
|
82
|
+
SetError(errorMessage);
|
|
83
|
+
return;
|
|
86
84
|
}
|
|
87
|
-
|
|
88
|
-
break;
|
|
85
|
+
break;
|
|
89
86
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
std::snprintf(errorMessage, kErrorBufferSize, kErrorMessageFormat, messageNumber + 1, error_code);
|
|
93
|
-
SetError(errorMessage);
|
|
87
|
+
default:
|
|
88
|
+
break;
|
|
94
89
|
}
|
|
95
90
|
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
char errorMessage[kErrorBufferSize];
|
|
92
|
+
std::snprintf(errorMessage, kErrorBufferSize, kErrorMessageFormat, messageNumber + 1, error_code);
|
|
93
|
+
SetError(errorMessage);
|
|
98
94
|
}
|
|
99
95
|
}
|
|
100
96
|
|
|
@@ -102,8 +98,14 @@ void EdhocProcessAsyncWorker::OnOK() {
|
|
|
102
98
|
Napi::Env env = Env();
|
|
103
99
|
Napi::HandleScope scope(env);
|
|
104
100
|
Napi::Array result = callback(env);
|
|
105
|
-
|
|
101
|
+
|
|
106
102
|
callback(env);
|
|
103
|
+
|
|
104
|
+
if (env.IsExceptionPending()) {
|
|
105
|
+
deferred.Reject(env.GetAndClearPendingException().Value());
|
|
106
|
+
} else {
|
|
107
|
+
deferred.Resolve(result);
|
|
108
|
+
}
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
void EdhocProcessAsyncWorker::OnError(const Napi::Error& error) {
|
|
@@ -118,8 +120,13 @@ void EdhocProcessAsyncWorker::OnError(const Napi::Error& error) {
|
|
|
118
120
|
error.Set("peerCipherSuites", result);
|
|
119
121
|
}
|
|
120
122
|
|
|
121
|
-
deferred.Reject(error.Value());
|
|
122
123
|
callback(env);
|
|
124
|
+
|
|
125
|
+
if (env.IsExceptionPending()) {
|
|
126
|
+
deferred.Reject(env.GetAndClearPendingException().Value());
|
|
127
|
+
} else {
|
|
128
|
+
deferred.Reject(error.Value());
|
|
129
|
+
}
|
|
123
130
|
}
|
|
124
131
|
|
|
125
132
|
Napi::Promise EdhocProcessAsyncWorker::GetPromise() {
|
package/src/LibEDHOC.cpp
CHANGED
|
@@ -49,7 +49,7 @@ LibEDHOC::LibEDHOC(const Napi::CallbackInfo& info) : Napi::ObjectWrap<LibEDHOC>(
|
|
|
49
49
|
// Initialize EDHOC context
|
|
50
50
|
context = {};
|
|
51
51
|
if (edhoc_context_init(&context) != EDHOC_SUCCESS) {
|
|
52
|
-
|
|
52
|
+
Napi::TypeError::New(env, kErrorFailedToInitializeEdhocContext).ThrowAsJavaScriptException();
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
// Connection ID, Methods, and Suites
|
|
@@ -72,7 +72,7 @@ LibEDHOC::LibEDHOC(const Napi::CallbackInfo& info) : Napi::ObjectWrap<LibEDHOC>(
|
|
|
72
72
|
edhoc_bind_crypto(&context, &cryptoManager->crypto) != EDHOC_SUCCESS ||
|
|
73
73
|
edhoc_bind_credentials(&context, &credentialManager->credentials) != EDHOC_SUCCESS ||
|
|
74
74
|
edhoc_bind_ead(&context, &eadManager->ead) != EDHOC_SUCCESS) {
|
|
75
|
-
|
|
75
|
+
Napi::TypeError::New(env, kErrorFailedToInitializeEdhocContext).ThrowAsJavaScriptException();
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// Logger
|
|
@@ -83,7 +83,7 @@ LibEDHOC::LibEDHOC(const Napi::CallbackInfo& info) : Napi::ObjectWrap<LibEDHOC>(
|
|
|
83
83
|
userContext->parent = Reference<Napi::Object>::New(info.This().As<Napi::Object>());
|
|
84
84
|
|
|
85
85
|
if (edhoc_set_user_context(&context, static_cast<void*>(userContext.get())) != EDHOC_SUCCESS) {
|
|
86
|
-
|
|
86
|
+
Napi::TypeError::New(env, kErrorFailedToInitializeEdhocContext).ThrowAsJavaScriptException();
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -121,7 +121,7 @@ void LibEDHOC::SetMethods(const Napi::CallbackInfo& info, const Napi::Value& val
|
|
|
121
121
|
Napi::Env env = info.Env();
|
|
122
122
|
|
|
123
123
|
if (!value.IsArray()) {
|
|
124
|
-
|
|
124
|
+
Napi::TypeError::New(env, kErrorArrayMethodIndexesExpected).ThrowAsJavaScriptException();
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
const auto jsArray = value.As<Napi::Array>();
|
|
@@ -133,7 +133,7 @@ void LibEDHOC::SetMethods(const Napi::CallbackInfo& info, const Napi::Value& val
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
if (edhoc_set_methods(&context, methods.data(), methods.size()) != EDHOC_SUCCESS) {
|
|
136
|
-
|
|
136
|
+
Napi::TypeError::New(env, kErrorFailedToSetEdhocMethod).ThrowAsJavaScriptException();
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
|
|
@@ -145,7 +145,7 @@ void LibEDHOC::SetCipherSuites(const Napi::CallbackInfo& info, const Napi::Value
|
|
|
145
145
|
Napi::Env env = info.Env();
|
|
146
146
|
|
|
147
147
|
if (!value.IsArray()) {
|
|
148
|
-
|
|
148
|
+
Napi::TypeError::New(env, kErrorArraySuiteIndexesExpected).ThrowAsJavaScriptException();
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
const auto jsArray = value.As<Napi::Array>();
|
|
@@ -156,14 +156,14 @@ void LibEDHOC::SetCipherSuites(const Napi::CallbackInfo& info, const Napi::Value
|
|
|
156
156
|
const uint32_t index = jsArray.Get(i).As<Napi::Number>().Uint32Value();
|
|
157
157
|
|
|
158
158
|
if (index >= suite_pointers_count || suite_pointers[index] == nullptr) {
|
|
159
|
-
|
|
159
|
+
Napi::RangeError::New(env, kErrorInvalidCipherSuiteIndex).ThrowAsJavaScriptException();
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
selected_suites.push_back(*suite_pointers[index]);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
if (edhoc_set_cipher_suites(&context, selected_suites.data(), selected_suites.size()) != 0) {
|
|
166
|
-
|
|
166
|
+
Napi::TypeError::New(env, kErrorFailedToSetCipherSuites).ThrowAsJavaScriptException();
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
|
|
@@ -215,12 +215,7 @@ Napi::Value LibEDHOC::ComposeMessage(const Napi::CallbackInfo& info, enum edhoc_
|
|
|
215
215
|
Napi::HandleScope scope(env);
|
|
216
216
|
|
|
217
217
|
if (info[0].IsArray()) {
|
|
218
|
-
|
|
219
|
-
userContext->GetEadManager()->StoreEad(messageNumber, info[0].As<Napi::Array>());
|
|
220
|
-
} catch (const Napi::Error& e) {
|
|
221
|
-
e.ThrowAsJavaScriptException();
|
|
222
|
-
return env.Null();
|
|
223
|
-
}
|
|
218
|
+
userContext->GetEadManager()->StoreEad(messageNumber, info[0].As<Napi::Array>());
|
|
224
219
|
}
|
|
225
220
|
|
|
226
221
|
userContext->GetCredentialManager()->SetupAsyncFunctions();
|
|
@@ -230,6 +225,9 @@ Napi::Value LibEDHOC::ComposeMessage(const Napi::CallbackInfo& info, enum edhoc_
|
|
|
230
225
|
userContext->GetEadManager()->ClearEadByMessage(messageNumber);
|
|
231
226
|
userContext->GetCredentialManager()->CleanupAsyncFunctions();
|
|
232
227
|
userContext->GetCryptoManager()->CleanupAsyncFunctions();
|
|
228
|
+
if (!userContext->error.IsEmpty()) {
|
|
229
|
+
userContext->error.ThrowAsJavaScriptException();
|
|
230
|
+
}
|
|
233
231
|
};
|
|
234
232
|
|
|
235
233
|
EdhocComposeAsyncWorker* worker = new EdhocComposeAsyncWorker(env, context, messageNumber, callback);
|
|
@@ -256,6 +254,9 @@ Napi::Value LibEDHOC::ProcessMessage(const Napi::CallbackInfo& info, enum edhoc_
|
|
|
256
254
|
userContext->GetEadManager()->ClearEadByMessage(messageNumber);
|
|
257
255
|
userContext->GetCredentialManager()->CleanupAsyncFunctions();
|
|
258
256
|
userContext->GetCryptoManager()->CleanupAsyncFunctions();
|
|
257
|
+
if (!userContext->error.IsEmpty()) {
|
|
258
|
+
userContext->error.ThrowAsJavaScriptException();
|
|
259
|
+
}
|
|
259
260
|
return EADs;
|
|
260
261
|
};
|
|
261
262
|
|
|
@@ -307,6 +308,9 @@ Napi::Value LibEDHOC::ExportOSCORE(const Napi::CallbackInfo& info) {
|
|
|
307
308
|
EdhocExportOscoreAsyncWorker::CallbackType callback = [this](Napi::Env& env) {
|
|
308
309
|
userContext->GetCredentialManager()->CleanupAsyncFunctions();
|
|
309
310
|
userContext->GetCryptoManager()->CleanupAsyncFunctions();
|
|
311
|
+
if (!userContext->error.IsEmpty()) {
|
|
312
|
+
userContext->error.ThrowAsJavaScriptException();
|
|
313
|
+
}
|
|
310
314
|
};
|
|
311
315
|
|
|
312
316
|
EdhocExportOscoreAsyncWorker* worker = new EdhocExportOscoreAsyncWorker(env, context, callback);
|
|
@@ -338,6 +342,9 @@ Napi::Value LibEDHOC::ExportKey(const Napi::CallbackInfo& info) {
|
|
|
338
342
|
EdhocKeyExporterAsyncWorker::CallbackType callback = [this](Napi::Env& env) {
|
|
339
343
|
userContext->GetCredentialManager()->CleanupAsyncFunctions();
|
|
340
344
|
userContext->GetCryptoManager()->CleanupAsyncFunctions();
|
|
345
|
+
if (!userContext->error.IsEmpty()) {
|
|
346
|
+
userContext->error.ThrowAsJavaScriptException();
|
|
347
|
+
}
|
|
341
348
|
};
|
|
342
349
|
|
|
343
350
|
EdhocKeyExporterAsyncWorker* worker = new EdhocKeyExporterAsyncWorker(env, context, label, desiredLength, callback);
|
|
@@ -364,6 +371,9 @@ Napi::Value LibEDHOC::KeyUpdate(const Napi::CallbackInfo& info) {
|
|
|
364
371
|
EdhocKeyUpdateAsyncWorker::CallbackType callback = [this](Napi::Env& env) {
|
|
365
372
|
userContext->GetCredentialManager()->CleanupAsyncFunctions();
|
|
366
373
|
userContext->GetCryptoManager()->CleanupAsyncFunctions();
|
|
374
|
+
if (!userContext->error.IsEmpty()) {
|
|
375
|
+
userContext->error.ThrowAsJavaScriptException();
|
|
376
|
+
}
|
|
367
377
|
};
|
|
368
378
|
|
|
369
379
|
EdhocKeyUpdateAsyncWorker* worker = new EdhocKeyUpdateAsyncWorker(env, context, contextBufferVector, callback);
|
package/src/Utils.cpp
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
#include <thread>
|
|
7
7
|
|
|
8
8
|
static constexpr const char* kStringThen = "then";
|
|
9
|
-
static constexpr const char* kStringCatch = "catch";
|
|
10
9
|
static constexpr const char* kErrorInputValueMustBeANumberOrABuffer = "Input value must be a number or a buffer";
|
|
11
10
|
|
|
12
11
|
void Utils::InvokeJSFunctionWithPromiseHandling(Napi::Env env,
|
|
@@ -17,21 +16,18 @@ void Utils::InvokeJSFunctionWithPromiseHandling(Napi::Env env,
|
|
|
17
16
|
ErrorHandler errorLambda) {
|
|
18
17
|
auto deferred = Napi::Promise::Deferred::New(env);
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
Napi::Value result = jsCallback.Call(jsObject, args);
|
|
20
|
+
|
|
21
|
+
if (env.IsExceptionPending()) {
|
|
22
|
+
deferred.Reject(env.GetAndClearPendingException().Value());
|
|
23
|
+
} else {
|
|
22
24
|
deferred.Resolve(result);
|
|
23
|
-
} catch (const Napi::Error& e) {
|
|
24
|
-
deferred.Reject(e.Value());
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
auto thenCallback = Napi::Function::New(env, [successLambda, errorLambda](const Napi::CallbackInfo& info) {
|
|
28
28
|
Napi::Env env = info.Env();
|
|
29
29
|
Napi::HandleScope scope(env);
|
|
30
|
-
|
|
31
|
-
successLambda(env, info[0].As<Napi::Value>());
|
|
32
|
-
} catch (const std::exception& e) {
|
|
33
|
-
errorLambda(env, Napi::Error::New(env, e.what()));
|
|
34
|
-
}
|
|
30
|
+
successLambda(env, info[0].As<Napi::Value>());
|
|
35
31
|
});
|
|
36
32
|
|
|
37
33
|
auto catchCallback = Napi::Function::New(env, [errorLambda](const Napi::CallbackInfo& info) {
|
|
@@ -41,8 +37,7 @@ void Utils::InvokeJSFunctionWithPromiseHandling(Napi::Env env,
|
|
|
41
37
|
});
|
|
42
38
|
|
|
43
39
|
Napi::Promise promise = deferred.Promise();
|
|
44
|
-
promise.Get(
|
|
45
|
-
promise.Get(kStringThen).As<Napi::Function>().Call(promise, {thenCallback});
|
|
40
|
+
promise.Get(kStringThen).As<Napi::Function>().Call(promise, {thenCallback, catchCallback});
|
|
46
41
|
}
|
|
47
42
|
|
|
48
43
|
void Utils::EncodeInt64ToBuffer(int64_t value, uint8_t* buffer, size_t* length) {
|
|
@@ -76,7 +71,7 @@ struct edhoc_connection_id Utils::ConvertJsValueToEdhocCid(Napi::Value value) {
|
|
|
76
71
|
cid.bstr_length = buffer.Length();
|
|
77
72
|
memcpy(cid.bstr_value, buffer.Data(), cid.bstr_length);
|
|
78
73
|
} else {
|
|
79
|
-
|
|
74
|
+
Napi::TypeError::New(value.Env(), kErrorInputValueMustBeANumberOrABuffer).ThrowAsJavaScriptException();
|
|
80
75
|
}
|
|
81
76
|
return cid;
|
|
82
77
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { EDHOC, X509CertificateCredentialManager, DefaultEdhocCryptoManager, EdhocMethod, EdhocSuite } from '../dist/index'
|
|
2
|
+
|
|
3
|
+
describe('EDHOC Handshake', () => {
|
|
4
|
+
|
|
5
|
+
const trustedCA = Buffer.from('308201323081DAA003020102021478408C6EC18A1D452DAE70C726CB0192A6116DBB300A06082A8648CE3D040302301A3118301606035504030C0F5468697320697320434120526F6F74301E170D3234313031393138333635335A170D3235313031393138333635335A301A3118301606035504030C0F5468697320697320434120526F6F743059301306072A8648CE3D020106082A8648CE3D03010703420004B9348A8A267EF52CFDC30109A29008A2D99F6B8F78BA9EAF5D51578C06134E78CB90A073EDC2488A14174B4E2997C840C5DE7F8E35EB54A0DB6977E894D1B2CB300A06082A8648CE3D040302034700304402203B92BFEC770B0FA4E17F8F02A13CD945D914ED8123AC85C37C8C7BAA2BE3E0F102202CB2DC2EC295B5F4B7BB631ED751179C145D6B6E081559AEA38CE215369E9C31', 'hex');
|
|
6
|
+
|
|
7
|
+
let initiator: EDHOC;
|
|
8
|
+
let responder: EDHOC;
|
|
9
|
+
let uncaughtException: jest.Mock;
|
|
10
|
+
let initiatorCryptoManager: DefaultEdhocCryptoManager;
|
|
11
|
+
let responderCryptoManager: DefaultEdhocCryptoManager;
|
|
12
|
+
|
|
13
|
+
let initiatorCredentialManager: X509CertificateCredentialManager;
|
|
14
|
+
let responderCredentialManager: X509CertificateCredentialManager;
|
|
15
|
+
|
|
16
|
+
const testError = new Error('Test error');
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
const initiatorKeyID = Buffer.from('00000001', 'hex');
|
|
20
|
+
initiatorCredentialManager = new X509CertificateCredentialManager(
|
|
21
|
+
[Buffer.from('3082012E3081D4A003020102021453423D5145C767CDC29895C3DB590192A611EA50300A06082A8648CE3D040302301A3118301606035504030C0F5468697320697320434120526F6F74301E170D3234313031393138333732345A170D3235313031393138333732345A30143112301006035504030C09696E69746961746F723059301306072A8648CE3D020106082A8648CE3D03010703420004EB0EF585F3992A1653CF310BF0F0F8035267CDAB6989C8B02E7228FBD759EF6B56263259AADF087F9849E7B7651F74C3B4F144CCCF86BB6FE2FF0EF3AA5FB5DC300A06082A8648CE3D0403020349003046022100D8C3AA7C98A730B3D4862EDAB4C1474FCD9A17A9CA3FB078914A10978FE95CC40221009F5877DD4E2C635A04ED1F6F1854C87B58521BDDFF533B1076F53D456739764C', 'hex')],
|
|
22
|
+
initiatorKeyID
|
|
23
|
+
);
|
|
24
|
+
initiatorCredentialManager.addTrustedCA(trustedCA);
|
|
25
|
+
|
|
26
|
+
initiatorCryptoManager = new DefaultEdhocCryptoManager();
|
|
27
|
+
initiatorCryptoManager.addKey(initiatorKeyID, Buffer.from('DC1FBB05B6B08360CE5B9EEA08EBFBFC6766A21340641863D4C8A3F68F096337', 'hex'));
|
|
28
|
+
|
|
29
|
+
const responderKeyID = Buffer.from('00000002', 'hex');
|
|
30
|
+
responderCredentialManager = new X509CertificateCredentialManager(
|
|
31
|
+
[Buffer.from('3082012E3081D4A00302010202146648869E2608FC2E16D945C10E1F0192A6125CC0300A06082A8648CE3D040302301A3118301606035504030C0F5468697320697320434120526F6F74301E170D3234313031393138333735345A170D3235313031393138333735345A30143112301006035504030C09726573706F6E6465723059301306072A8648CE3D020106082A8648CE3D03010703420004161F76A7A106C9B79B7F651156B5B095E63A6101A39020F4E86DDACE61FB395E8AEF6CD9C444EE9A43DBD62DAD44FF50FE4146247D3AFD28F60DBC01FBFC573C300A06082A8648CE3D0403020349003046022100E8AD0926518CDB61E84D171700C7158FD0E72D03A117D40133ECD10F8B9F42CE022100E7E69B4C79100B3F0792F010AE11EE5DD2859C29EFC4DBCEFD41FA5CD4D3C3C9', 'hex')],
|
|
32
|
+
responderKeyID
|
|
33
|
+
);
|
|
34
|
+
responderCredentialManager.addTrustedCA(trustedCA);
|
|
35
|
+
|
|
36
|
+
responderCryptoManager = new DefaultEdhocCryptoManager();
|
|
37
|
+
responderCryptoManager.addKey(responderKeyID, Buffer.from('EE6287116FE27CDC539629DC87E12BF8EAA2229E7773AA67BC4C0FBA96E7FBB2', 'hex'));
|
|
38
|
+
|
|
39
|
+
initiator = new EDHOC(10, [EdhocMethod.Method1], [EdhocSuite.Suite2], initiatorCredentialManager, initiatorCryptoManager);
|
|
40
|
+
responder = new EDHOC(20, [EdhocMethod.Method2, EdhocMethod.Method0, EdhocMethod.Method1], [EdhocSuite.Suite2], responderCredentialManager, responderCryptoManager);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
uncaughtException = jest.fn();
|
|
45
|
+
process.on('uncaughtException', err => uncaughtException(err))
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
afterEach(() => {
|
|
49
|
+
process.removeAllListeners('uncaughtException');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('should throw uncaughtException', async () => {
|
|
53
|
+
const error = new Error('Test error');
|
|
54
|
+
process.emit('uncaughtException', error);
|
|
55
|
+
expect(uncaughtException).toHaveBeenCalledWith(error);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('should throw from crypto manager hash', async () => {
|
|
59
|
+
|
|
60
|
+
responderCryptoManager.hash = jest.fn().mockImplementation(() => { throw testError });
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
|
|
64
|
+
const message1 = await initiator.composeMessage1([{ label: 1, value: Buffer.from('Hello') }]);
|
|
65
|
+
await responder.processMessage1(message1);
|
|
66
|
+
|
|
67
|
+
} catch (error) {
|
|
68
|
+
expect(error).toBe(testError);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
expect(uncaughtException).not.toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('should throw from credential manager fetch', async () => {
|
|
75
|
+
|
|
76
|
+
responderCredentialManager.fetch = jest.fn().mockImplementation(() => { throw testError });
|
|
77
|
+
const catchHandler = jest.fn();
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const message1 = await initiator.composeMessage1();
|
|
81
|
+
await responder.processMessage1(message1);
|
|
82
|
+
await responder.composeMessage2();
|
|
83
|
+
} catch (error) {
|
|
84
|
+
catchHandler(error);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
expect(catchHandler).toHaveBeenCalledWith(testError);
|
|
88
|
+
expect(uncaughtException).not.toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('should throw from crypto manager importKey', async () => {
|
|
92
|
+
|
|
93
|
+
initiatorCryptoManager.importKey = jest.fn().mockImplementation(() => { throw testError });
|
|
94
|
+
const catchHandler = jest.fn();
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const message1 = await initiator.composeMessage1([{ label: 1, value: Buffer.from('Hello') }]);
|
|
98
|
+
await responder.processMessage1(message1);
|
|
99
|
+
await responder.composeMessage2();
|
|
100
|
+
} catch (error) {
|
|
101
|
+
catchHandler(error);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
expect(catchHandler).toHaveBeenCalled();
|
|
105
|
+
expect(uncaughtException).not.toHaveBeenCalled();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('should throw from crypto manager encrypt', async () => {
|
|
109
|
+
|
|
110
|
+
initiatorCryptoManager.encrypt = jest.fn().mockImplementation(() => { throw testError });
|
|
111
|
+
const catchHandler = jest.fn();
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const message1 = await initiator.composeMessage1([{ label: 1, value: Buffer.from('Hello') }]);
|
|
115
|
+
await responder.processMessage1(message1);
|
|
116
|
+
|
|
117
|
+
const message2 = await responder.composeMessage2();
|
|
118
|
+
await initiator.processMessage2(message2);
|
|
119
|
+
|
|
120
|
+
const message3 = await initiator.composeMessage3();
|
|
121
|
+
await responder.processMessage3(message3);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
catchHandler(error);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
expect(catchHandler).toHaveBeenCalled();
|
|
127
|
+
expect(uncaughtException).not.toHaveBeenCalled();
|
|
128
|
+
});
|
|
129
|
+
});
|