edhoc 1.2.2 → 1.3.0
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/dist/edhoc.d.ts +4 -0
- package/dist/edhoc.d.ts.map +1 -1
- package/include/{LibEDHOC.h → Binding.h} +60 -40
- package/include/EdhocComposeAsyncWorker.h +8 -22
- package/include/EdhocCredentialManager.h +9 -25
- package/include/EdhocCryptoManager.h +27 -43
- package/include/EdhocEadManager.h +3 -4
- package/include/EdhocExportOscoreAsyncWorker.h +10 -27
- package/include/EdhocKeyExporterAsyncWorker.h +8 -28
- package/include/EdhocKeyUpdateAsyncWorker.h +7 -24
- package/include/EdhocProcessAsyncWorker.h +11 -36
- package/include/RunningContext.h +102 -0
- package/include/Utils.h +0 -43
- package/package.json +1 -2
- 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/Binding.cpp +434 -0
- package/src/EdhocComposeAsyncWorker.cpp +15 -26
- package/src/EdhocCredentialManager.cpp +50 -69
- package/src/EdhocCryptoManager.cpp +158 -332
- package/src/EdhocEadManager.cpp +11 -11
- package/src/EdhocExportOscoreAsyncWorker.cpp +18 -28
- package/src/EdhocKeyExporterAsyncWorker.cpp +11 -21
- package/src/EdhocKeyUpdateAsyncWorker.cpp +8 -18
- package/src/EdhocProcessAsyncWorker.cpp +28 -35
- package/src/RunningContext.cpp +95 -0
- package/src/Utils.cpp +1 -38
- package/test/basic.test.ts +57 -3
- package/include/UserContext.h +0 -77
- package/src/LibEDHOC.cpp +0 -408
package/include/Utils.h
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#define UTILS_H
|
|
3
3
|
|
|
4
4
|
#include <napi.h>
|
|
5
|
-
|
|
6
5
|
#include <cstdint>
|
|
7
6
|
#include <future>
|
|
8
7
|
#include <string>
|
|
@@ -22,48 +21,6 @@ extern "C" {
|
|
|
22
21
|
*/
|
|
23
22
|
class Utils {
|
|
24
23
|
public:
|
|
25
|
-
using SuccessHandler = std::function<void(Napi::Env, Napi::Value)>;
|
|
26
|
-
using ErrorHandler = std::function<void(Napi::Env, Napi::Error)>;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Invokes a JavaScript function with promise handling.
|
|
30
|
-
* The function is called with the specified arguments, and the result is
|
|
31
|
-
* passed to a callback function.
|
|
32
|
-
*
|
|
33
|
-
* @param env The N-API environment handle.
|
|
34
|
-
* @param jsObject The N-API object representing the JavaScript class.
|
|
35
|
-
* @param jsCallback The N-API function object to call.
|
|
36
|
-
* @param args A vector of N-API values representing the arguments to pass to
|
|
37
|
-
* the function.
|
|
38
|
-
* @param callbackLambda A lambda function to handle the result of the
|
|
39
|
-
* function call.
|
|
40
|
-
*/
|
|
41
|
-
static void InvokeJSFunctionWithPromiseHandling(Napi::Env env,
|
|
42
|
-
Napi::Object jsObject,
|
|
43
|
-
Napi::Function jsCallback,
|
|
44
|
-
const std::vector<napi_value>& args,
|
|
45
|
-
SuccessHandler successLambda,
|
|
46
|
-
ErrorHandler errorLambda);
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Creates a promise error handler for a given promise.
|
|
50
|
-
*
|
|
51
|
-
* @tparam T The type of the promise.
|
|
52
|
-
* @param promise The promise to handle errors for.
|
|
53
|
-
* @return A lambda function that sets the exception on the promise.
|
|
54
|
-
*/
|
|
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);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
24
|
/**
|
|
68
25
|
* Converts a JavaScript value to an EDHOC connection ID structure.
|
|
69
26
|
* The input can be a number or a buffer.
|
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.
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"author": "Marek Serafin <marek@serafin.email>",
|
|
@@ -53,7 +53,6 @@
|
|
|
53
53
|
"@semantic-release/git": "^10.0.1",
|
|
54
54
|
"@semantic-release/github": "^10.1.1",
|
|
55
55
|
"@types/elliptic": "^6.4.18",
|
|
56
|
-
"@types/eslint__js": "^8.42.3",
|
|
57
56
|
"@types/jest": "^29.5.14",
|
|
58
57
|
"@types/node": "^22.13.4",
|
|
59
58
|
"eslint": "^8.57.0",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/Binding.cpp
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
#include "Binding.h"
|
|
2
|
+
|
|
3
|
+
#include <iostream>
|
|
4
|
+
#include <thread>
|
|
5
|
+
|
|
6
|
+
#include "EdhocComposeAsyncWorker.h"
|
|
7
|
+
#include "EdhocExportOscoreAsyncWorker.h"
|
|
8
|
+
#include "EdhocKeyExporterAsyncWorker.h"
|
|
9
|
+
#include "EdhocKeyUpdateAsyncWorker.h"
|
|
10
|
+
#include "EdhocProcessAsyncWorker.h"
|
|
11
|
+
#include "Suites.h"
|
|
12
|
+
#include "Utils.h"
|
|
13
|
+
|
|
14
|
+
static constexpr const char* kErrorFailedToInitializeEdhocContext = "Failed to initialize EDHOC context.";
|
|
15
|
+
static constexpr const char* kErrorFailedToSetEdhocConnectionId = "Failed to set EDHOC Connection ID.";
|
|
16
|
+
static constexpr const char* kErrorFailedToSetEdhocMethod = "Failed to set EDHOC Method.";
|
|
17
|
+
static constexpr const char* kErrorArraySuiteIndexesExpected = "Array of suite indexes expected";
|
|
18
|
+
static constexpr const char* kErrorArrayMethodIndexesExpected = "Array of method indexes expected";
|
|
19
|
+
static constexpr const char* kErrorInvalidCipherSuiteIndex = "Invalid cipher suite index";
|
|
20
|
+
static constexpr const char* kErrorFailedToSetCipherSuites = "Failed to set cipher suites";
|
|
21
|
+
static constexpr const char* kErrorExpectedFirstArgumentToBeBuffer = "Expected first argument to be a Buffer";
|
|
22
|
+
static constexpr const char* kErrorExpectedArgumentToBeNumber = "Expected argument to be a number";
|
|
23
|
+
static constexpr const char* kErrorExpectedAFunction = "Expected a function";
|
|
24
|
+
|
|
25
|
+
Edhoc::Edhoc(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Edhoc>(info) {
|
|
26
|
+
Napi::Env env = info.Env();
|
|
27
|
+
Napi::HandleScope scope(env);
|
|
28
|
+
|
|
29
|
+
// Get the JS object
|
|
30
|
+
Napi::Object jsEdhoc = info.This().As<Napi::Object>();
|
|
31
|
+
|
|
32
|
+
// Crypto Manager
|
|
33
|
+
Napi::Object jsCryptoManager = info[4].As<Napi::Object>();
|
|
34
|
+
this->cryptoManager_ = std::make_unique<EdhocCryptoManager>(jsCryptoManager, jsEdhoc);
|
|
35
|
+
|
|
36
|
+
// Credentials
|
|
37
|
+
Napi::Object jsCredentialManager = info[3].As<Napi::Object>();
|
|
38
|
+
this->credentialManager_ = std::make_unique<EdhocCredentialManager>(jsCredentialManager, jsEdhoc);
|
|
39
|
+
|
|
40
|
+
// EAD
|
|
41
|
+
this->eadManager_ = std::make_unique<EdhocEadManager>();
|
|
42
|
+
|
|
43
|
+
// Reset the EDHOC context
|
|
44
|
+
this->Reset(info);
|
|
45
|
+
|
|
46
|
+
// Connection ID, Methods, and Suites
|
|
47
|
+
SetCID(info, info[0]);
|
|
48
|
+
SetMethods(info, info[1]);
|
|
49
|
+
SetCipherSuites(info, info[2]);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void Edhoc::Reset(const Napi::CallbackInfo& info) {
|
|
53
|
+
Napi::Env env = info.Env();
|
|
54
|
+
Napi::HandleScope scope(env);
|
|
55
|
+
|
|
56
|
+
bool isInitialized = edhocContext_ != nullptr;
|
|
57
|
+
|
|
58
|
+
// Get the Connection ID, Methods, and Suites
|
|
59
|
+
Napi::Value cid = env.Null();
|
|
60
|
+
Napi::Value methods = env.Null();
|
|
61
|
+
Napi::Value suites = env.Null();
|
|
62
|
+
|
|
63
|
+
if (isInitialized) {
|
|
64
|
+
cid = this->GetCID(info);
|
|
65
|
+
methods = this->GetMethods(info);
|
|
66
|
+
suites = this->GetCipherSuites(info);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Initialize EDHOC context
|
|
70
|
+
edhocContext_ = std::make_unique<edhoc_context>();
|
|
71
|
+
|
|
72
|
+
if (edhoc_context_init(edhocContext_.get()) != EDHOC_SUCCESS) {
|
|
73
|
+
Napi::TypeError::New(env, kErrorFailedToInitializeEdhocContext)
|
|
74
|
+
.ThrowAsJavaScriptException();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Bind all managers
|
|
78
|
+
if (edhoc_bind_keys(edhocContext_.get(), &this->cryptoManager_.get()->keys) != EDHOC_SUCCESS ||
|
|
79
|
+
edhoc_bind_crypto(edhocContext_.get(), &this->cryptoManager_.get()->crypto) != EDHOC_SUCCESS ||
|
|
80
|
+
edhoc_bind_credentials(edhocContext_.get(), &this->credentialManager_.get()->credentials) != EDHOC_SUCCESS ||
|
|
81
|
+
edhoc_bind_ead(edhocContext_.get(), &this->eadManager_.get()->ead) != EDHOC_SUCCESS)
|
|
82
|
+
{
|
|
83
|
+
Napi::TypeError::New(env, kErrorFailedToInitializeEdhocContext)
|
|
84
|
+
.ThrowAsJavaScriptException();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// If the previous context was initialized, copy the Connection ID, Methods, and Suites
|
|
88
|
+
if (isInitialized) {
|
|
89
|
+
this->SetCID(info, cid);
|
|
90
|
+
this->SetMethods(info, methods);
|
|
91
|
+
this->SetCipherSuites(info, suites);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Logger
|
|
95
|
+
edhocContext_->logger = Edhoc::Logger;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
Edhoc::~Edhoc() {
|
|
99
|
+
// Reset the EDHOC context
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
Napi::Value Edhoc::GetCID(const Napi::CallbackInfo& info) {
|
|
103
|
+
return Utils::CreateJsValueFromEdhocCid(info.Env(), cid_);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
void Edhoc::SetCID(const Napi::CallbackInfo& info, const Napi::Value& value) {
|
|
107
|
+
cid_ = Utils::ConvertJsValueToEdhocCid(value);
|
|
108
|
+
int result = edhoc_set_connection_id(edhocContext_.get(), &cid_);
|
|
109
|
+
if (result != EDHOC_SUCCESS) {
|
|
110
|
+
Napi::TypeError::New(info.Env(), kErrorFailedToSetEdhocConnectionId).ThrowAsJavaScriptException();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
Napi::Value Edhoc::GetPeerCID(const Napi::CallbackInfo& info) {
|
|
115
|
+
return Utils::CreateJsValueFromEdhocCid(info.Env(), edhocContext_->EDHOC_PRIVATE(peer_cid));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
Napi::Value Edhoc::GetMethods(const Napi::CallbackInfo& info) {
|
|
119
|
+
Napi::Env env = info.Env();
|
|
120
|
+
Napi::Array result = Napi::Array::New(env, edhocContext_->EDHOC_PRIVATE(method_len));
|
|
121
|
+
for (size_t i = 0; i < edhocContext_->EDHOC_PRIVATE(method_len); i++) {
|
|
122
|
+
result.Set(i, Napi::Number::New(env, edhocContext_->EDHOC_PRIVATE(method)[i]));
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
void Edhoc::SetMethods(const Napi::CallbackInfo& info, const Napi::Value& value) {
|
|
128
|
+
Napi::Env env = info.Env();
|
|
129
|
+
|
|
130
|
+
if (!value.IsArray()) {
|
|
131
|
+
Napi::TypeError::New(env, kErrorArrayMethodIndexesExpected)
|
|
132
|
+
.ThrowAsJavaScriptException();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const auto jsArray = value.As<Napi::Array>();
|
|
136
|
+
std::vector<edhoc_method> methods;
|
|
137
|
+
methods.reserve(jsArray.Length());
|
|
138
|
+
|
|
139
|
+
for (uint32_t i = 0; i < jsArray.Length(); i++) {
|
|
140
|
+
methods.push_back(static_cast<edhoc_method>(jsArray.Get(i).As<Napi::Number>().Int32Value()));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
int result = edhoc_set_methods(edhocContext_.get(), methods.data(), methods.size());
|
|
144
|
+
if (result != EDHOC_SUCCESS) {
|
|
145
|
+
Napi::TypeError::New(env, kErrorFailedToSetEdhocMethod)
|
|
146
|
+
.ThrowAsJavaScriptException();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
Napi::Value Edhoc::GetSelectedMethod(const Napi::CallbackInfo& info) {
|
|
151
|
+
return Napi::Number::New(info.Env(), edhocContext_->EDHOC_PRIVATE(chosen_method));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
void Edhoc::SetCipherSuites(const Napi::CallbackInfo& info, const Napi::Value& value) {
|
|
155
|
+
Napi::Env env = info.Env();
|
|
156
|
+
|
|
157
|
+
if (!value.IsArray()) {
|
|
158
|
+
Napi::TypeError::New(env, kErrorArraySuiteIndexesExpected)
|
|
159
|
+
.ThrowAsJavaScriptException();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const auto jsArray = value.As<Napi::Array>();
|
|
163
|
+
std::vector<edhoc_cipher_suite> selected_suites;
|
|
164
|
+
selected_suites.reserve(jsArray.Length());
|
|
165
|
+
|
|
166
|
+
for (uint32_t i = 0; i < jsArray.Length(); i++) {
|
|
167
|
+
const uint32_t index = jsArray.Get(i).As<Napi::Number>().Uint32Value();
|
|
168
|
+
|
|
169
|
+
if (index >= suite_pointers_count || suite_pointers[index] == nullptr) {
|
|
170
|
+
Napi::RangeError::New(env, kErrorInvalidCipherSuiteIndex)
|
|
171
|
+
.ThrowAsJavaScriptException();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
selected_suites.push_back(*suite_pointers[index]);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (edhoc_set_cipher_suites(edhocContext_.get(), selected_suites.data(), selected_suites.size()) != 0) {
|
|
178
|
+
Napi::TypeError::New(env, kErrorFailedToSetCipherSuites)
|
|
179
|
+
.ThrowAsJavaScriptException();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
Napi::Value Edhoc::GetCipherSuites(const Napi::CallbackInfo& info) {
|
|
184
|
+
Napi::Env env = info.Env();
|
|
185
|
+
Napi::Array result = Napi::Array::New(env, edhocContext_->EDHOC_PRIVATE(csuite_len));
|
|
186
|
+
for (size_t i = 0; i < edhocContext_->EDHOC_PRIVATE(csuite_len); i++) {
|
|
187
|
+
result.Set(i, Napi::Number::New(env, edhocContext_->EDHOC_PRIVATE(csuite)[i].value));
|
|
188
|
+
}
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
Napi::Value Edhoc::GetSelectedCipherSuite(const Napi::CallbackInfo& info) {
|
|
193
|
+
Napi::Env env = info.Env();
|
|
194
|
+
Napi::Number suite =
|
|
195
|
+
Napi::Number::New(env, edhocContext_->EDHOC_PRIVATE(csuite)[edhocContext_->EDHOC_PRIVATE(chosen_csuite_idx)].value);
|
|
196
|
+
return suite;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
Napi::Value Edhoc::GetLogger(const Napi::CallbackInfo& info) {
|
|
200
|
+
return logger_.Value();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
void Edhoc::SetLogger(const Napi::CallbackInfo& info, const Napi::Value& value) {
|
|
204
|
+
if (!info[0].IsFunction()) {
|
|
205
|
+
Napi::TypeError::New(info.Env(), kErrorExpectedAFunction).ThrowAsJavaScriptException();
|
|
206
|
+
}
|
|
207
|
+
Napi::Function jsCallback = info[0].As<Napi::Function>();
|
|
208
|
+
logger_ = Napi::Persistent(jsCallback);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
void Edhoc::Logger(void* user_context, const char* name, const uint8_t* buffer, size_t buffer_length) {
|
|
212
|
+
RunningContext* context = static_cast<RunningContext*>(const_cast<void*>(user_context));
|
|
213
|
+
|
|
214
|
+
if (!context || !context->GetTsfn() || !context->GetLoggerRef()) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const std::vector<uint8_t> bufferCopy(buffer, buffer + buffer_length);
|
|
219
|
+
|
|
220
|
+
context->GetTsfn().NonBlockingCall(context, [name = std::string(name), bufferCopy](Napi::Env env, Napi::Function jsCallback, RunningContext* context) {
|
|
221
|
+
Napi::HandleScope scope(env);
|
|
222
|
+
try {
|
|
223
|
+
context->GetLoggerRef().Value().As<Napi::Function>().Call({Napi::String::New(env, name), Napi::Buffer<uint8_t>::Copy(env, bufferCopy.data(), bufferCopy.size())});
|
|
224
|
+
} catch (const Napi::Error& e) {
|
|
225
|
+
// This is just a logger, so we don't want to throw an error
|
|
226
|
+
std::cerr << "Error in Logger: " << e.Get("stack").ToString().Utf8Value() << std::endl;
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
void Edhoc::StartRunningContext(Napi::Env env) {
|
|
232
|
+
// Initialize the running context
|
|
233
|
+
this->runningContext_ = std::make_unique<RunningContext>(
|
|
234
|
+
env,
|
|
235
|
+
edhocContext_.get(),
|
|
236
|
+
this->cryptoManager_.get(),
|
|
237
|
+
this->eadManager_.get(),
|
|
238
|
+
this->credentialManager_.get(),
|
|
239
|
+
logger_.Value()
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
// Set the user context of the EDHOC context
|
|
243
|
+
if (edhoc_set_user_context(edhocContext_.get(), static_cast<void*>(this->runningContext_.get())) != EDHOC_SUCCESS) {
|
|
244
|
+
Napi::TypeError::New(env, kErrorFailedToInitializeEdhocContext)
|
|
245
|
+
.ThrowAsJavaScriptException();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
Napi::Value Edhoc::ComposeMessage(const Napi::CallbackInfo& info, enum edhoc_message messageNumber) {
|
|
250
|
+
Napi::Env env = info.Env();
|
|
251
|
+
Napi::HandleScope scope(env);
|
|
252
|
+
|
|
253
|
+
// Check if the first argument (EADs) is an array
|
|
254
|
+
if (info[0].IsArray()) {
|
|
255
|
+
try {
|
|
256
|
+
this->eadManager_->StoreEad(messageNumber, info[0].As<Napi::Array>());
|
|
257
|
+
} catch (const Napi::Error& e) {
|
|
258
|
+
e.ThrowAsJavaScriptException();
|
|
259
|
+
return env.Null();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Start the running context
|
|
264
|
+
this->StartRunningContext(env);
|
|
265
|
+
|
|
266
|
+
// Compose the message
|
|
267
|
+
EdhocComposeAsyncWorker* worker = new EdhocComposeAsyncWorker(this->runningContext_.get(), messageNumber);
|
|
268
|
+
worker->Queue();
|
|
269
|
+
|
|
270
|
+
// Return the promise of the running context
|
|
271
|
+
return this->runningContext_->GetPromise();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
Napi::Value Edhoc::ProcessMessage(const Napi::CallbackInfo& info, enum edhoc_message messageNumber) {
|
|
275
|
+
Napi::Env env = info.Env();
|
|
276
|
+
Napi::HandleScope scope(env);
|
|
277
|
+
|
|
278
|
+
// Check if the first argument (input buffer) is a buffer
|
|
279
|
+
if (info.Length() < 1 || !info[0].IsBuffer()) {
|
|
280
|
+
Napi::TypeError::New(env, kErrorExpectedFirstArgumentToBeBuffer).ThrowAsJavaScriptException();
|
|
281
|
+
return env.Null();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Get the input buffer
|
|
285
|
+
Napi::Buffer<uint8_t> inputBuffer = info[0].As<Napi::Buffer<uint8_t>>();
|
|
286
|
+
|
|
287
|
+
// Start the running context
|
|
288
|
+
this->StartRunningContext(env);
|
|
289
|
+
|
|
290
|
+
// Process the message
|
|
291
|
+
EdhocProcessAsyncWorker* worker = new EdhocProcessAsyncWorker(this->runningContext_.get(), messageNumber, inputBuffer);
|
|
292
|
+
worker->Queue();
|
|
293
|
+
|
|
294
|
+
// Return the promise of the running context
|
|
295
|
+
return this->runningContext_->GetPromise();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
Napi::Value Edhoc::ComposeMessage1(const Napi::CallbackInfo& info) {
|
|
299
|
+
return ComposeMessage(info, EDHOC_MSG_1);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
Napi::Value Edhoc::ProcessMessage1(const Napi::CallbackInfo& info) {
|
|
303
|
+
return ProcessMessage(info, EDHOC_MSG_1);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
Napi::Value Edhoc::ComposeMessage2(const Napi::CallbackInfo& info) {
|
|
307
|
+
return ComposeMessage(info, EDHOC_MSG_2);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
Napi::Value Edhoc::ProcessMessage2(const Napi::CallbackInfo& info) {
|
|
311
|
+
return ProcessMessage(info, EDHOC_MSG_2);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
Napi::Value Edhoc::ComposeMessage3(const Napi::CallbackInfo& info) {
|
|
315
|
+
return ComposeMessage(info, EDHOC_MSG_3);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
Napi::Value Edhoc::ProcessMessage3(const Napi::CallbackInfo& info) {
|
|
319
|
+
return ProcessMessage(info, EDHOC_MSG_3);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
Napi::Value Edhoc::ComposeMessage4(const Napi::CallbackInfo& info) {
|
|
323
|
+
return ComposeMessage(info, EDHOC_MSG_4);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
Napi::Value Edhoc::ProcessMessage4(const Napi::CallbackInfo& info) {
|
|
327
|
+
return ProcessMessage(info, EDHOC_MSG_4);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
Napi::Value Edhoc::ExportOSCORE(const Napi::CallbackInfo& info) {
|
|
331
|
+
Napi::Env env = info.Env();
|
|
332
|
+
Napi::HandleScope scope(env);
|
|
333
|
+
|
|
334
|
+
// Start the running context
|
|
335
|
+
this->StartRunningContext(env);
|
|
336
|
+
|
|
337
|
+
// Export the OSCORE
|
|
338
|
+
EdhocExportOscoreAsyncWorker* worker = new EdhocExportOscoreAsyncWorker(this->runningContext_.get());
|
|
339
|
+
worker->Queue();
|
|
340
|
+
|
|
341
|
+
// Return the promise of the running context
|
|
342
|
+
return this->runningContext_->GetPromise();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
Napi::Value Edhoc::ExportKey(const Napi::CallbackInfo& info) {
|
|
346
|
+
Napi::Env env = info.Env();
|
|
347
|
+
Napi::HandleScope scope(env);
|
|
348
|
+
|
|
349
|
+
// Check if the first argument (label) is a number
|
|
350
|
+
if (info.Length() < 1 || !info[0].IsNumber()) {
|
|
351
|
+
Napi::TypeError::New(env, kErrorExpectedArgumentToBeNumber).ThrowAsJavaScriptException();
|
|
352
|
+
return env.Null();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Check if the second argument (desired length) is a number
|
|
356
|
+
if (info.Length() < 2 || !info[1].IsNumber()) {
|
|
357
|
+
Napi::TypeError::New(env, kErrorExpectedArgumentToBeNumber).ThrowAsJavaScriptException();
|
|
358
|
+
return env.Null();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Get the label and desired length
|
|
362
|
+
uint16_t label = (uint16_t)info[0].As<Napi::Number>().Uint32Value();
|
|
363
|
+
uint8_t desiredLength = (uint8_t)info[1].As<Napi::Number>().Uint32Value();
|
|
364
|
+
|
|
365
|
+
// Start the running context
|
|
366
|
+
this->StartRunningContext(env);
|
|
367
|
+
|
|
368
|
+
// Export the key
|
|
369
|
+
EdhocKeyExporterAsyncWorker* worker = new EdhocKeyExporterAsyncWorker(this->runningContext_.get(), label, desiredLength);
|
|
370
|
+
worker->Queue();
|
|
371
|
+
|
|
372
|
+
// Return the promise of the running context
|
|
373
|
+
return this->runningContext_->GetPromise();
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
Napi::Value Edhoc::KeyUpdate(const Napi::CallbackInfo& info) {
|
|
377
|
+
Napi::Env env = info.Env();
|
|
378
|
+
Napi::HandleScope scope(env);
|
|
379
|
+
|
|
380
|
+
// Check if the first argument (context buffer) is a buffer
|
|
381
|
+
if (info.Length() < 1 || !info[0].IsBuffer()) {
|
|
382
|
+
Napi::TypeError::New(env, kErrorExpectedFirstArgumentToBeBuffer).ThrowAsJavaScriptException();
|
|
383
|
+
return env.Null();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Get the context buffer
|
|
387
|
+
Napi::Buffer<uint8_t> contextBuffer = info[0].As<Napi::Buffer<uint8_t>>();
|
|
388
|
+
std::vector<uint8_t> contextBufferVector(contextBuffer.Data(), contextBuffer.Data() + contextBuffer.Length());
|
|
389
|
+
|
|
390
|
+
// Start the running context
|
|
391
|
+
this->StartRunningContext(env);
|
|
392
|
+
|
|
393
|
+
// Update the key
|
|
394
|
+
EdhocKeyUpdateAsyncWorker* worker = new EdhocKeyUpdateAsyncWorker(this->runningContext_.get(), contextBufferVector);
|
|
395
|
+
worker->Queue();
|
|
396
|
+
|
|
397
|
+
// Return the promise of the running context
|
|
398
|
+
return this->runningContext_->GetPromise();
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
Napi::Object Edhoc::Init(Napi::Env env, Napi::Object exports) {
|
|
402
|
+
Napi::HandleScope scope(env);
|
|
403
|
+
|
|
404
|
+
Napi::Function func = DefineClass(env, "EDHOC", {
|
|
405
|
+
InstanceAccessor("connectionID", &Edhoc::GetCID, &Edhoc::SetCID),
|
|
406
|
+
InstanceAccessor<&Edhoc::GetPeerCID>("peerConnectionID"),
|
|
407
|
+
InstanceAccessor("methods", &Edhoc::GetMethods, &Edhoc::SetMethods),
|
|
408
|
+
InstanceAccessor<&Edhoc::GetSelectedMethod>("selectedMethod"),
|
|
409
|
+
InstanceAccessor("cipherSuites", &Edhoc::GetCipherSuites, &Edhoc::SetCipherSuites),
|
|
410
|
+
InstanceAccessor<&Edhoc::GetSelectedCipherSuite>("selectedSuite"),
|
|
411
|
+
InstanceAccessor("logger", &Edhoc::GetLogger, &Edhoc::SetLogger),
|
|
412
|
+
InstanceMethod("reset", &Edhoc::Reset),
|
|
413
|
+
InstanceMethod("composeMessage1", &Edhoc::ComposeMessage1),
|
|
414
|
+
InstanceMethod("processMessage1", &Edhoc::ProcessMessage1),
|
|
415
|
+
InstanceMethod("composeMessage2", &Edhoc::ComposeMessage2),
|
|
416
|
+
InstanceMethod("processMessage2", &Edhoc::ProcessMessage2),
|
|
417
|
+
InstanceMethod("composeMessage3", &Edhoc::ComposeMessage3),
|
|
418
|
+
InstanceMethod("processMessage3", &Edhoc::ProcessMessage3),
|
|
419
|
+
InstanceMethod("composeMessage4", &Edhoc::ComposeMessage4),
|
|
420
|
+
InstanceMethod("processMessage4", &Edhoc::ProcessMessage4),
|
|
421
|
+
InstanceMethod("exportOSCORE", &Edhoc::ExportOSCORE),
|
|
422
|
+
InstanceMethod("exportKey", &Edhoc::ExportKey),
|
|
423
|
+
InstanceMethod("keyUpdate", &Edhoc::KeyUpdate),
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
Napi::FunctionReference* constructor = new Napi::FunctionReference();
|
|
427
|
+
*constructor = Napi::Persistent(func);
|
|
428
|
+
env.SetInstanceData(constructor);
|
|
429
|
+
|
|
430
|
+
exports.Set("EDHOC", func);
|
|
431
|
+
return exports;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
NODE_API_NAMED_ADDON(addon, Edhoc);
|
|
@@ -5,48 +5,42 @@ static constexpr const char* kErrorInvalidMessageNumber = "Invalid message numbe
|
|
|
5
5
|
static constexpr const char* kErrorMessageFormat = "Failed to compose EDHOC message %d. Error code: %d";
|
|
6
6
|
static constexpr size_t kErrorBufferSize = 100;
|
|
7
7
|
|
|
8
|
-
EdhocComposeAsyncWorker::EdhocComposeAsyncWorker(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
: Napi::AsyncWorker(env),
|
|
13
|
-
deferred(Napi::Promise::Deferred::New(env)),
|
|
14
|
-
context(context),
|
|
15
|
-
messageNumber(messageNumber),
|
|
16
|
-
callback(std::move(callback)) {}
|
|
8
|
+
EdhocComposeAsyncWorker::EdhocComposeAsyncWorker(RunningContext* runningContext, int messageNumber)
|
|
9
|
+
: Napi::AsyncWorker(runningContext->GetEnv()),
|
|
10
|
+
runningContext_(runningContext),
|
|
11
|
+
messageNumber_(messageNumber) {}
|
|
17
12
|
|
|
18
13
|
void EdhocComposeAsyncWorker::Execute() {
|
|
19
14
|
try {
|
|
20
|
-
|
|
15
|
+
composedMessage_.resize(kInitialBufferSize);
|
|
21
16
|
size_t composedMessageLength = 0;
|
|
22
17
|
|
|
23
18
|
int ret = EDHOC_ERROR_GENERIC_ERROR;
|
|
24
|
-
switch (
|
|
19
|
+
switch (messageNumber_) {
|
|
25
20
|
case EDHOC_MSG_1:
|
|
26
|
-
ret = edhoc_message_1_compose(
|
|
21
|
+
ret = edhoc_message_1_compose(runningContext_->GetEdhocContext(), composedMessage_.data(), composedMessage_.size(), &composedMessageLength);
|
|
27
22
|
break;
|
|
28
23
|
case EDHOC_MSG_2:
|
|
29
|
-
ret = edhoc_message_2_compose(
|
|
24
|
+
ret = edhoc_message_2_compose(runningContext_->GetEdhocContext(), composedMessage_.data(), composedMessage_.size(), &composedMessageLength);
|
|
30
25
|
break;
|
|
31
26
|
case EDHOC_MSG_3:
|
|
32
|
-
ret = edhoc_message_3_compose(
|
|
27
|
+
ret = edhoc_message_3_compose(runningContext_->GetEdhocContext(), composedMessage_.data(), composedMessage_.size(), &composedMessageLength);
|
|
33
28
|
break;
|
|
34
29
|
case EDHOC_MSG_4:
|
|
35
|
-
ret = edhoc_message_4_compose(
|
|
30
|
+
ret = edhoc_message_4_compose(runningContext_->GetEdhocContext(), composedMessage_.data(), composedMessage_.size(), &composedMessageLength);
|
|
36
31
|
break;
|
|
37
32
|
default:
|
|
38
33
|
SetError(kErrorInvalidMessageNumber);
|
|
39
34
|
return;
|
|
40
35
|
}
|
|
41
36
|
|
|
42
|
-
|
|
37
|
+
composedMessage_.resize(composedMessageLength);
|
|
43
38
|
|
|
44
39
|
if (ret != EDHOC_SUCCESS) {
|
|
45
40
|
char errorMessage[kErrorBufferSize];
|
|
46
|
-
std::snprintf(errorMessage, kErrorBufferSize, kErrorMessageFormat,
|
|
41
|
+
std::snprintf(errorMessage, kErrorBufferSize, kErrorMessageFormat, messageNumber_ + 1, ret);
|
|
47
42
|
SetError(errorMessage);
|
|
48
43
|
}
|
|
49
|
-
|
|
50
44
|
} catch (const std::exception& e) {
|
|
51
45
|
SetError(e.what());
|
|
52
46
|
}
|
|
@@ -55,17 +49,12 @@ void EdhocComposeAsyncWorker::Execute() {
|
|
|
55
49
|
void EdhocComposeAsyncWorker::OnOK() {
|
|
56
50
|
Napi::Env env = Env();
|
|
57
51
|
Napi::HandleScope scope(env);
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
runningContext_->Resolve(Napi::Buffer<uint8_t>::Copy(env, composedMessage_.data(), composedMessage_.size()));
|
|
53
|
+
runningContext_->GetEadManager()->ClearEadByMessage(static_cast<enum edhoc_message>(messageNumber_));
|
|
60
54
|
}
|
|
61
55
|
|
|
62
56
|
void EdhocComposeAsyncWorker::OnError(const Napi::Error& error) {
|
|
63
57
|
Napi::Env env = Env();
|
|
64
58
|
Napi::HandleScope scope(env);
|
|
65
|
-
|
|
66
|
-
callback(env);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
Napi::Promise EdhocComposeAsyncWorker::GetPromise() {
|
|
70
|
-
return deferred.Promise();
|
|
59
|
+
runningContext_->Reject(error.Value());
|
|
71
60
|
}
|