edhoc 1.2.3 → 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/binding.gyp +2 -2
- 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 +2 -46
- 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 +39 -57
- package/src/EdhocCredentialManager.cpp +58 -93
- package/src/EdhocCryptoManager.cpp +181 -400
- package/src/EdhocEadManager.cpp +13 -13
- package/src/EdhocExportOscoreAsyncWorker.cpp +29 -45
- package/src/EdhocKeyExporterAsyncWorker.cpp +19 -37
- package/src/EdhocKeyUpdateAsyncWorker.cpp +15 -33
- package/src/EdhocProcessAsyncWorker.cpp +82 -96
- package/src/RunningContext.cpp +95 -0
- package/src/Utils.cpp +2 -34
- package/test/basic.test.ts +57 -3
- package/include/UserContext.h +0 -78
- package/src/LibEDHOC.cpp +0 -418
- package/test/errors.test.ts +0 -129
package/src/Utils.cpp
CHANGED
|
@@ -4,42 +4,10 @@
|
|
|
4
4
|
#include <cstring>
|
|
5
5
|
#include <mutex>
|
|
6
6
|
#include <thread>
|
|
7
|
+
#include <iostream>
|
|
7
8
|
|
|
8
|
-
static constexpr const char* kStringThen = "then";
|
|
9
9
|
static constexpr const char* kErrorInputValueMustBeANumberOrABuffer = "Input value must be a number or a buffer";
|
|
10
10
|
|
|
11
|
-
void Utils::InvokeJSFunctionWithPromiseHandling(Napi::Env env,
|
|
12
|
-
Napi::Object jsObject,
|
|
13
|
-
Napi::Function jsCallback,
|
|
14
|
-
const std::vector<napi_value>& args,
|
|
15
|
-
SuccessHandler successLambda,
|
|
16
|
-
ErrorHandler errorLambda) {
|
|
17
|
-
auto deferred = Napi::Promise::Deferred::New(env);
|
|
18
|
-
|
|
19
|
-
Napi::Value result = jsCallback.Call(jsObject, args);
|
|
20
|
-
|
|
21
|
-
if (env.IsExceptionPending()) {
|
|
22
|
-
deferred.Reject(env.GetAndClearPendingException().Value());
|
|
23
|
-
} else {
|
|
24
|
-
deferred.Resolve(result);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
auto thenCallback = Napi::Function::New(env, [successLambda, errorLambda](const Napi::CallbackInfo& info) {
|
|
28
|
-
Napi::Env env = info.Env();
|
|
29
|
-
Napi::HandleScope scope(env);
|
|
30
|
-
successLambda(env, info[0].As<Napi::Value>());
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
auto catchCallback = Napi::Function::New(env, [errorLambda](const Napi::CallbackInfo& info) {
|
|
34
|
-
Napi::Env env = info.Env();
|
|
35
|
-
Napi::HandleScope scope(env);
|
|
36
|
-
errorLambda(env, info[0].As<Napi::Error>());
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
Napi::Promise promise = deferred.Promise();
|
|
40
|
-
promise.Get(kStringThen).As<Napi::Function>().Call(promise, {thenCallback, catchCallback});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
11
|
void Utils::EncodeInt64ToBuffer(int64_t value, uint8_t* buffer, size_t* length) {
|
|
44
12
|
size_t idx = 0;
|
|
45
13
|
if (value == 0) {
|
|
@@ -71,7 +39,7 @@ struct edhoc_connection_id Utils::ConvertJsValueToEdhocCid(Napi::Value value) {
|
|
|
71
39
|
cid.bstr_length = buffer.Length();
|
|
72
40
|
memcpy(cid.bstr_value, buffer.Data(), cid.bstr_length);
|
|
73
41
|
} else {
|
|
74
|
-
Napi::TypeError::New(value.Env(), kErrorInputValueMustBeANumberOrABuffer)
|
|
42
|
+
throw Napi::TypeError::New(value.Env(), kErrorInputValueMustBeANumberOrABuffer);
|
|
75
43
|
}
|
|
76
44
|
return cid;
|
|
77
45
|
}
|
package/test/basic.test.ts
CHANGED
|
@@ -1,15 +1,40 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomBytes } from 'crypto';
|
|
2
|
+
import { EDHOC, X509CertificateCredentialManager, DefaultEdhocCryptoManager, EdhocMethod, EdhocSuite, EdhocKeyType } from '../dist/index'
|
|
2
3
|
|
|
3
4
|
describe('EDHOC Handshake', () => {
|
|
4
5
|
// Test setup variables
|
|
5
6
|
const trustedCA = Buffer.from('308201323081DAA003020102021478408C6EC18A1D452DAE70C726CB0192A6116DBB300A06082A8648CE3D040302301A3118301606035504030C0F5468697320697320434120526F6F74301E170D3234313031393138333635335A170D3235313031393138333635335A301A3118301606035504030C0F5468697320697320434120526F6F743059301306072A8648CE3D020106082A8648CE3D03010703420004B9348A8A267EF52CFDC30109A29008A2D99F6B8F78BA9EAF5D51578C06134E78CB90A073EDC2488A14174B4E2997C840C5DE7F8E35EB54A0DB6977E894D1B2CB300A06082A8648CE3D040302034700304402203B92BFEC770B0FA4E17F8F02A13CD945D914ED8123AC85C37C8C7BAA2BE3E0F102202CB2DC2EC295B5F4B7BB631ED751179C145D6B6E081559AEA38CE215369E9C31', 'hex');
|
|
6
7
|
let initiator: EDHOC;
|
|
7
8
|
let responder: EDHOC;
|
|
9
|
+
|
|
10
|
+
let staticDhKeyInitiator: Buffer;
|
|
11
|
+
let staticDhKeyResponder: Buffer;
|
|
12
|
+
|
|
13
|
+
let initiatorCredentialManager: X509CertificateCredentialManager;
|
|
14
|
+
let responderCredentialManager: X509CertificateCredentialManager;
|
|
15
|
+
|
|
16
|
+
class StaticCryptoManager extends DefaultEdhocCryptoManager {
|
|
17
|
+
|
|
18
|
+
async importKey(edhoc: EDHOC, keyType: EdhocKeyType, key: Buffer) {
|
|
19
|
+
if (keyType === EdhocKeyType.MakeKeyPair && key && edhoc.connectionID === 10) {
|
|
20
|
+
key = staticDhKeyInitiator
|
|
21
|
+
}
|
|
22
|
+
if (keyType === EdhocKeyType.MakeKeyPair && key && edhoc.connectionID === 20) {
|
|
23
|
+
key = staticDhKeyResponder
|
|
24
|
+
}
|
|
25
|
+
return super.importKey(edhoc, keyType, key);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
beforeAll(() => {
|
|
30
|
+
staticDhKeyInitiator = randomBytes(32);
|
|
31
|
+
staticDhKeyResponder = randomBytes(32);
|
|
32
|
+
})
|
|
8
33
|
|
|
9
34
|
beforeEach(() => {
|
|
10
35
|
// Initialize credentials and crypto managers for both parties
|
|
11
36
|
const initiatorKeyID = Buffer.from('00000001', 'hex');
|
|
12
|
-
|
|
37
|
+
initiatorCredentialManager = new X509CertificateCredentialManager(
|
|
13
38
|
[Buffer.from('3082012E3081D4A003020102021453423D5145C767CDC29895C3DB590192A611EA50300A06082A8648CE3D040302301A3118301606035504030C0F5468697320697320434120526F6F74301E170D3234313031393138333732345A170D3235313031393138333732345A30143112301006035504030C09696E69746961746F723059301306072A8648CE3D020106082A8648CE3D03010703420004EB0EF585F3992A1653CF310BF0F0F8035267CDAB6989C8B02E7228FBD759EF6B56263259AADF087F9849E7B7651F74C3B4F144CCCF86BB6FE2FF0EF3AA5FB5DC300A06082A8648CE3D0403020349003046022100D8C3AA7C98A730B3D4862EDAB4C1474FCD9A17A9CA3FB078914A10978FE95CC40221009F5877DD4E2C635A04ED1F6F1854C87B58521BDDFF533B1076F53D456739764C', 'hex')],
|
|
14
39
|
initiatorKeyID
|
|
15
40
|
);
|
|
@@ -19,7 +44,7 @@ describe('EDHOC Handshake', () => {
|
|
|
19
44
|
initiatorCryptoManager.addKey(initiatorKeyID, Buffer.from('DC1FBB05B6B08360CE5B9EEA08EBFBFC6766A21340641863D4C8A3F68F096337', 'hex'));
|
|
20
45
|
|
|
21
46
|
const responderKeyID = Buffer.from('00000002', 'hex');
|
|
22
|
-
|
|
47
|
+
responderCredentialManager = new X509CertificateCredentialManager(
|
|
23
48
|
[Buffer.from('3082012E3081D4A00302010202146648869E2608FC2E16D945C10E1F0192A6125CC0300A06082A8648CE3D040302301A3118301606035504030C0F5468697320697320434120526F6F74301E170D3234313031393138333735345A170D3235313031393138333735345A30143112301006035504030C09726573706F6E6465723059301306072A8648CE3D020106082A8648CE3D03010703420004161F76A7A106C9B79B7F651156B5B095E63A6101A39020F4E86DDACE61FB395E8AEF6CD9C444EE9A43DBD62DAD44FF50FE4146247D3AFD28F60DBC01FBFC573C300A06082A8648CE3D0403020349003046022100E8AD0926518CDB61E84D171700C7158FD0E72D03A117D40133ECD10F8B9F42CE022100E7E69B4C79100B3F0792F010AE11EE5DD2859C29EFC4DBCEFD41FA5CD4D3C3C9', 'hex')],
|
|
24
49
|
responderKeyID
|
|
25
50
|
);
|
|
@@ -61,4 +86,33 @@ describe('EDHOC Handshake', () => {
|
|
|
61
86
|
const responderKey = await responder.exportKey(40001, 32);
|
|
62
87
|
expect(initiatorKey).toEqual(responderKey);
|
|
63
88
|
});
|
|
89
|
+
|
|
90
|
+
test('should fail to generate message 1 twice', async () => {
|
|
91
|
+
await initiator.composeMessage1();
|
|
92
|
+
await expect(initiator.composeMessage1()).rejects.toThrow();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe('should NOT fail to generate message 1 twice', () => {
|
|
96
|
+
|
|
97
|
+
it('messages should be different', async () => {
|
|
98
|
+
const message_a = await responder.composeMessage1();
|
|
99
|
+
await responder.reset();
|
|
100
|
+
const message_b = await responder.composeMessage1();
|
|
101
|
+
expect(message_a).not.toEqual(message_b);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('messages should be the same', async () => {
|
|
105
|
+
const initiatorCryptoManager = new StaticCryptoManager();
|
|
106
|
+
const responderCryptoManager = new StaticCryptoManager();
|
|
107
|
+
|
|
108
|
+
initiator = new EDHOC(10, [EdhocMethod.Method1], [EdhocSuite.Suite2], initiatorCredentialManager, initiatorCryptoManager);
|
|
109
|
+
responder = new EDHOC(20, [EdhocMethod.Method2, EdhocMethod.Method0, EdhocMethod.Method1], [EdhocSuite.Suite2], responderCredentialManager, responderCryptoManager);
|
|
110
|
+
|
|
111
|
+
const message_a = await responder.composeMessage1();
|
|
112
|
+
await responder.reset();
|
|
113
|
+
const message_b = await responder.composeMessage1();
|
|
114
|
+
|
|
115
|
+
expect(message_a).toEqual(message_b);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
64
118
|
});
|
package/include/UserContext.h
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
#ifndef USER_CONTEXT_H
|
|
2
|
-
#define USER_CONTEXT_H
|
|
3
|
-
|
|
4
|
-
#include <napi.h>
|
|
5
|
-
|
|
6
|
-
#include <memory>
|
|
7
|
-
|
|
8
|
-
#include "EdhocCredentialManager.h"
|
|
9
|
-
#include "EdhocCryptoManager.h"
|
|
10
|
-
#include "EdhocEadManager.h"
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @class UserContext
|
|
14
|
-
* @brief Represents the user context for the Edhoc protocol.
|
|
15
|
-
*
|
|
16
|
-
* The UserContext class encapsulates the necessary components for the Edhoc
|
|
17
|
-
* protocol, including the crypto manager, EAD manager, and credential manager.
|
|
18
|
-
* It also provides access to a logger and a parent object reference.
|
|
19
|
-
*/
|
|
20
|
-
class UserContext {
|
|
21
|
-
public:
|
|
22
|
-
/**
|
|
23
|
-
* @brief Constructs a UserContext object with the specified components.
|
|
24
|
-
*
|
|
25
|
-
* @param cryptoManager The shared pointer to the EdhocCryptoManager.
|
|
26
|
-
* @param eadManager The shared pointer to the EdhocEadManager.
|
|
27
|
-
* @param credentialManager The shared pointer to the EdhocCredentialManager.
|
|
28
|
-
*/
|
|
29
|
-
UserContext(std::shared_ptr<EdhocCryptoManager> cryptoManager,
|
|
30
|
-
std::shared_ptr<EdhocEadManager> eadManager,
|
|
31
|
-
std::shared_ptr<EdhocCredentialManager> credentialManager)
|
|
32
|
-
: cryptoManager(std::move(cryptoManager)),
|
|
33
|
-
eadManager(std::move(eadManager)),
|
|
34
|
-
credentialManager(std::move(credentialManager)) {}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* @brief Destroys the UserContext object.
|
|
38
|
-
*
|
|
39
|
-
* If a logger is present, it will be released.
|
|
40
|
-
*/
|
|
41
|
-
virtual ~UserContext() {
|
|
42
|
-
if (logger) {
|
|
43
|
-
logger.Release();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @brief Gets the crypto manager associated with the UserContext.
|
|
49
|
-
*
|
|
50
|
-
* @return A pointer to the EdhocCryptoManager.
|
|
51
|
-
*/
|
|
52
|
-
EdhocCryptoManager* GetCryptoManager() const { return cryptoManager.get(); }
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @brief Gets the EAD manager associated with the UserContext.
|
|
56
|
-
*
|
|
57
|
-
* @return A pointer to the EdhocEadManager.
|
|
58
|
-
*/
|
|
59
|
-
EdhocEadManager* GetEadManager() const { return eadManager.get(); }
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @brief Gets the credential manager associated with the UserContext.
|
|
63
|
-
*
|
|
64
|
-
* @return A pointer to the EdhocCredentialManager.
|
|
65
|
-
*/
|
|
66
|
-
EdhocCredentialManager* GetCredentialManager() const { return credentialManager.get(); }
|
|
67
|
-
|
|
68
|
-
Napi::ThreadSafeFunction logger; ///< The logger for the UserContext
|
|
69
|
-
Napi::ObjectReference parent; ///< The parent object reference for the UserContext
|
|
70
|
-
Napi::Error error; ///< The last error for the UserContext
|
|
71
|
-
|
|
72
|
-
protected:
|
|
73
|
-
std::shared_ptr<EdhocCryptoManager> cryptoManager; ///< The crypto manager
|
|
74
|
-
std::shared_ptr<EdhocEadManager> eadManager; ///< The EAD manager
|
|
75
|
-
std::shared_ptr<EdhocCredentialManager> credentialManager; ///< The credential manager
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
#endif // USER_CONTEXT_H
|
package/src/LibEDHOC.cpp
DELETED
|
@@ -1,418 +0,0 @@
|
|
|
1
|
-
#include "LibEDHOC.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
|
-
static constexpr const char* kClassNameLibEDHOC = "EDHOC";
|
|
25
|
-
static constexpr const char* kMethodComposeMessage1 = "composeMessage1";
|
|
26
|
-
static constexpr const char* kMethodProcessMessage1 = "processMessage1";
|
|
27
|
-
static constexpr const char* kMethodComposeMessage2 = "composeMessage2";
|
|
28
|
-
static constexpr const char* kMethodProcessMessage2 = "processMessage2";
|
|
29
|
-
static constexpr const char* kMethodComposeMessage3 = "composeMessage3";
|
|
30
|
-
static constexpr const char* kMethodProcessMessage3 = "processMessage3";
|
|
31
|
-
static constexpr const char* kMethodComposeMessage4 = "composeMessage4";
|
|
32
|
-
static constexpr const char* kMethodProcessMessage4 = "processMessage4";
|
|
33
|
-
static constexpr const char* kMethodExportOSCORE = "exportOSCORE";
|
|
34
|
-
static constexpr const char* kMethodExportKey = "exportKey";
|
|
35
|
-
static constexpr const char* kMethodKeyUpdate = "keyUpdate";
|
|
36
|
-
static constexpr const char* kJsPropertyConnectionID = "connectionID";
|
|
37
|
-
static constexpr const char* kJsPropertyPeerConnectionID = "peerConnectionID";
|
|
38
|
-
static constexpr const char* kJsPropertyMethods = "methods";
|
|
39
|
-
static constexpr const char* kJsPropertySelectedMethod = "selectedMethod";
|
|
40
|
-
static constexpr const char* kJsPropertyCipherSuites = "cipherSuites";
|
|
41
|
-
static constexpr const char* kJsPropertySelectedCipherSuite = "selectedSuite";
|
|
42
|
-
static constexpr const char* kJsPropertyLogger = "logger";
|
|
43
|
-
static constexpr const char* kLogggerFunctionName = "Logger";
|
|
44
|
-
|
|
45
|
-
LibEDHOC::LibEDHOC(const Napi::CallbackInfo& info) : Napi::ObjectWrap<LibEDHOC>(info) {
|
|
46
|
-
Napi::Env env = info.Env();
|
|
47
|
-
Napi::HandleScope scope(env);
|
|
48
|
-
|
|
49
|
-
// Initialize EDHOC context
|
|
50
|
-
context = {};
|
|
51
|
-
if (edhoc_context_init(&context) != EDHOC_SUCCESS) {
|
|
52
|
-
Napi::TypeError::New(env, kErrorFailedToInitializeEdhocContext).ThrowAsJavaScriptException();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Connection ID, Methods, and Suites
|
|
56
|
-
SetCID(info, info[0]);
|
|
57
|
-
SetMethods(info, info[1]);
|
|
58
|
-
SetCipherSuites(info, info[2]);
|
|
59
|
-
|
|
60
|
-
// Crypto Manager
|
|
61
|
-
Napi::Object jsCryptoManager = info[4].As<Napi::Object>();
|
|
62
|
-
auto cryptoManager = std::make_shared<EdhocCryptoManager>(jsCryptoManager);
|
|
63
|
-
|
|
64
|
-
// Credentials
|
|
65
|
-
Napi::Object jsCredentialManager = info[3].As<Napi::Object>();
|
|
66
|
-
auto credentialManager = std::make_shared<EdhocCredentialManager>(jsCredentialManager);
|
|
67
|
-
// EAD
|
|
68
|
-
auto eadManager = std::make_shared<EdhocEadManager>();
|
|
69
|
-
|
|
70
|
-
// Bind all managers
|
|
71
|
-
if (edhoc_bind_keys(&context, &cryptoManager->keys) != EDHOC_SUCCESS ||
|
|
72
|
-
edhoc_bind_crypto(&context, &cryptoManager->crypto) != EDHOC_SUCCESS ||
|
|
73
|
-
edhoc_bind_credentials(&context, &credentialManager->credentials) != EDHOC_SUCCESS ||
|
|
74
|
-
edhoc_bind_ead(&context, &eadManager->ead) != EDHOC_SUCCESS) {
|
|
75
|
-
Napi::TypeError::New(env, kErrorFailedToInitializeEdhocContext).ThrowAsJavaScriptException();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Logger
|
|
79
|
-
context.logger = LibEDHOC::Logger;
|
|
80
|
-
|
|
81
|
-
// User Context
|
|
82
|
-
userContext = std::make_shared<UserContext>(cryptoManager, eadManager, credentialManager);
|
|
83
|
-
userContext->parent = Reference<Napi::Object>::New(info.This().As<Napi::Object>());
|
|
84
|
-
|
|
85
|
-
if (edhoc_set_user_context(&context, static_cast<void*>(userContext.get())) != EDHOC_SUCCESS) {
|
|
86
|
-
Napi::TypeError::New(env, kErrorFailedToInitializeEdhocContext).ThrowAsJavaScriptException();
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
LibEDHOC::~LibEDHOC() {
|
|
91
|
-
userContext.reset();
|
|
92
|
-
context = {};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
Napi::Value LibEDHOC::GetCID(const Napi::CallbackInfo& info) {
|
|
96
|
-
return Utils::CreateJsValueFromEdhocCid(info.Env(), cid);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
void LibEDHOC::SetCID(const Napi::CallbackInfo& info, const Napi::Value& value) {
|
|
100
|
-
cid = Utils::ConvertJsValueToEdhocCid(value);
|
|
101
|
-
int result = edhoc_set_connection_id(&context, &cid);
|
|
102
|
-
if (result != EDHOC_SUCCESS) {
|
|
103
|
-
Napi::TypeError::New(info.Env(), kErrorFailedToSetEdhocConnectionId).ThrowAsJavaScriptException();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
Napi::Value LibEDHOC::GetPeerCID(const Napi::CallbackInfo& info) {
|
|
108
|
-
return Utils::CreateJsValueFromEdhocCid(info.Env(), context.EDHOC_PRIVATE(peer_cid));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
Napi::Value LibEDHOC::GetMethods(const Napi::CallbackInfo& info) {
|
|
112
|
-
Napi::Env env = info.Env();
|
|
113
|
-
Napi::Array result = Napi::Array::New(env, context.EDHOC_PRIVATE(method_len));
|
|
114
|
-
for (size_t i = 0; i < context.EDHOC_PRIVATE(method_len); i++) {
|
|
115
|
-
result.Set(i, Napi::Number::New(env, context.EDHOC_PRIVATE(method)[i]));
|
|
116
|
-
}
|
|
117
|
-
return result;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
void LibEDHOC::SetMethods(const Napi::CallbackInfo& info, const Napi::Value& value) {
|
|
121
|
-
Napi::Env env = info.Env();
|
|
122
|
-
|
|
123
|
-
if (!value.IsArray()) {
|
|
124
|
-
Napi::TypeError::New(env, kErrorArrayMethodIndexesExpected).ThrowAsJavaScriptException();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const auto jsArray = value.As<Napi::Array>();
|
|
128
|
-
std::vector<edhoc_method> methods;
|
|
129
|
-
methods.reserve(jsArray.Length());
|
|
130
|
-
|
|
131
|
-
for (uint32_t i = 0; i < jsArray.Length(); i++) {
|
|
132
|
-
methods.push_back(static_cast<edhoc_method>(jsArray.Get(i).As<Napi::Number>().Int32Value()));
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (edhoc_set_methods(&context, methods.data(), methods.size()) != EDHOC_SUCCESS) {
|
|
136
|
-
Napi::TypeError::New(env, kErrorFailedToSetEdhocMethod).ThrowAsJavaScriptException();
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
Napi::Value LibEDHOC::GetSelectedMethod(const Napi::CallbackInfo& info) {
|
|
141
|
-
return Napi::Number::New(info.Env(), context.EDHOC_PRIVATE(chosen_method));
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
void LibEDHOC::SetCipherSuites(const Napi::CallbackInfo& info, const Napi::Value& value) {
|
|
145
|
-
Napi::Env env = info.Env();
|
|
146
|
-
|
|
147
|
-
if (!value.IsArray()) {
|
|
148
|
-
Napi::TypeError::New(env, kErrorArraySuiteIndexesExpected).ThrowAsJavaScriptException();
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const auto jsArray = value.As<Napi::Array>();
|
|
152
|
-
std::vector<edhoc_cipher_suite> selected_suites;
|
|
153
|
-
selected_suites.reserve(jsArray.Length());
|
|
154
|
-
|
|
155
|
-
for (uint32_t i = 0; i < jsArray.Length(); i++) {
|
|
156
|
-
const uint32_t index = jsArray.Get(i).As<Napi::Number>().Uint32Value();
|
|
157
|
-
|
|
158
|
-
if (index >= suite_pointers_count || suite_pointers[index] == nullptr) {
|
|
159
|
-
Napi::RangeError::New(env, kErrorInvalidCipherSuiteIndex).ThrowAsJavaScriptException();
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
selected_suites.push_back(*suite_pointers[index]);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (edhoc_set_cipher_suites(&context, selected_suites.data(), selected_suites.size()) != 0) {
|
|
166
|
-
Napi::TypeError::New(env, kErrorFailedToSetCipherSuites).ThrowAsJavaScriptException();
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
Napi::Value LibEDHOC::GetCipherSuites(const Napi::CallbackInfo& info) {
|
|
171
|
-
Napi::Env env = info.Env();
|
|
172
|
-
Napi::Array result = Napi::Array::New(env, context.EDHOC_PRIVATE(csuite_len));
|
|
173
|
-
for (size_t i = 0; i < context.EDHOC_PRIVATE(csuite_len); i++) {
|
|
174
|
-
result.Set(i, Napi::Number::New(env, context.EDHOC_PRIVATE(csuite)[i].value));
|
|
175
|
-
}
|
|
176
|
-
return result;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
Napi::Value LibEDHOC::GetSelectedCipherSuite(const Napi::CallbackInfo& info) {
|
|
180
|
-
Napi::Env env = info.Env();
|
|
181
|
-
Napi::Number suite =
|
|
182
|
-
Napi::Number::New(env, context.EDHOC_PRIVATE(csuite)[context.EDHOC_PRIVATE(chosen_csuite_idx)].value);
|
|
183
|
-
return suite;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
Napi::Value LibEDHOC::GetLogger(const Napi::CallbackInfo& info) {
|
|
187
|
-
return logger.Value();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
void LibEDHOC::SetLogger(const Napi::CallbackInfo& info, const Napi::Value& value) {
|
|
191
|
-
if (!info[0].IsFunction()) {
|
|
192
|
-
Napi::TypeError::New(info.Env(), kErrorExpectedAFunction).ThrowAsJavaScriptException();
|
|
193
|
-
}
|
|
194
|
-
Napi::Function jsCallback = info[0].As<Napi::Function>();
|
|
195
|
-
logger = Napi::Persistent(jsCallback);
|
|
196
|
-
userContext->logger = Napi::ThreadSafeFunction::New(info.Env(), jsCallback, kLogggerFunctionName, 0, 1);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
void LibEDHOC::Logger(void* usercontext, const char* name, const uint8_t* buffer, size_t buffer_length) {
|
|
200
|
-
auto* context = static_cast<UserContext*>(usercontext);
|
|
201
|
-
if (!context || !context->logger) {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const std::vector<uint8_t> bufferCopy(buffer, buffer + buffer_length);
|
|
206
|
-
|
|
207
|
-
context->logger.NonBlockingCall([name = std::string(name), bufferCopy](Napi::Env env, Napi::Function jsCallback) {
|
|
208
|
-
jsCallback.Call(
|
|
209
|
-
{Napi::String::New(env, name), Napi::Buffer<uint8_t>::Copy(env, bufferCopy.data(), bufferCopy.size())});
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
Napi::Value LibEDHOC::ComposeMessage(const Napi::CallbackInfo& info, enum edhoc_message messageNumber) {
|
|
214
|
-
Napi::Env env = info.Env();
|
|
215
|
-
Napi::HandleScope scope(env);
|
|
216
|
-
|
|
217
|
-
if (info[0].IsArray()) {
|
|
218
|
-
userContext->GetEadManager()->StoreEad(messageNumber, info[0].As<Napi::Array>());
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
userContext->GetCredentialManager()->SetupAsyncFunctions();
|
|
222
|
-
userContext->GetCryptoManager()->SetupAsyncFunctions();
|
|
223
|
-
|
|
224
|
-
EdhocComposeAsyncWorker::CallbackType callback = [this, messageNumber](Napi::Env& env) {
|
|
225
|
-
userContext->GetEadManager()->ClearEadByMessage(messageNumber);
|
|
226
|
-
userContext->GetCredentialManager()->CleanupAsyncFunctions();
|
|
227
|
-
userContext->GetCryptoManager()->CleanupAsyncFunctions();
|
|
228
|
-
if (!userContext->error.IsEmpty()) {
|
|
229
|
-
userContext->error.ThrowAsJavaScriptException();
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
EdhocComposeAsyncWorker* worker = new EdhocComposeAsyncWorker(env, context, messageNumber, callback);
|
|
234
|
-
worker->Queue();
|
|
235
|
-
|
|
236
|
-
return worker->GetPromise();
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
Napi::Value LibEDHOC::ProcessMessage(const Napi::CallbackInfo& info, enum edhoc_message messageNumber) {
|
|
240
|
-
Napi::Env env = info.Env();
|
|
241
|
-
Napi::HandleScope scope(env);
|
|
242
|
-
|
|
243
|
-
if (info.Length() < 1 || !info[0].IsBuffer()) {
|
|
244
|
-
Napi::TypeError::New(env, kErrorExpectedFirstArgumentToBeBuffer).ThrowAsJavaScriptException();
|
|
245
|
-
return env.Null();
|
|
246
|
-
}
|
|
247
|
-
Napi::Buffer<uint8_t> inputBuffer = info[0].As<Napi::Buffer<uint8_t>>();
|
|
248
|
-
|
|
249
|
-
userContext->GetCredentialManager()->SetupAsyncFunctions();
|
|
250
|
-
userContext->GetCryptoManager()->SetupAsyncFunctions();
|
|
251
|
-
|
|
252
|
-
EdhocProcessAsyncWorker::CallbackType callback = [this, messageNumber](Napi::Env& env) {
|
|
253
|
-
Napi::Array EADs = userContext->GetEadManager()->GetEadByMessage(env, messageNumber);
|
|
254
|
-
userContext->GetEadManager()->ClearEadByMessage(messageNumber);
|
|
255
|
-
userContext->GetCredentialManager()->CleanupAsyncFunctions();
|
|
256
|
-
userContext->GetCryptoManager()->CleanupAsyncFunctions();
|
|
257
|
-
if (!userContext->error.IsEmpty()) {
|
|
258
|
-
userContext->error.ThrowAsJavaScriptException();
|
|
259
|
-
}
|
|
260
|
-
return EADs;
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
EdhocProcessAsyncWorker* worker = new EdhocProcessAsyncWorker(env, context, messageNumber, inputBuffer, callback);
|
|
264
|
-
worker->Queue();
|
|
265
|
-
|
|
266
|
-
return worker->GetPromise();
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
Napi::Value LibEDHOC::ComposeMessage1(const Napi::CallbackInfo& info) {
|
|
270
|
-
return ComposeMessage(info, EDHOC_MSG_1);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
Napi::Value LibEDHOC::ProcessMessage1(const Napi::CallbackInfo& info) {
|
|
274
|
-
return ProcessMessage(info, EDHOC_MSG_1);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
Napi::Value LibEDHOC::ComposeMessage2(const Napi::CallbackInfo& info) {
|
|
278
|
-
return ComposeMessage(info, EDHOC_MSG_2);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
Napi::Value LibEDHOC::ProcessMessage2(const Napi::CallbackInfo& info) {
|
|
282
|
-
return ProcessMessage(info, EDHOC_MSG_2);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
Napi::Value LibEDHOC::ComposeMessage3(const Napi::CallbackInfo& info) {
|
|
286
|
-
return ComposeMessage(info, EDHOC_MSG_3);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
Napi::Value LibEDHOC::ProcessMessage3(const Napi::CallbackInfo& info) {
|
|
290
|
-
return ProcessMessage(info, EDHOC_MSG_3);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
Napi::Value LibEDHOC::ComposeMessage4(const Napi::CallbackInfo& info) {
|
|
294
|
-
return ComposeMessage(info, EDHOC_MSG_4);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
Napi::Value LibEDHOC::ProcessMessage4(const Napi::CallbackInfo& info) {
|
|
298
|
-
return ProcessMessage(info, EDHOC_MSG_4);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
Napi::Value LibEDHOC::ExportOSCORE(const Napi::CallbackInfo& info) {
|
|
302
|
-
Napi::Env env = info.Env();
|
|
303
|
-
Napi::HandleScope scope(env);
|
|
304
|
-
|
|
305
|
-
userContext->GetCredentialManager()->SetupAsyncFunctions();
|
|
306
|
-
userContext->GetCryptoManager()->SetupAsyncFunctions();
|
|
307
|
-
|
|
308
|
-
EdhocExportOscoreAsyncWorker::CallbackType callback = [this](Napi::Env& env) {
|
|
309
|
-
userContext->GetCredentialManager()->CleanupAsyncFunctions();
|
|
310
|
-
userContext->GetCryptoManager()->CleanupAsyncFunctions();
|
|
311
|
-
if (!userContext->error.IsEmpty()) {
|
|
312
|
-
userContext->error.ThrowAsJavaScriptException();
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
EdhocExportOscoreAsyncWorker* worker = new EdhocExportOscoreAsyncWorker(env, context, callback);
|
|
317
|
-
worker->Queue();
|
|
318
|
-
|
|
319
|
-
return worker->GetPromise();
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
Napi::Value LibEDHOC::ExportKey(const Napi::CallbackInfo& info) {
|
|
323
|
-
Napi::Env env = info.Env();
|
|
324
|
-
Napi::HandleScope scope(env);
|
|
325
|
-
|
|
326
|
-
if (info.Length() < 1 || !info[0].IsNumber()) {
|
|
327
|
-
Napi::TypeError::New(env, kErrorExpectedArgumentToBeNumber).ThrowAsJavaScriptException();
|
|
328
|
-
return env.Null();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (info.Length() < 2 || !info[1].IsNumber()) {
|
|
332
|
-
Napi::TypeError::New(env, kErrorExpectedArgumentToBeNumber).ThrowAsJavaScriptException();
|
|
333
|
-
return env.Null();
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
uint16_t label = (uint16_t)info[0].As<Napi::Number>().Uint32Value();
|
|
337
|
-
uint8_t desiredLength = (uint8_t)info[1].As<Napi::Number>().Uint32Value();
|
|
338
|
-
|
|
339
|
-
userContext->GetCredentialManager()->SetupAsyncFunctions();
|
|
340
|
-
userContext->GetCryptoManager()->SetupAsyncFunctions();
|
|
341
|
-
|
|
342
|
-
EdhocKeyExporterAsyncWorker::CallbackType callback = [this](Napi::Env& env) {
|
|
343
|
-
userContext->GetCredentialManager()->CleanupAsyncFunctions();
|
|
344
|
-
userContext->GetCryptoManager()->CleanupAsyncFunctions();
|
|
345
|
-
if (!userContext->error.IsEmpty()) {
|
|
346
|
-
userContext->error.ThrowAsJavaScriptException();
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
EdhocKeyExporterAsyncWorker* worker = new EdhocKeyExporterAsyncWorker(env, context, label, desiredLength, callback);
|
|
351
|
-
worker->Queue();
|
|
352
|
-
|
|
353
|
-
return worker->GetPromise();
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
Napi::Value LibEDHOC::KeyUpdate(const Napi::CallbackInfo& info) {
|
|
357
|
-
Napi::Env env = info.Env();
|
|
358
|
-
Napi::HandleScope scope(env);
|
|
359
|
-
|
|
360
|
-
if (info.Length() < 1 || !info[0].IsBuffer()) {
|
|
361
|
-
Napi::TypeError::New(env, kErrorExpectedFirstArgumentToBeBuffer).ThrowAsJavaScriptException();
|
|
362
|
-
return env.Null();
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
Napi::Buffer<uint8_t> contextBuffer = info[0].As<Napi::Buffer<uint8_t>>();
|
|
366
|
-
std::vector<uint8_t> contextBufferVector(contextBuffer.Data(), contextBuffer.Data() + contextBuffer.Length());
|
|
367
|
-
|
|
368
|
-
userContext->GetCredentialManager()->SetupAsyncFunctions();
|
|
369
|
-
userContext->GetCryptoManager()->SetupAsyncFunctions();
|
|
370
|
-
|
|
371
|
-
EdhocKeyUpdateAsyncWorker::CallbackType callback = [this](Napi::Env& env) {
|
|
372
|
-
userContext->GetCredentialManager()->CleanupAsyncFunctions();
|
|
373
|
-
userContext->GetCryptoManager()->CleanupAsyncFunctions();
|
|
374
|
-
if (!userContext->error.IsEmpty()) {
|
|
375
|
-
userContext->error.ThrowAsJavaScriptException();
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
EdhocKeyUpdateAsyncWorker* worker = new EdhocKeyUpdateAsyncWorker(env, context, contextBufferVector, callback);
|
|
380
|
-
worker->Queue();
|
|
381
|
-
|
|
382
|
-
return worker->GetPromise();
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
Napi::Object LibEDHOC::Init(Napi::Env env, Napi::Object exports) {
|
|
386
|
-
Napi::HandleScope scope(env);
|
|
387
|
-
Napi::Function func =
|
|
388
|
-
DefineClass(env, kClassNameLibEDHOC,
|
|
389
|
-
{
|
|
390
|
-
InstanceAccessor(kJsPropertyConnectionID, &LibEDHOC::GetCID, &LibEDHOC::SetCID),
|
|
391
|
-
InstanceAccessor<&LibEDHOC::GetPeerCID>(kJsPropertyPeerConnectionID),
|
|
392
|
-
InstanceAccessor(kJsPropertyMethods, &LibEDHOC::GetMethods, &LibEDHOC::SetMethods),
|
|
393
|
-
InstanceAccessor<&LibEDHOC::GetSelectedMethod>(kJsPropertySelectedMethod),
|
|
394
|
-
InstanceAccessor(kJsPropertyCipherSuites, &LibEDHOC::GetCipherSuites, &LibEDHOC::SetCipherSuites),
|
|
395
|
-
InstanceAccessor<&LibEDHOC::GetSelectedCipherSuite>(kJsPropertySelectedCipherSuite),
|
|
396
|
-
InstanceAccessor(kJsPropertyLogger, &LibEDHOC::GetLogger, &LibEDHOC::SetLogger),
|
|
397
|
-
InstanceMethod(kMethodComposeMessage1, &LibEDHOC::ComposeMessage1),
|
|
398
|
-
InstanceMethod(kMethodProcessMessage1, &LibEDHOC::ProcessMessage1),
|
|
399
|
-
InstanceMethod(kMethodComposeMessage2, &LibEDHOC::ComposeMessage2),
|
|
400
|
-
InstanceMethod(kMethodProcessMessage2, &LibEDHOC::ProcessMessage2),
|
|
401
|
-
InstanceMethod(kMethodComposeMessage3, &LibEDHOC::ComposeMessage3),
|
|
402
|
-
InstanceMethod(kMethodProcessMessage3, &LibEDHOC::ProcessMessage3),
|
|
403
|
-
InstanceMethod(kMethodComposeMessage4, &LibEDHOC::ComposeMessage4),
|
|
404
|
-
InstanceMethod(kMethodProcessMessage4, &LibEDHOC::ProcessMessage4),
|
|
405
|
-
InstanceMethod(kMethodExportOSCORE, &LibEDHOC::ExportOSCORE),
|
|
406
|
-
InstanceMethod(kMethodExportKey, &LibEDHOC::ExportKey),
|
|
407
|
-
InstanceMethod(kMethodKeyUpdate, &LibEDHOC::KeyUpdate),
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
Napi::FunctionReference* constructor = new Napi::FunctionReference();
|
|
411
|
-
*constructor = Napi::Persistent(func);
|
|
412
|
-
env.SetInstanceData(constructor);
|
|
413
|
-
|
|
414
|
-
exports.Set(kClassNameLibEDHOC, func);
|
|
415
|
-
return exports;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
NODE_API_NAMED_ADDON(addon, LibEDHOC);
|