@matter/protocol 0.15.0-alpha.0-20250613-a55f991d4 → 0.15.0-alpha.0-20250616-4b3754906
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/cjs/certificate/AttestationCertificateManager.d.ts +3 -3
- package/dist/cjs/certificate/AttestationCertificateManager.d.ts.map +1 -1
- package/dist/cjs/certificate/AttestationCertificateManager.js +12 -10
- package/dist/cjs/certificate/AttestationCertificateManager.js.map +1 -1
- package/dist/cjs/certificate/CertificateAuthority.d.ts +5 -3
- package/dist/cjs/certificate/CertificateAuthority.d.ts.map +1 -1
- package/dist/cjs/certificate/CertificateAuthority.js +19 -11
- package/dist/cjs/certificate/CertificateAuthority.js.map +1 -1
- package/dist/cjs/certificate/CertificateManager.d.ts +18 -15
- package/dist/cjs/certificate/CertificateManager.d.ts.map +1 -1
- package/dist/cjs/certificate/CertificateManager.js +92 -83
- package/dist/cjs/certificate/CertificateManager.js.map +2 -2
- package/dist/cjs/certificate/CertificationDeclarationManager.d.ts +7 -1
- package/dist/cjs/certificate/CertificationDeclarationManager.d.ts.map +1 -1
- package/dist/cjs/certificate/CertificationDeclarationManager.js +2 -2
- package/dist/cjs/certificate/CertificationDeclarationManager.js.map +1 -1
- package/dist/cjs/certificate/DeviceCertification.d.ts +2 -2
- package/dist/cjs/certificate/DeviceCertification.d.ts.map +1 -1
- package/dist/cjs/certificate/DeviceCertification.js +10 -4
- package/dist/cjs/certificate/DeviceCertification.js.map +1 -1
- package/dist/cjs/common/FailsafeContext.js +1 -1
- package/dist/cjs/common/FailsafeContext.js.map +1 -1
- package/dist/cjs/fabric/Fabric.d.ts +6 -4
- package/dist/cjs/fabric/Fabric.d.ts.map +1 -1
- package/dist/cjs/fabric/Fabric.js +33 -20
- package/dist/cjs/fabric/Fabric.js.map +1 -1
- package/dist/cjs/fabric/FabricAuthority.d.ts +1 -1
- package/dist/cjs/fabric/FabricAuthority.d.ts.map +1 -1
- package/dist/cjs/fabric/FabricAuthority.js +7 -7
- package/dist/cjs/fabric/FabricAuthority.js.map +1 -1
- package/dist/cjs/fabric/FabricManager.d.ts +3 -2
- package/dist/cjs/fabric/FabricManager.d.ts.map +1 -1
- package/dist/cjs/fabric/FabricManager.js +8 -3
- package/dist/cjs/fabric/FabricManager.js.map +1 -1
- package/dist/cjs/fabric/TestFabric.d.ts.map +1 -1
- package/dist/cjs/fabric/TestFabric.js +15 -19
- package/dist/cjs/fabric/TestFabric.js.map +1 -1
- package/dist/cjs/groups/FabricGroups.d.ts.map +1 -1
- package/dist/cjs/groups/FabricGroups.js +11 -7
- package/dist/cjs/groups/FabricGroups.js.map +1 -1
- package/dist/cjs/groups/KeySets.d.ts +2 -2
- package/dist/cjs/groups/KeySets.d.ts.map +1 -1
- package/dist/cjs/groups/KeySets.js +2 -2
- package/dist/cjs/groups/KeySets.js.map +1 -1
- package/dist/cjs/groups/MessagingState.d.ts +2 -2
- package/dist/cjs/groups/MessagingState.d.ts.map +1 -1
- package/dist/cjs/groups/MessagingState.js +4 -2
- package/dist/cjs/groups/MessagingState.js.map +1 -1
- package/dist/cjs/mdns/MdnsBroadcaster.d.ts +3 -3
- package/dist/cjs/mdns/MdnsBroadcaster.d.ts.map +1 -1
- package/dist/cjs/mdns/MdnsBroadcaster.js +7 -4
- package/dist/cjs/mdns/MdnsBroadcaster.js.map +1 -1
- package/dist/cjs/mdns/MdnsService.d.ts.map +1 -1
- package/dist/cjs/mdns/MdnsService.js +2 -1
- package/dist/cjs/mdns/MdnsService.js.map +1 -1
- package/dist/cjs/peer/ControllerCommissioner.js +1 -1
- package/dist/cjs/peer/ControllerCommissioner.js.map +1 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.d.ts +1 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.d.ts.map +1 -1
- package/dist/cjs/peer/ControllerCommissioningFlow.js +3 -4
- package/dist/cjs/peer/ControllerCommissioningFlow.js.map +1 -1
- package/dist/cjs/protocol/DeviceCommissioner.d.ts.map +1 -1
- package/dist/cjs/protocol/DeviceCommissioner.js +1 -1
- package/dist/cjs/protocol/DeviceCommissioner.js.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.d.ts +4 -2
- package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeManager.js +11 -6
- package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
- package/dist/cjs/protocol/MessageCounter.d.ts +4 -4
- package/dist/cjs/protocol/MessageCounter.d.ts.map +1 -1
- package/dist/cjs/protocol/MessageCounter.js +7 -6
- package/dist/cjs/protocol/MessageCounter.js.map +1 -1
- package/dist/cjs/session/GroupSession.d.ts.map +1 -1
- package/dist/cjs/session/GroupSession.js +7 -2
- package/dist/cjs/session/GroupSession.js.map +1 -1
- package/dist/cjs/session/InsecureSession.d.ts +2 -0
- package/dist/cjs/session/InsecureSession.d.ts.map +1 -1
- package/dist/cjs/session/InsecureSession.js +2 -2
- package/dist/cjs/session/InsecureSession.js.map +1 -1
- package/dist/cjs/session/NodeSession.d.ts +3 -1
- package/dist/cjs/session/NodeSession.d.ts.map +1 -1
- package/dist/cjs/session/NodeSession.js +21 -13
- package/dist/cjs/session/NodeSession.js.map +1 -1
- package/dist/cjs/session/SessionManager.d.ts +1 -0
- package/dist/cjs/session/SessionManager.d.ts.map +1 -1
- package/dist/cjs/session/SessionManager.js +13 -3
- package/dist/cjs/session/SessionManager.js.map +1 -1
- package/dist/cjs/session/case/CaseClient.d.ts.map +1 -1
- package/dist/cjs/session/case/CaseClient.js +16 -15
- package/dist/cjs/session/case/CaseClient.js.map +1 -1
- package/dist/cjs/session/case/CaseServer.d.ts.map +1 -1
- package/dist/cjs/session/case/CaseServer.js +22 -18
- package/dist/cjs/session/case/CaseServer.js.map +1 -1
- package/dist/cjs/session/pase/PaseClient.d.ts +4 -4
- package/dist/cjs/session/pase/PaseClient.d.ts.map +1 -1
- package/dist/cjs/session/pase/PaseClient.js +11 -9
- package/dist/cjs/session/pase/PaseClient.js.map +1 -1
- package/dist/cjs/session/pase/PaseServer.d.ts.map +1 -1
- package/dist/cjs/session/pase/PaseServer.js +6 -5
- package/dist/cjs/session/pase/PaseServer.js.map +1 -1
- package/dist/esm/certificate/AttestationCertificateManager.d.ts +3 -3
- package/dist/esm/certificate/AttestationCertificateManager.d.ts.map +1 -1
- package/dist/esm/certificate/AttestationCertificateManager.js +13 -11
- package/dist/esm/certificate/AttestationCertificateManager.js.map +1 -1
- package/dist/esm/certificate/CertificateAuthority.d.ts +5 -3
- package/dist/esm/certificate/CertificateAuthority.d.ts.map +1 -1
- package/dist/esm/certificate/CertificateAuthority.js +19 -11
- package/dist/esm/certificate/CertificateAuthority.js.map +1 -1
- package/dist/esm/certificate/CertificateManager.d.ts +18 -15
- package/dist/esm/certificate/CertificateManager.d.ts.map +1 -1
- package/dist/esm/certificate/CertificateManager.js +92 -84
- package/dist/esm/certificate/CertificateManager.js.map +2 -2
- package/dist/esm/certificate/CertificationDeclarationManager.d.ts +7 -1
- package/dist/esm/certificate/CertificationDeclarationManager.d.ts.map +1 -1
- package/dist/esm/certificate/CertificationDeclarationManager.js +2 -2
- package/dist/esm/certificate/CertificationDeclarationManager.js.map +1 -1
- package/dist/esm/certificate/DeviceCertification.d.ts +2 -2
- package/dist/esm/certificate/DeviceCertification.d.ts.map +1 -1
- package/dist/esm/certificate/DeviceCertification.js +11 -5
- package/dist/esm/certificate/DeviceCertification.js.map +1 -1
- package/dist/esm/common/FailsafeContext.js +1 -1
- package/dist/esm/common/FailsafeContext.js.map +1 -1
- package/dist/esm/fabric/Fabric.d.ts +6 -4
- package/dist/esm/fabric/Fabric.d.ts.map +1 -1
- package/dist/esm/fabric/Fabric.js +33 -21
- package/dist/esm/fabric/Fabric.js.map +1 -1
- package/dist/esm/fabric/FabricAuthority.d.ts +1 -1
- package/dist/esm/fabric/FabricAuthority.d.ts.map +1 -1
- package/dist/esm/fabric/FabricAuthority.js +8 -15
- package/dist/esm/fabric/FabricAuthority.js.map +1 -1
- package/dist/esm/fabric/FabricManager.d.ts +3 -2
- package/dist/esm/fabric/FabricManager.d.ts.map +1 -1
- package/dist/esm/fabric/FabricManager.js +9 -3
- package/dist/esm/fabric/FabricManager.js.map +1 -1
- package/dist/esm/fabric/TestFabric.d.ts.map +1 -1
- package/dist/esm/fabric/TestFabric.js +16 -20
- package/dist/esm/fabric/TestFabric.js.map +1 -1
- package/dist/esm/groups/FabricGroups.d.ts.map +1 -1
- package/dist/esm/groups/FabricGroups.js +12 -8
- package/dist/esm/groups/FabricGroups.js.map +1 -1
- package/dist/esm/groups/KeySets.d.ts +2 -2
- package/dist/esm/groups/KeySets.d.ts.map +1 -1
- package/dist/esm/groups/KeySets.js +3 -3
- package/dist/esm/groups/KeySets.js.map +1 -1
- package/dist/esm/groups/MessagingState.d.ts +2 -2
- package/dist/esm/groups/MessagingState.d.ts.map +1 -1
- package/dist/esm/groups/MessagingState.js +4 -2
- package/dist/esm/groups/MessagingState.js.map +1 -1
- package/dist/esm/mdns/MdnsBroadcaster.d.ts +3 -3
- package/dist/esm/mdns/MdnsBroadcaster.d.ts.map +1 -1
- package/dist/esm/mdns/MdnsBroadcaster.js +7 -5
- package/dist/esm/mdns/MdnsBroadcaster.js.map +1 -1
- package/dist/esm/mdns/MdnsService.d.ts.map +1 -1
- package/dist/esm/mdns/MdnsService.js +3 -1
- package/dist/esm/mdns/MdnsService.js.map +1 -1
- package/dist/esm/peer/ControllerCommissioner.js +1 -1
- package/dist/esm/peer/ControllerCommissioner.js.map +1 -1
- package/dist/esm/peer/ControllerCommissioningFlow.d.ts +1 -1
- package/dist/esm/peer/ControllerCommissioningFlow.d.ts.map +1 -1
- package/dist/esm/peer/ControllerCommissioningFlow.js +3 -5
- package/dist/esm/peer/ControllerCommissioningFlow.js.map +1 -1
- package/dist/esm/protocol/DeviceCommissioner.d.ts.map +1 -1
- package/dist/esm/protocol/DeviceCommissioner.js +1 -2
- package/dist/esm/protocol/DeviceCommissioner.js.map +1 -1
- package/dist/esm/protocol/ExchangeManager.d.ts +4 -2
- package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeManager.js +11 -6
- package/dist/esm/protocol/ExchangeManager.js.map +1 -1
- package/dist/esm/protocol/MessageCounter.d.ts +4 -4
- package/dist/esm/protocol/MessageCounter.d.ts.map +1 -1
- package/dist/esm/protocol/MessageCounter.js +8 -7
- package/dist/esm/protocol/MessageCounter.js.map +1 -1
- package/dist/esm/session/GroupSession.d.ts.map +1 -1
- package/dist/esm/session/GroupSession.js +7 -3
- package/dist/esm/session/GroupSession.js.map +1 -1
- package/dist/esm/session/InsecureSession.d.ts +2 -0
- package/dist/esm/session/InsecureSession.d.ts.map +1 -1
- package/dist/esm/session/InsecureSession.js +2 -2
- package/dist/esm/session/InsecureSession.js.map +1 -1
- package/dist/esm/session/NodeSession.d.ts +3 -1
- package/dist/esm/session/NodeSession.d.ts.map +1 -1
- package/dist/esm/session/NodeSession.js +22 -14
- package/dist/esm/session/NodeSession.js.map +1 -1
- package/dist/esm/session/SessionManager.d.ts +1 -0
- package/dist/esm/session/SessionManager.d.ts.map +1 -1
- package/dist/esm/session/SessionManager.js +13 -4
- package/dist/esm/session/SessionManager.js.map +1 -1
- package/dist/esm/session/case/CaseClient.d.ts.map +1 -1
- package/dist/esm/session/case/CaseClient.js +17 -16
- package/dist/esm/session/case/CaseClient.js.map +1 -1
- package/dist/esm/session/case/CaseServer.d.ts.map +1 -1
- package/dist/esm/session/case/CaseServer.js +23 -19
- package/dist/esm/session/case/CaseServer.js.map +1 -1
- package/dist/esm/session/pase/PaseClient.d.ts +4 -4
- package/dist/esm/session/pase/PaseClient.d.ts.map +1 -1
- package/dist/esm/session/pase/PaseClient.js +12 -10
- package/dist/esm/session/pase/PaseClient.js.map +1 -1
- package/dist/esm/session/pase/PaseServer.d.ts.map +1 -1
- package/dist/esm/session/pase/PaseServer.js +6 -6
- package/dist/esm/session/pase/PaseServer.js.map +1 -1
- package/package.json +6 -6
- package/src/certificate/AttestationCertificateManager.ts +12 -10
- package/src/certificate/CertificateAuthority.ts +20 -11
- package/src/certificate/CertificateManager.ts +77 -72
- package/src/certificate/CertificationDeclarationManager.ts +3 -3
- package/src/certificate/DeviceCertification.ts +10 -4
- package/src/common/FailsafeContext.ts +1 -1
- package/src/fabric/Fabric.ts +36 -20
- package/src/fabric/FabricAuthority.ts +8 -16
- package/src/fabric/FabricManager.ts +10 -3
- package/src/fabric/TestFabric.ts +17 -22
- package/src/groups/FabricGroups.ts +20 -8
- package/src/groups/KeySets.ts +2 -2
- package/src/groups/MessagingState.ts +6 -3
- package/src/mdns/MdnsBroadcaster.ts +11 -4
- package/src/mdns/MdnsService.ts +3 -1
- package/src/peer/ControllerCommissioner.ts +1 -1
- package/src/peer/ControllerCommissioningFlow.ts +4 -6
- package/src/protocol/DeviceCommissioner.ts +1 -2
- package/src/protocol/ExchangeManager.ts +13 -6
- package/src/protocol/MessageCounter.ts +11 -3
- package/src/session/GroupSession.ts +7 -3
- package/src/session/InsecureSession.ts +4 -3
- package/src/session/NodeSession.ts +25 -14
- package/src/session/SessionManager.ts +14 -4
- package/src/session/case/CaseClient.ts +18 -16
- package/src/session/case/CaseServer.ts +22 -17
- package/src/session/pase/PaseClient.ts +11 -9
- package/src/session/pase/PaseServer.ts +6 -5
|
@@ -30,6 +30,7 @@ export class NoAssociatedFabricError extends StatusResponseError {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export class NodeSession extends SecureSession {
|
|
33
|
+
readonly #crypto: Crypto;
|
|
33
34
|
readonly #subscriptions = new BasicSet<Subscription>();
|
|
34
35
|
#closingAfterExchangeFinished = false;
|
|
35
36
|
#sendCloseMessageWhenClosing = true;
|
|
@@ -47,6 +48,7 @@ export class NodeSession extends SecureSession {
|
|
|
47
48
|
readonly type = SessionType.Unicast;
|
|
48
49
|
|
|
49
50
|
static async create(args: {
|
|
51
|
+
crypto: Crypto;
|
|
50
52
|
manager?: SessionManager;
|
|
51
53
|
id: number;
|
|
52
54
|
fabric: Fabric | undefined;
|
|
@@ -60,6 +62,7 @@ export class NodeSession extends SecureSession {
|
|
|
60
62
|
caseAuthenticatedTags?: CaseAuthenticatedTag[];
|
|
61
63
|
}) {
|
|
62
64
|
const {
|
|
65
|
+
crypto,
|
|
63
66
|
manager,
|
|
64
67
|
id,
|
|
65
68
|
fabric,
|
|
@@ -72,7 +75,7 @@ export class NodeSession extends SecureSession {
|
|
|
72
75
|
peerSessionParameters,
|
|
73
76
|
caseAuthenticatedTags,
|
|
74
77
|
} = args;
|
|
75
|
-
const keys = await
|
|
78
|
+
const keys = await args.crypto.createHkdfKey(
|
|
76
79
|
sharedSecret,
|
|
77
80
|
salt,
|
|
78
81
|
isResumption ? SESSION_RESUMPTION_KEYS_INFO : SESSION_KEYS_INFO,
|
|
@@ -82,6 +85,7 @@ export class NodeSession extends SecureSession {
|
|
|
82
85
|
const encryptKey = isInitiator ? keys.slice(0, 16) : keys.slice(16, 32);
|
|
83
86
|
const attestationKey = keys.slice(32, 48);
|
|
84
87
|
return new NodeSession({
|
|
88
|
+
crypto,
|
|
85
89
|
manager,
|
|
86
90
|
id,
|
|
87
91
|
fabric,
|
|
@@ -97,6 +101,7 @@ export class NodeSession extends SecureSession {
|
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
constructor(args: {
|
|
104
|
+
crypto: Crypto;
|
|
100
105
|
manager?: SessionManager;
|
|
101
106
|
id: number;
|
|
102
107
|
fabric: Fabric | undefined;
|
|
@@ -109,18 +114,8 @@ export class NodeSession extends SecureSession {
|
|
|
109
114
|
caseAuthenticatedTags?: CaseAuthenticatedTag[];
|
|
110
115
|
isInitiator: boolean;
|
|
111
116
|
}) {
|
|
112
|
-
super({
|
|
113
|
-
...args,
|
|
114
|
-
setActiveTimestamp: true, // We always set the active timestamp for Secure sessions
|
|
115
|
-
// Can be changed to a PersistedMessageCounter if we implement session storage
|
|
116
|
-
messageCounter: new MessageCounter(() => {
|
|
117
|
-
// Secure Session Message Counter
|
|
118
|
-
// Expire/End the session before the counter rolls over
|
|
119
|
-
this.end(true, true).catch(error => logger.error(`Error while closing session: ${error}`));
|
|
120
|
-
}),
|
|
121
|
-
messageReceptionState: new MessageReceptionStateEncryptedWithoutRollover(),
|
|
122
|
-
});
|
|
123
117
|
const {
|
|
118
|
+
crypto,
|
|
124
119
|
manager,
|
|
125
120
|
id,
|
|
126
121
|
fabric,
|
|
@@ -133,6 +128,19 @@ export class NodeSession extends SecureSession {
|
|
|
133
128
|
isInitiator,
|
|
134
129
|
} = args;
|
|
135
130
|
|
|
131
|
+
super({
|
|
132
|
+
...args,
|
|
133
|
+
setActiveTimestamp: true, // We always set the active timestamp for Secure sessions
|
|
134
|
+
// Can be changed to a PersistedMessageCounter if we implement session storage
|
|
135
|
+
messageCounter: new MessageCounter(crypto, () => {
|
|
136
|
+
// Secure Session Message Counter
|
|
137
|
+
// Expire/End the session before the counter rolls over
|
|
138
|
+
this.end(true, true).catch(error => logger.error(`Error while closing session: ${error}`));
|
|
139
|
+
}),
|
|
140
|
+
messageReceptionState: new MessageReceptionStateEncryptedWithoutRollover(),
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
this.#crypto = crypto;
|
|
136
144
|
this.#id = id;
|
|
137
145
|
this.#fabric = fabric;
|
|
138
146
|
this.#peerNodeId = peerNodeId;
|
|
@@ -220,7 +228,7 @@ export class NodeSession extends SecureSession {
|
|
|
220
228
|
const nonce = Session.generateNonce(header.securityFlags, header.messageId, this.#peerNodeId);
|
|
221
229
|
const message = MessageCodec.decodePayload({
|
|
222
230
|
header,
|
|
223
|
-
applicationPayload:
|
|
231
|
+
applicationPayload: this.#crypto.decrypt(this.#decryptKey, applicationPayload, nonce, aad),
|
|
224
232
|
});
|
|
225
233
|
|
|
226
234
|
if (message.payloadHeader.hasSecuredExtension) {
|
|
@@ -241,7 +249,10 @@ export class NodeSession extends SecureSession {
|
|
|
241
249
|
? NodeId.UNSPECIFIED_NODE_ID
|
|
242
250
|
: (this.#fabric?.nodeId ?? NodeId.UNSPECIFIED_NODE_ID);
|
|
243
251
|
const nonce = Session.generateNonce(securityFlags, header.messageId, sessionNodeId);
|
|
244
|
-
return {
|
|
252
|
+
return {
|
|
253
|
+
header,
|
|
254
|
+
applicationPayload: this.#crypto.encrypt(this.#encryptKey, applicationPayload, nonce, headerBytes),
|
|
255
|
+
};
|
|
245
256
|
}
|
|
246
257
|
|
|
247
258
|
get attestationChallengeKey(): Uint8Array {
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
BasicSet,
|
|
11
11
|
Bytes,
|
|
12
12
|
Construction,
|
|
13
|
-
Crypto,
|
|
14
13
|
Environment,
|
|
15
14
|
Environmental,
|
|
16
15
|
Lifecycle,
|
|
@@ -124,9 +123,9 @@ export class SessionManager {
|
|
|
124
123
|
readonly #insecureSessions = new Map<NodeId, InsecureSession>();
|
|
125
124
|
readonly #sessions = new BasicSet<NodeSession>();
|
|
126
125
|
readonly #groupSessions = new Map<NodeId, BasicSet<GroupSession>>();
|
|
127
|
-
#nextSessionId
|
|
126
|
+
#nextSessionId: number;
|
|
128
127
|
#resumptionRecords = new PeerAddressMap<ResumptionRecord>();
|
|
129
|
-
readonly #globalUnencryptedMessageCounter
|
|
128
|
+
readonly #globalUnencryptedMessageCounter;
|
|
130
129
|
readonly #subscriptionsChanged = Observable<[session: NodeSession, subscription: Subscription]>();
|
|
131
130
|
#sessionParameters: SessionParameters;
|
|
132
131
|
readonly #resubmissionStarted = Observable<[session: Session]>();
|
|
@@ -137,7 +136,12 @@ export class SessionManager {
|
|
|
137
136
|
|
|
138
137
|
constructor(context: SessionManagerContext) {
|
|
139
138
|
this.#context = context;
|
|
139
|
+
const {
|
|
140
|
+
fabrics: { crypto },
|
|
141
|
+
} = context;
|
|
140
142
|
this.#sessionParameters = { ...DEFAULT_SESSION_PARAMETERS, ...context.parameters };
|
|
143
|
+
this.#nextSessionId = crypto.randomUint16;
|
|
144
|
+
this.#globalUnencryptedMessageCounter = new MessageCounter(crypto);
|
|
141
145
|
|
|
142
146
|
// When fabric is removed, also remove the resumption record
|
|
143
147
|
this.#observers.on(context.fabrics.events.deleted, async fabric => {
|
|
@@ -164,6 +168,10 @@ export class SessionManager {
|
|
|
164
168
|
return this.#context;
|
|
165
169
|
}
|
|
166
170
|
|
|
171
|
+
get crypto() {
|
|
172
|
+
return this.#context.fabrics.crypto;
|
|
173
|
+
}
|
|
174
|
+
|
|
167
175
|
/**
|
|
168
176
|
* Active secure sessions.
|
|
169
177
|
*/
|
|
@@ -242,6 +250,7 @@ export class SessionManager {
|
|
|
242
250
|
}
|
|
243
251
|
while (true) {
|
|
244
252
|
const session = new InsecureSession({
|
|
253
|
+
crypto: this.#context.fabrics.crypto,
|
|
245
254
|
manager: this,
|
|
246
255
|
messageCounter: this.#globalUnencryptedMessageCounter,
|
|
247
256
|
initiatorNodeId,
|
|
@@ -284,6 +293,7 @@ export class SessionManager {
|
|
|
284
293
|
caseAuthenticatedTags,
|
|
285
294
|
} = args;
|
|
286
295
|
const session = await NodeSession.create({
|
|
296
|
+
crypto: this.crypto,
|
|
287
297
|
manager: this,
|
|
288
298
|
id: sessionId,
|
|
289
299
|
fabric,
|
|
@@ -698,7 +708,7 @@ export class SessionManager {
|
|
|
698
708
|
*/
|
|
699
709
|
compressIdRange(upperBound: number) {
|
|
700
710
|
this.#idUpperBound = upperBound;
|
|
701
|
-
this.#nextSessionId =
|
|
711
|
+
this.#nextSessionId = this.#context.fabrics.crypto.randomUint32 % upperBound;
|
|
702
712
|
if (this.#nextSessionId === 0) this.#nextSessionId++;
|
|
703
713
|
}
|
|
704
714
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { Bytes,
|
|
7
|
+
import { Bytes, Logger, PublicKey, UnexpectedDataError } from "#general";
|
|
8
8
|
import { ChannelStatusResponseError } from "#securechannel/index.js";
|
|
9
9
|
import { SessionManager } from "#session/SessionManager.js";
|
|
10
10
|
import { NodeId, ProtocolStatusCode } from "#types";
|
|
@@ -49,11 +49,13 @@ export class CaseClient {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
async #doPair(messenger: CaseClientMessenger, exchange: MessageExchange, fabric: Fabric, peerNodeId: NodeId) {
|
|
52
|
+
const { crypto } = fabric;
|
|
53
|
+
|
|
52
54
|
// Generate pairing info
|
|
53
|
-
const initiatorRandom =
|
|
55
|
+
const initiatorRandom = crypto.randomBytes(32);
|
|
54
56
|
const initiatorSessionId = await this.#sessions.getNextAvailableSessionId(); // Initiator Session Id
|
|
55
57
|
const { operationalIdentityProtectionKey, operationalCert: localNoc, intermediateCACert: localIcac } = fabric;
|
|
56
|
-
const localKey = await
|
|
58
|
+
const localKey = await crypto.createKeyPair();
|
|
57
59
|
|
|
58
60
|
// Send sigma1
|
|
59
61
|
let sigma1Bytes;
|
|
@@ -61,12 +63,12 @@ export class CaseClient {
|
|
|
61
63
|
let resumptionRecord = this.#sessions.findResumptionRecordByAddress(fabric.addressOf(peerNodeId));
|
|
62
64
|
if (resumptionRecord !== undefined) {
|
|
63
65
|
const { sharedSecret, resumptionId } = resumptionRecord;
|
|
64
|
-
const resumeKey = await
|
|
66
|
+
const resumeKey = await crypto.createHkdfKey(
|
|
65
67
|
sharedSecret,
|
|
66
68
|
Bytes.concat(initiatorRandom, resumptionId),
|
|
67
69
|
KDFSR1_KEY_INFO,
|
|
68
70
|
);
|
|
69
|
-
const initiatorResumeMic =
|
|
71
|
+
const initiatorResumeMic = crypto.encrypt(resumeKey, new Uint8Array(0), RESUME1_MIC_NONCE);
|
|
70
72
|
sigma1Bytes = await messenger.sendSigma1({
|
|
71
73
|
initiatorSessionId,
|
|
72
74
|
destinationId: await fabric.currentDestinationIdFor(peerNodeId, initiatorRandom),
|
|
@@ -106,8 +108,8 @@ export class CaseClient {
|
|
|
106
108
|
};
|
|
107
109
|
|
|
108
110
|
const resumeSalt = Bytes.concat(initiatorRandom, resumptionId);
|
|
109
|
-
const resumeKey = await
|
|
110
|
-
|
|
111
|
+
const resumeKey = await crypto.createHkdfKey(sharedSecret, resumeSalt, KDFSR2_KEY_INFO);
|
|
112
|
+
crypto.decrypt(resumeKey, resumeMic, RESUME2_MIC_NONCE);
|
|
111
113
|
|
|
112
114
|
const secureSessionSalt = Bytes.concat(initiatorRandom, resumptionRecord.resumptionId);
|
|
113
115
|
secureSession = await this.#sessions.createSecureSession({
|
|
@@ -145,15 +147,15 @@ export class CaseClient {
|
|
|
145
147
|
...exchange.session.parameters,
|
|
146
148
|
...(responderSessionParams ?? {}),
|
|
147
149
|
};
|
|
148
|
-
const sharedSecret = await
|
|
150
|
+
const sharedSecret = await crypto.generateDhSecret(localKey, PublicKey(peerKey));
|
|
149
151
|
const sigma2Salt = Bytes.concat(
|
|
150
152
|
operationalIdentityProtectionKey,
|
|
151
153
|
responderRandom,
|
|
152
154
|
peerKey,
|
|
153
|
-
await
|
|
155
|
+
await crypto.computeSha256(sigma1Bytes),
|
|
154
156
|
);
|
|
155
|
-
const sigma2Key = await
|
|
156
|
-
const peerEncryptedData =
|
|
157
|
+
const sigma2Key = await crypto.createHkdfKey(sharedSecret, sigma2Salt, KDFSR2_INFO);
|
|
158
|
+
const peerEncryptedData = crypto.decrypt(sigma2Key, peerEncrypted, TBE_DATA2_NONCE);
|
|
157
159
|
const {
|
|
158
160
|
responderNoc: peerNoc,
|
|
159
161
|
responderIcac: peerIcac,
|
|
@@ -171,7 +173,7 @@ export class CaseClient {
|
|
|
171
173
|
subject: { fabricId: peerFabricIdNOCert, nodeId: peerNodeIdNOCert },
|
|
172
174
|
} = TlvOperationalCertificate.decode(peerNoc);
|
|
173
175
|
|
|
174
|
-
await
|
|
176
|
+
await crypto.verifyEcdsa(PublicKey(peerPublicKey), peerSignatureData, peerSignature);
|
|
175
177
|
|
|
176
178
|
if (peerNodeIdNOCert !== peerNodeId) {
|
|
177
179
|
throw new UnexpectedDataError(
|
|
@@ -199,9 +201,9 @@ export class CaseClient {
|
|
|
199
201
|
// Generate and send sigma3
|
|
200
202
|
const sigma3Salt = Bytes.concat(
|
|
201
203
|
operationalIdentityProtectionKey,
|
|
202
|
-
await
|
|
204
|
+
await crypto.computeSha256([sigma1Bytes, sigma2Bytes]),
|
|
203
205
|
);
|
|
204
|
-
const sigma3Key = await
|
|
206
|
+
const sigma3Key = await crypto.createHkdfKey(sharedSecret, sigma3Salt, KDFSR3_INFO);
|
|
205
207
|
const signatureData = TlvSignedData.encode({
|
|
206
208
|
responderNoc: localNoc,
|
|
207
209
|
responderIcac: localIcac,
|
|
@@ -214,7 +216,7 @@ export class CaseClient {
|
|
|
214
216
|
responderIcac: localIcac,
|
|
215
217
|
signature,
|
|
216
218
|
});
|
|
217
|
-
const encrypted =
|
|
219
|
+
const encrypted = crypto.encrypt(sigma3Key, encryptedData, TBE_DATA3_NONCE);
|
|
218
220
|
const sigma3Bytes = await messenger.sendSigma3({ encrypted });
|
|
219
221
|
await messenger.waitForSuccess("Sigma3-Success");
|
|
220
222
|
|
|
@@ -222,7 +224,7 @@ export class CaseClient {
|
|
|
222
224
|
const { caseAuthenticatedTags } = resumptionRecord ?? {}; // Even if resumption does not work try to reuse the caseAuthenticatedTags
|
|
223
225
|
const secureSessionSalt = Bytes.concat(
|
|
224
226
|
operationalIdentityProtectionKey,
|
|
225
|
-
await
|
|
227
|
+
await crypto.computeSha256([sigma1Bytes, sigma2Bytes, sigma3Bytes]),
|
|
226
228
|
);
|
|
227
229
|
secureSession = await this.#sessions.createSecureSession({
|
|
228
230
|
sessionId: initiatorSessionId,
|
|
@@ -73,7 +73,7 @@ export class CaseServer implements ProtocolHandler {
|
|
|
73
73
|
? this.#sessions.findResumptionRecordById(sigma1.resumptionId)
|
|
74
74
|
: undefined;
|
|
75
75
|
|
|
76
|
-
const context = new Sigma1Context(messenger, sigma1Bytes, sigma1, resumptionRecord);
|
|
76
|
+
const context = new Sigma1Context(this.#fabrics.crypto, messenger, sigma1Bytes, sigma1, resumptionRecord);
|
|
77
77
|
|
|
78
78
|
// Attempt resumption
|
|
79
79
|
if (await this.#resume(context)) {
|
|
@@ -100,14 +100,15 @@ export class CaseServer implements ProtocolHandler {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
const { sharedSecret, fabric, peerNodeId, caseAuthenticatedTags } = cx.resumptionRecord;
|
|
103
|
-
const
|
|
103
|
+
const { crypto } = this.#fabrics;
|
|
104
|
+
const peerResumeKey = await crypto.createHkdfKey(
|
|
104
105
|
sharedSecret,
|
|
105
106
|
Bytes.concat(cx.peerRandom, cx.peerResumptionId),
|
|
106
107
|
KDFSR1_KEY_INFO,
|
|
107
108
|
);
|
|
108
109
|
|
|
109
110
|
try {
|
|
110
|
-
|
|
111
|
+
crypto.decrypt(peerResumeKey, cx.peerResumeMic, RESUME1_MIC_NONCE);
|
|
111
112
|
} catch (e) {
|
|
112
113
|
CryptoDecryptError.accept(e);
|
|
113
114
|
|
|
@@ -135,8 +136,8 @@ export class CaseServer implements ProtocolHandler {
|
|
|
135
136
|
|
|
136
137
|
// Generate sigma 2 resume
|
|
137
138
|
const resumeSalt = Bytes.concat(cx.peerRandom, cx.localResumptionId);
|
|
138
|
-
const resumeKey = await
|
|
139
|
-
const resumeMic =
|
|
139
|
+
const resumeKey = await crypto.createHkdfKey(sharedSecret, resumeSalt, KDFSR2_KEY_INFO);
|
|
140
|
+
const resumeMic = crypto.encrypt(resumeKey, new Uint8Array(0), RESUME2_MIC_NONCE);
|
|
140
141
|
try {
|
|
141
142
|
await cx.messenger.sendSigma2Resume({
|
|
142
143
|
resumptionId: cx.localResumptionId,
|
|
@@ -179,22 +180,23 @@ export class CaseServer implements ProtocolHandler {
|
|
|
179
180
|
}
|
|
180
181
|
|
|
181
182
|
// Generate pairing info
|
|
182
|
-
const
|
|
183
|
+
const { crypto } = this.#fabrics;
|
|
184
|
+
const responderRandom = crypto.randomBytes(32);
|
|
183
185
|
|
|
184
186
|
// TODO: Pass through a group id?
|
|
185
187
|
const fabric = await this.#fabrics.findFabricFromDestinationId(cx.destinationId, cx.peerRandom);
|
|
186
188
|
const { operationalCert: nodeOpCert, intermediateCACert, operationalIdentityProtectionKey } = fabric;
|
|
187
|
-
const key = await
|
|
189
|
+
const key = await crypto.createKeyPair();
|
|
188
190
|
const responderEcdhPublicKey = key.publicBits;
|
|
189
|
-
const sharedSecret = await
|
|
191
|
+
const sharedSecret = await crypto.generateDhSecret(key, PublicKey(cx.peerEcdhPublicKey));
|
|
190
192
|
|
|
191
193
|
const sigma2Salt = Bytes.concat(
|
|
192
194
|
operationalIdentityProtectionKey,
|
|
193
195
|
responderRandom,
|
|
194
196
|
responderEcdhPublicKey,
|
|
195
|
-
await
|
|
197
|
+
await crypto.computeSha256(cx.bytes),
|
|
196
198
|
);
|
|
197
|
-
const sigma2Key = await
|
|
199
|
+
const sigma2Key = await crypto.createHkdfKey(sharedSecret, sigma2Salt, KDFSR2_INFO);
|
|
198
200
|
const signatureData = TlvSignedData.encode({
|
|
199
201
|
responderNoc: nodeOpCert,
|
|
200
202
|
responderIcac: intermediateCACert,
|
|
@@ -208,7 +210,7 @@ export class CaseServer implements ProtocolHandler {
|
|
|
208
210
|
signature,
|
|
209
211
|
resumptionId: cx.localResumptionId,
|
|
210
212
|
});
|
|
211
|
-
const encrypted =
|
|
213
|
+
const encrypted = crypto.encrypt(sigma2Key, encryptedData, TBE_DATA2_NONCE);
|
|
212
214
|
const responderSessionId = await this.#sessions.getNextAvailableSessionId();
|
|
213
215
|
const sigma2Bytes = await cx.messenger.sendSigma2({
|
|
214
216
|
responderRandom,
|
|
@@ -225,10 +227,10 @@ export class CaseServer implements ProtocolHandler {
|
|
|
225
227
|
} = await cx.messenger.readSigma3();
|
|
226
228
|
const sigma3Salt = Bytes.concat(
|
|
227
229
|
operationalIdentityProtectionKey,
|
|
228
|
-
await
|
|
230
|
+
await crypto.computeSha256([cx.bytes, sigma2Bytes]),
|
|
229
231
|
);
|
|
230
|
-
const sigma3Key = await
|
|
231
|
-
const peerDecryptedData =
|
|
232
|
+
const sigma3Key = await crypto.createHkdfKey(sharedSecret, sigma3Salt, KDFSR3_INFO);
|
|
233
|
+
const peerDecryptedData = crypto.decrypt(sigma3Key, peerEncrypted, TBE_DATA3_NONCE);
|
|
232
234
|
const {
|
|
233
235
|
responderNoc: peerNewOpCert,
|
|
234
236
|
responderIcac: peerIntermediateCACert,
|
|
@@ -252,12 +254,12 @@ export class CaseServer implements ProtocolHandler {
|
|
|
252
254
|
throw new UnexpectedDataError(`Fabric ID mismatch: ${fabric.fabricId} !== ${peerFabricId}`);
|
|
253
255
|
}
|
|
254
256
|
|
|
255
|
-
await
|
|
257
|
+
await crypto.verifyEcdsa(PublicKey(peerPublicKey), peerSignatureData, peerSignature);
|
|
256
258
|
|
|
257
259
|
// All good! Create secure session
|
|
258
260
|
const secureSessionSalt = Bytes.concat(
|
|
259
261
|
operationalIdentityProtectionKey,
|
|
260
|
-
await
|
|
262
|
+
await crypto.computeSha256([cx.bytes, sigma2Bytes, sigma3Bytes]),
|
|
261
263
|
);
|
|
262
264
|
const secureSession = await this.#sessions.createSecureSession({
|
|
263
265
|
sessionId: responderSessionId,
|
|
@@ -301,6 +303,7 @@ export class CaseServer implements ProtocolHandler {
|
|
|
301
303
|
}
|
|
302
304
|
|
|
303
305
|
class Sigma1Context {
|
|
306
|
+
crypto: Crypto;
|
|
304
307
|
messenger: CaseServerMessenger;
|
|
305
308
|
bytes: Uint8Array;
|
|
306
309
|
peerSessionId: number;
|
|
@@ -315,11 +318,13 @@ class Sigma1Context {
|
|
|
315
318
|
#localResumptionId?: Uint8Array;
|
|
316
319
|
|
|
317
320
|
constructor(
|
|
321
|
+
crypto: Crypto,
|
|
318
322
|
messenger: CaseServerMessenger,
|
|
319
323
|
bytes: Uint8Array,
|
|
320
324
|
sigma1: TypeFromSchema<typeof TlvCaseSigma1>,
|
|
321
325
|
resumptionRecord?: ResumptionRecord,
|
|
322
326
|
) {
|
|
327
|
+
this.crypto = crypto;
|
|
323
328
|
this.messenger = messenger;
|
|
324
329
|
this.bytes = bytes;
|
|
325
330
|
this.peerSessionId = sigma1.initiatorSessionId;
|
|
@@ -333,6 +338,6 @@ class Sigma1Context {
|
|
|
333
338
|
}
|
|
334
339
|
|
|
335
340
|
get localResumptionId() {
|
|
336
|
-
return (this.#localResumptionId ??=
|
|
341
|
+
return (this.#localResumptionId ??= this.crypto.randomBytes(16));
|
|
337
342
|
}
|
|
338
343
|
}
|
|
@@ -22,27 +22,28 @@ export class PaseClient {
|
|
|
22
22
|
this.#sessions = sessions;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
static async generatePakePasscodeVerifier(setupPinCode: number, pbkdfParameters: PbkdfParameters) {
|
|
26
|
-
const { w0, L } = await Spake2p.computeW0L(pbkdfParameters, setupPinCode);
|
|
25
|
+
static async generatePakePasscodeVerifier(crypto: Crypto, setupPinCode: number, pbkdfParameters: PbkdfParameters) {
|
|
26
|
+
const { w0, L } = await Spake2p.computeW0L(crypto, pbkdfParameters, setupPinCode);
|
|
27
27
|
return Bytes.concat(numberToBytesBE(w0, 32), L);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
static generateRandomPasscode() {
|
|
30
|
+
static generateRandomPasscode(crypto: Crypto) {
|
|
31
31
|
let passcode: number;
|
|
32
|
-
passcode = (
|
|
32
|
+
passcode = (crypto.randomUint32 % 99999998) + 1; // prevents 00000000 and 99999999
|
|
33
33
|
if (CommissioningOptions.FORBIDDEN_PASSCODES.includes(passcode)) {
|
|
34
34
|
passcode += 1; // With current forbidden passcode list can never collide
|
|
35
35
|
}
|
|
36
36
|
return passcode;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
static generateRandomDiscriminator() {
|
|
40
|
-
return
|
|
39
|
+
static generateRandomDiscriminator(crypto: Crypto) {
|
|
40
|
+
return crypto.randomUint16 % 4096;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
async pair(sessionParameters: SessionParameters, exchange: MessageExchange, setupPin: number) {
|
|
44
44
|
const messenger = new PaseClientMessenger(exchange);
|
|
45
|
-
const
|
|
45
|
+
const { crypto } = this.#sessions;
|
|
46
|
+
const initiatorRandom = crypto.randomBytes(32);
|
|
46
47
|
const initiatorSessionId = await this.#sessions.getNextAvailableSessionId(); // Initiator Session Id
|
|
47
48
|
|
|
48
49
|
// Send pbkdfRequest and Read pbkdfResponse
|
|
@@ -80,9 +81,10 @@ export class PaseClient {
|
|
|
80
81
|
};
|
|
81
82
|
|
|
82
83
|
// Compute pake1 and read pake2
|
|
83
|
-
const { w0, w1 } = await Spake2p.computeW0W1(pbkdfParameters, setupPin);
|
|
84
|
+
const { w0, w1 } = await Spake2p.computeW0W1(crypto, pbkdfParameters, setupPin);
|
|
84
85
|
const spake2p = Spake2p.create(
|
|
85
|
-
|
|
86
|
+
crypto,
|
|
87
|
+
await crypto.computeSha256([SPAKE_CONTEXT, requestPayload, responsePayload]),
|
|
86
88
|
w0,
|
|
87
89
|
);
|
|
88
90
|
const X = spake2p.computeX();
|
|
@@ -40,7 +40,7 @@ export class PaseServer implements ProtocolHandler {
|
|
|
40
40
|
#pairingErrors = 0;
|
|
41
41
|
|
|
42
42
|
static async fromPin(sessions: SessionManager, setupPinCode: number, pbkdfParameters: PbkdfParameters) {
|
|
43
|
-
const { w0, L } = await Spake2p.computeW0L(pbkdfParameters, setupPinCode);
|
|
43
|
+
const { w0, L } = await Spake2p.computeW0L(sessions.crypto, pbkdfParameters, setupPinCode);
|
|
44
44
|
return new PaseServer(sessions, w0, L, pbkdfParameters);
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -76,7 +76,7 @@ export class PaseServer implements ProtocolHandler {
|
|
|
76
76
|
);
|
|
77
77
|
} else {
|
|
78
78
|
// Ok new pairing try, handle it
|
|
79
|
-
await this.handlePairingRequest(messenger);
|
|
79
|
+
await this.handlePairingRequest(this.sessions.crypto, messenger);
|
|
80
80
|
}
|
|
81
81
|
} catch (error) {
|
|
82
82
|
this.#pairingErrors++;
|
|
@@ -100,7 +100,7 @@ export class PaseServer implements ProtocolHandler {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
private async handlePairingRequest(messenger: PaseServerMessenger) {
|
|
103
|
+
private async handlePairingRequest(crypto: Crypto, messenger: PaseServerMessenger) {
|
|
104
104
|
logger.info(`Received pairing request from ${messenger.getChannelName()}.`);
|
|
105
105
|
|
|
106
106
|
this.#pairingTimer = Time.getTimer("PASE pairing timeout", PASE_PAIRING_TIMEOUT_MS, () =>
|
|
@@ -123,7 +123,7 @@ export class PaseServer implements ProtocolHandler {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
const responderSessionId = await this.sessions.getNextAvailableSessionId(); // Responder Session Id
|
|
126
|
-
const responderRandom =
|
|
126
|
+
const responderRandom = crypto.randomBytes(32);
|
|
127
127
|
|
|
128
128
|
const responderSessionParams = this.sessions.sessionParameters;
|
|
129
129
|
const tcpSupported =
|
|
@@ -145,7 +145,8 @@ export class PaseServer implements ProtocolHandler {
|
|
|
145
145
|
|
|
146
146
|
// Process pake1 and send pake2
|
|
147
147
|
const spake2p = Spake2p.create(
|
|
148
|
-
|
|
148
|
+
crypto,
|
|
149
|
+
await crypto.computeSha256([SPAKE_CONTEXT, requestPayload, responsePayload]),
|
|
149
150
|
this.w0,
|
|
150
151
|
);
|
|
151
152
|
const { x: X } = await messenger.readPasePake1();
|