@matter/protocol 0.17.2 → 0.17.3-alpha.0-20260617-ea3690abc
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/action/client/ClientInteraction.d.ts.map +1 -1
- package/dist/cjs/action/client/ClientInteraction.js +16 -2
- package/dist/cjs/action/client/ClientInteraction.js.map +1 -1
- package/dist/cjs/action/client/ClientRequest.d.ts +8 -1
- package/dist/cjs/action/client/ClientRequest.d.ts.map +1 -1
- package/dist/cjs/action/server/AttributeReadResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/AttributeReadResponse.js +26 -12
- package/dist/cjs/action/server/AttributeReadResponse.js.map +1 -1
- package/dist/cjs/action/server/AttributeWriteResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/AttributeWriteResponse.js +27 -10
- package/dist/cjs/action/server/AttributeWriteResponse.js.map +1 -1
- package/dist/cjs/action/server/CommandInvokeResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/CommandInvokeResponse.js +27 -10
- package/dist/cjs/action/server/CommandInvokeResponse.js.map +1 -1
- package/dist/cjs/action/server/EventReadResponse.d.ts.map +1 -1
- package/dist/cjs/action/server/EventReadResponse.js +27 -10
- package/dist/cjs/action/server/EventReadResponse.js.map +1 -1
- package/dist/cjs/certificate/DeviceAttestationValidator.d.ts.map +1 -1
- package/dist/cjs/certificate/DeviceAttestationValidator.js +15 -12
- package/dist/cjs/certificate/DeviceAttestationValidator.js.map +1 -1
- package/dist/cjs/certificate/kinds/Certificate.d.ts +7 -0
- package/dist/cjs/certificate/kinds/Certificate.d.ts.map +1 -1
- package/dist/cjs/certificate/kinds/Certificate.js +30 -1
- package/dist/cjs/certificate/kinds/Certificate.js.map +1 -1
- package/dist/cjs/codec/MessagePrivacy.d.ts +1 -1
- package/dist/cjs/codec/MessagePrivacy.d.ts.map +1 -1
- package/dist/cjs/codec/MessagePrivacy.js +3 -2
- package/dist/cjs/codec/MessagePrivacy.js.map +1 -1
- package/dist/cjs/events/OccurrenceManager.d.ts +2 -2
- package/dist/cjs/events/OccurrenceManager.d.ts.map +1 -1
- package/dist/cjs/interaction/AttributeDataEncoder.d.ts.map +1 -1
- package/dist/cjs/interaction/AttributeDataEncoder.js.map +1 -1
- package/dist/cjs/peer/Peer.d.ts +5 -0
- package/dist/cjs/peer/Peer.d.ts.map +1 -1
- package/dist/cjs/peer/Peer.js +1 -0
- package/dist/cjs/peer/Peer.js.map +1 -1
- package/dist/cjs/peer/PeerConnection.d.ts +6 -1
- package/dist/cjs/peer/PeerConnection.d.ts.map +1 -1
- package/dist/cjs/peer/PeerConnection.js +23 -5
- package/dist/cjs/peer/PeerConnection.js.map +1 -1
- package/dist/cjs/peer/PeerExchangeProvider.d.ts.map +1 -1
- package/dist/cjs/peer/PeerExchangeProvider.js +3 -0
- package/dist/cjs/peer/PeerExchangeProvider.js.map +1 -1
- package/dist/cjs/peer/PeerTimingParameters.d.ts +9 -0
- package/dist/cjs/peer/PeerTimingParameters.d.ts.map +1 -1
- package/dist/cjs/peer/PeerTimingParameters.js +3 -1
- package/dist/cjs/peer/PeerTimingParameters.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/ExchangeProvider.d.ts +6 -1
- package/dist/cjs/protocol/ExchangeProvider.d.ts.map +1 -1
- package/dist/cjs/protocol/ExchangeProvider.js +4 -2
- package/dist/cjs/protocol/ExchangeProvider.js.map +1 -1
- package/dist/cjs/protocol/MRP.d.ts +1 -1
- package/dist/cjs/protocol/MRP.d.ts.map +1 -1
- package/dist/cjs/protocol/MRP.js +1 -2
- package/dist/cjs/protocol/MRP.js.map +1 -1
- package/dist/cjs/protocol/MessageExchange.d.ts +14 -1
- package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/cjs/protocol/MessageExchange.js +31 -5
- package/dist/cjs/protocol/MessageExchange.js.map +1 -1
- package/dist/cjs/session/pase/PaseClient.d.ts.map +1 -1
- package/dist/cjs/session/pase/PaseClient.js +1 -1
- 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 +11 -2
- package/dist/cjs/session/pase/PaseServer.js.map +1 -1
- package/dist/esm/action/client/ClientInteraction.d.ts.map +1 -1
- package/dist/esm/action/client/ClientInteraction.js +16 -2
- package/dist/esm/action/client/ClientInteraction.js.map +1 -1
- package/dist/esm/action/client/ClientRequest.d.ts +8 -1
- package/dist/esm/action/client/ClientRequest.d.ts.map +1 -1
- package/dist/esm/action/server/AttributeReadResponse.d.ts.map +1 -1
- package/dist/esm/action/server/AttributeReadResponse.js +27 -13
- package/dist/esm/action/server/AttributeReadResponse.js.map +1 -1
- package/dist/esm/action/server/AttributeWriteResponse.d.ts.map +1 -1
- package/dist/esm/action/server/AttributeWriteResponse.js +28 -11
- package/dist/esm/action/server/AttributeWriteResponse.js.map +1 -1
- package/dist/esm/action/server/CommandInvokeResponse.d.ts.map +1 -1
- package/dist/esm/action/server/CommandInvokeResponse.js +28 -11
- package/dist/esm/action/server/CommandInvokeResponse.js.map +1 -1
- package/dist/esm/action/server/EventReadResponse.d.ts.map +1 -1
- package/dist/esm/action/server/EventReadResponse.js +28 -11
- package/dist/esm/action/server/EventReadResponse.js.map +1 -1
- package/dist/esm/certificate/DeviceAttestationValidator.d.ts.map +1 -1
- package/dist/esm/certificate/DeviceAttestationValidator.js +16 -13
- package/dist/esm/certificate/DeviceAttestationValidator.js.map +1 -1
- package/dist/esm/certificate/kinds/Certificate.d.ts +7 -0
- package/dist/esm/certificate/kinds/Certificate.d.ts.map +1 -1
- package/dist/esm/certificate/kinds/Certificate.js +30 -1
- package/dist/esm/certificate/kinds/Certificate.js.map +1 -1
- package/dist/esm/codec/MessagePrivacy.d.ts +1 -1
- package/dist/esm/codec/MessagePrivacy.d.ts.map +1 -1
- package/dist/esm/codec/MessagePrivacy.js +4 -2
- package/dist/esm/codec/MessagePrivacy.js.map +1 -1
- package/dist/esm/events/OccurrenceManager.d.ts +2 -2
- package/dist/esm/events/OccurrenceManager.d.ts.map +1 -1
- package/dist/esm/events/OccurrenceManager.js.map +1 -1
- package/dist/esm/interaction/AttributeDataEncoder.d.ts.map +1 -1
- package/dist/esm/interaction/AttributeDataEncoder.js.map +1 -1
- package/dist/esm/peer/Peer.d.ts +5 -0
- package/dist/esm/peer/Peer.d.ts.map +1 -1
- package/dist/esm/peer/Peer.js +1 -0
- package/dist/esm/peer/Peer.js.map +1 -1
- package/dist/esm/peer/PeerConnection.d.ts +6 -1
- package/dist/esm/peer/PeerConnection.d.ts.map +1 -1
- package/dist/esm/peer/PeerConnection.js +23 -5
- package/dist/esm/peer/PeerConnection.js.map +1 -1
- package/dist/esm/peer/PeerExchangeProvider.d.ts.map +1 -1
- package/dist/esm/peer/PeerExchangeProvider.js +3 -0
- package/dist/esm/peer/PeerExchangeProvider.js.map +1 -1
- package/dist/esm/peer/PeerTimingParameters.d.ts +9 -0
- package/dist/esm/peer/PeerTimingParameters.d.ts.map +1 -1
- package/dist/esm/peer/PeerTimingParameters.js +4 -2
- package/dist/esm/peer/PeerTimingParameters.js.map +1 -1
- package/dist/esm/protocol/DeviceCommissioner.d.ts.map +1 -1
- package/dist/esm/protocol/DeviceCommissioner.js +2 -1
- package/dist/esm/protocol/DeviceCommissioner.js.map +1 -1
- package/dist/esm/protocol/ExchangeProvider.d.ts +6 -1
- package/dist/esm/protocol/ExchangeProvider.d.ts.map +1 -1
- package/dist/esm/protocol/ExchangeProvider.js +4 -2
- package/dist/esm/protocol/ExchangeProvider.js.map +1 -1
- package/dist/esm/protocol/MRP.d.ts +1 -1
- package/dist/esm/protocol/MRP.d.ts.map +1 -1
- package/dist/esm/protocol/MRP.js +1 -2
- package/dist/esm/protocol/MRP.js.map +1 -1
- package/dist/esm/protocol/MessageExchange.d.ts +14 -1
- package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
- package/dist/esm/protocol/MessageExchange.js +31 -5
- package/dist/esm/protocol/MessageExchange.js.map +1 -1
- package/dist/esm/session/pase/PaseClient.d.ts.map +1 -1
- package/dist/esm/session/pase/PaseClient.js +2 -2
- 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 +12 -2
- package/dist/esm/session/pase/PaseServer.js.map +1 -1
- package/package.json +5 -5
- package/src/action/client/ClientInteraction.ts +19 -1
- package/src/action/client/ClientRequest.ts +9 -1
- package/src/action/server/AttributeReadResponse.ts +39 -18
- package/src/action/server/AttributeWriteResponse.ts +35 -19
- package/src/action/server/CommandInvokeResponse.ts +36 -15
- package/src/action/server/EventReadResponse.ts +42 -16
- package/src/certificate/DeviceAttestationValidator.ts +17 -13
- package/src/certificate/kinds/Certificate.ts +43 -0
- package/src/codec/MessagePrivacy.ts +6 -4
- package/src/events/OccurrenceManager.ts +2 -2
- package/src/interaction/AttributeDataEncoder.ts +3 -3
- package/src/peer/Peer.ts +7 -0
- package/src/peer/PeerConnection.ts +33 -6
- package/src/peer/PeerExchangeProvider.ts +4 -0
- package/src/peer/PeerTimingParameters.ts +15 -2
- package/src/protocol/DeviceCommissioner.ts +2 -1
- package/src/protocol/ExchangeProvider.ts +12 -2
- package/src/protocol/MRP.ts +5 -6
- package/src/protocol/MessageExchange.ts +44 -6
- package/src/session/pase/PaseClient.ts +2 -6
- package/src/session/pase/PaseServer.ts +12 -2
|
@@ -11,7 +11,7 @@ import { InvokeResult } from "#action/response/InvokeResult.js";
|
|
|
11
11
|
import { AccessControl, hasRemoteActor } from "#action/server/AccessControl.js";
|
|
12
12
|
import { DataResponse, FallbackLimits } from "#action/server/DataResponse.js";
|
|
13
13
|
import { Diagnostic, InternalError, Logger } from "@matter/general";
|
|
14
|
-
import { CommandModel, DataModelPath, ElementTag, FabricIndex as FabricIndexField } from "@matter/model";
|
|
14
|
+
import { AccessLevel, CommandModel, DataModelPath, ElementTag, FabricIndex as FabricIndexField } from "@matter/model";
|
|
15
15
|
import {
|
|
16
16
|
CommandPath,
|
|
17
17
|
EndpointNumber,
|
|
@@ -214,9 +214,10 @@ export class CommandInvokeResponse<
|
|
|
214
214
|
limits = command.limits;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
//
|
|
217
|
+
// Order prescribed by core spec 8.8.3.2: an Operate-privilege pass gates element-existence disclosure,
|
|
218
|
+
// existence checks follow, then the actual-privilege pass gates the invoke.
|
|
218
219
|
// We need some fallback location if cluster is not defined
|
|
219
|
-
const location = {
|
|
220
|
+
const location: AccessControl.Location = {
|
|
220
221
|
...(cluster?.location ?? {
|
|
221
222
|
path: DataModelPath.none,
|
|
222
223
|
endpoint: endpointId,
|
|
@@ -225,20 +226,13 @@ export class CommandInvokeResponse<
|
|
|
225
226
|
owningFabric: this.session.fabric,
|
|
226
227
|
};
|
|
227
228
|
|
|
229
|
+
let access: { session: AccessControl.RemoteActorSession; location: AccessControl.Location } | undefined;
|
|
228
230
|
if (hasRemoteActor(this.session)) {
|
|
229
|
-
|
|
230
|
-
switch (permission) {
|
|
231
|
-
case AccessControl.Authority.Granted:
|
|
232
|
-
break;
|
|
231
|
+
access = { session: this.session, location };
|
|
233
232
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
case AccessControl.Authority.Restricted:
|
|
238
|
-
return this.#addStatus(path, commandRef, Status.AccessRestricted);
|
|
239
|
-
|
|
240
|
-
default:
|
|
241
|
-
throw new InternalError(`Unsupported authorization state ${permission}`);
|
|
233
|
+
const denial = this.#authorize(access.session, AccessLevel.Operate, location);
|
|
234
|
+
if (denial !== undefined) {
|
|
235
|
+
return this.#addStatus(path, commandRef, denial);
|
|
242
236
|
}
|
|
243
237
|
}
|
|
244
238
|
|
|
@@ -252,6 +246,13 @@ export class CommandInvokeResponse<
|
|
|
252
246
|
return this.#addStatus(path, commandRef, Status.UnsupportedCommand);
|
|
253
247
|
}
|
|
254
248
|
|
|
249
|
+
if (access !== undefined) {
|
|
250
|
+
const denial = this.#authorize(access.session, limits.writeLevel, access.location);
|
|
251
|
+
if (denial !== undefined) {
|
|
252
|
+
return this.#addStatus(path, commandRef, denial);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
255
256
|
if (hasRemoteActor(this.session)) {
|
|
256
257
|
if (limits.largeMessage && !this.session.largeMessage) {
|
|
257
258
|
this.#errorCount++;
|
|
@@ -369,6 +370,26 @@ export class CommandInvokeResponse<
|
|
|
369
370
|
}
|
|
370
371
|
}
|
|
371
372
|
|
|
373
|
+
/**
|
|
374
|
+
* Validate access at {@link level}. Returns undefined if granted; otherwise the status to report.
|
|
375
|
+
*/
|
|
376
|
+
#authorize(session: AccessControl.RemoteActorSession, level: AccessLevel, location: AccessControl.Location) {
|
|
377
|
+
const permission = session.authorityAt(level, location);
|
|
378
|
+
switch (permission) {
|
|
379
|
+
case AccessControl.Authority.Granted:
|
|
380
|
+
return undefined;
|
|
381
|
+
|
|
382
|
+
case AccessControl.Authority.Unauthorized:
|
|
383
|
+
return Status.UnsupportedAccess;
|
|
384
|
+
|
|
385
|
+
case AccessControl.Authority.Restricted:
|
|
386
|
+
return Status.AccessRestricted;
|
|
387
|
+
|
|
388
|
+
default:
|
|
389
|
+
throw new InternalError(`Unsupported authorization state ${permission}`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
372
393
|
#addResponse(chunk: InvokeResult.Data) {
|
|
373
394
|
if (this.#chunk) {
|
|
374
395
|
this.#chunk.push(chunk);
|
|
@@ -12,7 +12,7 @@ import { AccessControl, hasRemoteActor } from "#action/server/AccessControl.js";
|
|
|
12
12
|
import { DataResponse, FallbackLimits } from "#action/server/DataResponse.js";
|
|
13
13
|
import { NumberedOccurrence } from "#events/Occurrence.js";
|
|
14
14
|
import { InternalError, isObject, Logger } from "@matter/general";
|
|
15
|
-
import { DataModelPath, ElementTag, EventModel } from "@matter/model";
|
|
15
|
+
import { AccessLevel, DataModelPath, ElementTag, EventModel } from "@matter/model";
|
|
16
16
|
import {
|
|
17
17
|
EventNumber,
|
|
18
18
|
EventPath,
|
|
@@ -185,10 +185,12 @@ export class EventReadResponse<
|
|
|
185
185
|
limits = event.limits;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
//
|
|
189
|
-
//
|
|
188
|
+
// Order prescribed by core spec 8.4.3.2: a View-privilege pass gates element-existence disclosure,
|
|
189
|
+
// existence checks follow, then the actual-privilege pass gates the data.
|
|
190
|
+
let access: { session: AccessControl.RemoteActorSession; location: AccessControl.Location } | undefined;
|
|
190
191
|
if (hasRemoteActor(this.session)) {
|
|
191
|
-
|
|
192
|
+
// We need some fallback location if cluster is not defined
|
|
193
|
+
const location: AccessControl.Location = {
|
|
192
194
|
...(cluster?.location ?? {
|
|
193
195
|
path: DataModelPath.none,
|
|
194
196
|
endpoint: endpointId,
|
|
@@ -196,19 +198,11 @@ export class EventReadResponse<
|
|
|
196
198
|
}),
|
|
197
199
|
owningFabric: this.session.fabric,
|
|
198
200
|
};
|
|
199
|
-
|
|
200
|
-
switch (permission) {
|
|
201
|
-
case AccessControl.Authority.Granted:
|
|
202
|
-
break;
|
|
203
|
-
|
|
204
|
-
case AccessControl.Authority.Unauthorized:
|
|
205
|
-
return this.#asStatus(path, Status.UnsupportedAccess);
|
|
206
|
-
|
|
207
|
-
case AccessControl.Authority.Restricted:
|
|
208
|
-
return this.#asStatus(path, Status.AccessRestricted);
|
|
201
|
+
access = { session: this.session, location };
|
|
209
202
|
|
|
210
|
-
|
|
211
|
-
|
|
203
|
+
const denied = this.#authorize(access.session, path, AccessLevel.View, location);
|
|
204
|
+
if (denied !== undefined) {
|
|
205
|
+
return denied;
|
|
212
206
|
}
|
|
213
207
|
}
|
|
214
208
|
|
|
@@ -222,6 +216,13 @@ export class EventReadResponse<
|
|
|
222
216
|
return this.#asStatus(path, Status.UnsupportedEvent);
|
|
223
217
|
}
|
|
224
218
|
|
|
219
|
+
if (access !== undefined) {
|
|
220
|
+
const denied = this.#authorize(access.session, path, limits.readLevel, access.location);
|
|
221
|
+
if (denied !== undefined) {
|
|
222
|
+
return denied;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
225
226
|
if (this.#currentEndpoint !== endpoint) {
|
|
226
227
|
this.#currentEndpoint = endpoint;
|
|
227
228
|
this.#currentCluster = cluster;
|
|
@@ -354,6 +355,31 @@ export class EventReadResponse<
|
|
|
354
355
|
}
|
|
355
356
|
}
|
|
356
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Validate access at {@link level}. Returns undefined if granted; otherwise a status report to return.
|
|
360
|
+
*/
|
|
361
|
+
#authorize(
|
|
362
|
+
session: AccessControl.RemoteActorSession,
|
|
363
|
+
path: ReadResult.ConcreteEventPath,
|
|
364
|
+
level: AccessLevel,
|
|
365
|
+
location: AccessControl.Location,
|
|
366
|
+
) {
|
|
367
|
+
const permission = session.authorityAt(level, location);
|
|
368
|
+
switch (permission) {
|
|
369
|
+
case AccessControl.Authority.Granted:
|
|
370
|
+
return undefined;
|
|
371
|
+
|
|
372
|
+
case AccessControl.Authority.Unauthorized:
|
|
373
|
+
return this.#asStatus(path, Status.UnsupportedAccess);
|
|
374
|
+
|
|
375
|
+
case AccessControl.Authority.Restricted:
|
|
376
|
+
return this.#asStatus(path, Status.AccessRestricted);
|
|
377
|
+
|
|
378
|
+
default:
|
|
379
|
+
throw new InternalError(`Unsupported authorization state ${permission}`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
357
383
|
/**
|
|
358
384
|
* Add a status value.
|
|
359
385
|
*/
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { Bytes, Crypto, EcdsaSignature, MaybePromise, PublicKey } from "@matter/general";
|
|
7
|
+
import { Bytes, Crypto, Diagnostic, EcdsaSignature, MaybePromise, PublicKey } from "@matter/general";
|
|
8
8
|
import { MATTER_EPOCH_OFFSET_S, VendorId } from "@matter/types";
|
|
9
9
|
import { TlvAttestation } from "../common/OperationalCredentialsTypes.js";
|
|
10
10
|
import { DclCertificateService } from "../dcl/DclCertificateService.js";
|
|
@@ -59,6 +59,10 @@ export class DeviceAttestationError extends CommissioningError {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
function idHex(id?: number) {
|
|
63
|
+
return id === undefined ? "undefined" : `0x${Diagnostic.hex(id, 4).toUpperCase()}`;
|
|
64
|
+
}
|
|
65
|
+
|
|
62
66
|
export namespace DeviceAttestationValidator {
|
|
63
67
|
export interface Context {
|
|
64
68
|
crypto: Crypto;
|
|
@@ -131,7 +135,7 @@ export namespace DeviceAttestationValidator {
|
|
|
131
135
|
if (dac.cert.subject.vendorId !== pai.cert.subject.vendorId) {
|
|
132
136
|
throw new DeviceAttestationError(
|
|
133
137
|
DeviceAttestationCheck.VendorIdMismatch,
|
|
134
|
-
`DAC vendorId ${dac.cert.subject.vendorId} does not match PAI vendorId ${pai.cert.subject.vendorId}`,
|
|
138
|
+
`DAC vendorId ${idHex(dac.cert.subject.vendorId)} does not match PAI vendorId ${idHex(pai.cert.subject.vendorId)}`,
|
|
135
139
|
);
|
|
136
140
|
}
|
|
137
141
|
|
|
@@ -270,7 +274,7 @@ export namespace DeviceAttestationValidator {
|
|
|
270
274
|
if (paaVendorId !== undefined && paaVendorId !== pai.cert.subject.vendorId) {
|
|
271
275
|
throw new DeviceAttestationError(
|
|
272
276
|
DeviceAttestationCheck.VendorIdMismatch,
|
|
273
|
-
`PAA vendorId ${paaVendorId} does not match PAI vendorId ${pai.cert.subject.vendorId}`,
|
|
277
|
+
`PAA vendorId ${idHex(paaVendorId)} does not match PAI vendorId ${idHex(pai.cert.subject.vendorId)}`,
|
|
274
278
|
);
|
|
275
279
|
}
|
|
276
280
|
|
|
@@ -356,7 +360,7 @@ export namespace DeviceAttestationValidator {
|
|
|
356
360
|
if (cdContent.vendorId !== data.vendorId) {
|
|
357
361
|
throw new DeviceAttestationError(
|
|
358
362
|
DeviceAttestationCheck.CertificationDeclarationFieldMismatch,
|
|
359
|
-
`CD vendor_id ${cdContent.vendorId} does not match BasicInformation VendorID ${data.vendorId}`,
|
|
363
|
+
`CD vendor_id ${idHex(cdContent.vendorId)} does not match BasicInformation VendorID ${idHex(data.vendorId)}`,
|
|
360
364
|
);
|
|
361
365
|
}
|
|
362
366
|
|
|
@@ -364,7 +368,7 @@ export namespace DeviceAttestationValidator {
|
|
|
364
368
|
if (!cdContent.produceIdArray.includes(data.productId)) {
|
|
365
369
|
throw new DeviceAttestationError(
|
|
366
370
|
DeviceAttestationCheck.CertificationDeclarationFieldMismatch,
|
|
367
|
-
`CD product_id_array does not contain BasicInformation ProductID ${data.productId}`,
|
|
371
|
+
`CD product_id_array [${cdContent.produceIdArray.map(idHex).join(", ")}] does not contain BasicInformation ProductID ${idHex(data.productId)}`,
|
|
368
372
|
);
|
|
369
373
|
}
|
|
370
374
|
|
|
@@ -383,27 +387,27 @@ export namespace DeviceAttestationValidator {
|
|
|
383
387
|
if (dac.cert.subject.vendorId !== cdContent.dacOriginVendorId) {
|
|
384
388
|
throw new DeviceAttestationError(
|
|
385
389
|
DeviceAttestationCheck.CertificationDeclarationFieldMismatch,
|
|
386
|
-
|
|
390
|
+
`DAC vendorId ${idHex(dac.cert.subject.vendorId)} does not match CD dac_origin_vendor_id ${idHex(cdContent.dacOriginVendorId)}`,
|
|
387
391
|
);
|
|
388
392
|
}
|
|
389
393
|
if (pai.cert.subject.vendorId !== cdContent.dacOriginVendorId) {
|
|
390
394
|
throw new DeviceAttestationError(
|
|
391
395
|
DeviceAttestationCheck.CertificationDeclarationFieldMismatch,
|
|
392
|
-
|
|
396
|
+
`PAI vendorId ${idHex(pai.cert.subject.vendorId)} does not match CD dac_origin_vendor_id ${idHex(cdContent.dacOriginVendorId)}`,
|
|
393
397
|
);
|
|
394
398
|
}
|
|
395
399
|
const dacProductId = dac.cert.subject.productId;
|
|
396
400
|
if (dacProductId !== undefined && dacProductId !== cdContent.dacOriginProductId) {
|
|
397
401
|
throw new DeviceAttestationError(
|
|
398
402
|
DeviceAttestationCheck.CertificationDeclarationFieldMismatch,
|
|
399
|
-
|
|
403
|
+
`DAC productId ${idHex(dacProductId)} does not match CD dac_origin_product_id ${idHex(cdContent.dacOriginProductId)}`,
|
|
400
404
|
);
|
|
401
405
|
}
|
|
402
406
|
const paiProductId = pai.cert.subject.productId;
|
|
403
407
|
if (paiProductId !== undefined && paiProductId !== cdContent.dacOriginProductId) {
|
|
404
408
|
throw new DeviceAttestationError(
|
|
405
409
|
DeviceAttestationCheck.CertificationDeclarationFieldMismatch,
|
|
406
|
-
|
|
410
|
+
`PAI productId ${idHex(paiProductId)} does not match CD dac_origin_product_id ${idHex(cdContent.dacOriginProductId)}`,
|
|
407
411
|
);
|
|
408
412
|
}
|
|
409
413
|
} else {
|
|
@@ -411,27 +415,27 @@ export namespace DeviceAttestationValidator {
|
|
|
411
415
|
if (dac.cert.subject.vendorId !== cdContent.vendorId) {
|
|
412
416
|
throw new DeviceAttestationError(
|
|
413
417
|
DeviceAttestationCheck.CertificationDeclarationFieldMismatch,
|
|
414
|
-
|
|
418
|
+
`DAC vendorId ${idHex(dac.cert.subject.vendorId)} does not match CD vendor_id ${idHex(cdContent.vendorId)}`,
|
|
415
419
|
);
|
|
416
420
|
}
|
|
417
421
|
if (pai.cert.subject.vendorId !== cdContent.vendorId) {
|
|
418
422
|
throw new DeviceAttestationError(
|
|
419
423
|
DeviceAttestationCheck.CertificationDeclarationFieldMismatch,
|
|
420
|
-
|
|
424
|
+
`PAI vendorId ${idHex(pai.cert.subject.vendorId)} does not match CD vendor_id ${idHex(cdContent.vendorId)}`,
|
|
421
425
|
);
|
|
422
426
|
}
|
|
423
427
|
const dacProductId = dac.cert.subject.productId;
|
|
424
428
|
if (dacProductId !== undefined && !cdContent.produceIdArray.includes(dacProductId)) {
|
|
425
429
|
throw new DeviceAttestationError(
|
|
426
430
|
DeviceAttestationCheck.CertificationDeclarationFieldMismatch,
|
|
427
|
-
|
|
431
|
+
`DAC productId ${idHex(dacProductId)} not found in CD product_id_array [${cdContent.produceIdArray.map(idHex).join(", ")}]`,
|
|
428
432
|
);
|
|
429
433
|
}
|
|
430
434
|
const paiProductId = pai.cert.subject.productId;
|
|
431
435
|
if (paiProductId !== undefined && !cdContent.produceIdArray.includes(paiProductId)) {
|
|
432
436
|
throw new DeviceAttestationError(
|
|
433
437
|
DeviceAttestationCheck.CertificationDeclarationFieldMismatch,
|
|
434
|
-
|
|
438
|
+
`PAI productId ${idHex(paiProductId)} not found in CD product_id_array [${cdContent.produceIdArray.map(idHex).join(", ")}]`,
|
|
435
439
|
);
|
|
436
440
|
}
|
|
437
441
|
}
|
|
@@ -166,6 +166,23 @@ export abstract class Certificate<CT extends MatterCertificate> {
|
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Extract a VendorID or ProductID encoded via the "fallback method" (Matter spec 6.2.2.2): the
|
|
171
|
+
* prefix `Mvid:`/`Mpid:` followed by 4 uppercase hexadecimal characters, anywhere within a
|
|
172
|
+
* `commonName`. Returns the leftmost correctly-encoded value, or `undefined` if the prefix is
|
|
173
|
+
* absent. Throws if the prefix appears but no correctly-encoded value exists (spec 6.2.2.2.1).
|
|
174
|
+
*/
|
|
175
|
+
export function parseMatterFallbackVidPid(commonName: string, prefix: "Mvid:" | "Mpid:"): number | undefined {
|
|
176
|
+
const match = commonName.match(new RegExp(`${prefix}([0-9A-F]{4})`));
|
|
177
|
+
if (match !== null) {
|
|
178
|
+
return parseInt(match[1], 16);
|
|
179
|
+
}
|
|
180
|
+
if (commonName.includes(prefix)) {
|
|
181
|
+
throw new CertificateError(`commonName contains ${prefix} not followed by 4 uppercase hex digits`);
|
|
182
|
+
}
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
|
|
169
186
|
export namespace Certificate {
|
|
170
187
|
/**
|
|
171
188
|
* Create a Certificate Signing Request (CSR) in ASN.1 DER format.
|
|
@@ -285,6 +302,21 @@ export namespace Certificate {
|
|
|
285
302
|
}
|
|
286
303
|
}
|
|
287
304
|
|
|
305
|
+
// Spec 6.2.2.2: an OID VID/PID anywhere in the field disables fallback parsing for that field.
|
|
306
|
+
if (result.vendorId === undefined && result.productId === undefined) {
|
|
307
|
+
const commonName = (result.commonName ?? result.commonNamePs) as string | undefined;
|
|
308
|
+
if (commonName !== undefined) {
|
|
309
|
+
const vendorId = parseMatterFallbackVidPid(commonName, "Mvid:");
|
|
310
|
+
if (vendorId !== undefined) {
|
|
311
|
+
result.vendorId = vendorId;
|
|
312
|
+
}
|
|
313
|
+
const productId = parseMatterFallbackVidPid(commonName, "Mpid:");
|
|
314
|
+
if (productId !== undefined) {
|
|
315
|
+
result.productId = productId;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
288
320
|
return result;
|
|
289
321
|
}
|
|
290
322
|
|
|
@@ -677,10 +709,21 @@ function matterToX509(cert: Unsigned<MatterCertificate>): X509.UnsignedCertifica
|
|
|
677
709
|
*/
|
|
678
710
|
function astOfDistinguishedName(data: { [field: string]: any }) {
|
|
679
711
|
const ast = {} as { [field: string]: any[] };
|
|
712
|
+
|
|
713
|
+
// Spec 6.2.2.2 forbids mixing fallback (Mvid:/Mpid: in commonName) and OID VID/PID in one field.
|
|
714
|
+
const commonName = (data.commonName ?? data.commonNamePs) as string | undefined;
|
|
715
|
+
const usesFallbackVidPid =
|
|
716
|
+
commonName !== undefined &&
|
|
717
|
+
(parseMatterFallbackVidPid(commonName, "Mvid:") !== undefined ||
|
|
718
|
+
parseMatterFallbackVidPid(commonName, "Mpid:") !== undefined);
|
|
719
|
+
|
|
680
720
|
Object.entries(data).forEach(([key, value]) => {
|
|
681
721
|
if (value === undefined) {
|
|
682
722
|
return;
|
|
683
723
|
}
|
|
724
|
+
if (usesFallbackVidPid && (key === "vendorId" || key === "productId")) {
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
684
727
|
switch (key) {
|
|
685
728
|
case "commonName":
|
|
686
729
|
ast.commonName = X520.CommonName(value as string);
|
|
@@ -8,19 +8,21 @@ import {
|
|
|
8
8
|
Bytes,
|
|
9
9
|
Crypto,
|
|
10
10
|
CRYPTO_AEAD_MIC_LENGTH_BYTES,
|
|
11
|
+
CRYPTO_PRIVACY_NONCE_LENGTH_BYTES,
|
|
11
12
|
CRYPTO_SYMMETRIC_KEY_LENGTH,
|
|
12
13
|
CryptoInputError,
|
|
13
14
|
MaybePromise,
|
|
14
15
|
} from "@matter/general";
|
|
15
16
|
|
|
16
|
-
/** HKDF info string for deriving a privacy key from an encryption key (Matter spec §4.
|
|
17
|
+
/** HKDF info string for deriving a privacy key from an encryption key (Matter spec §4.9.1). */
|
|
17
18
|
const PRIVACY_KEY_INFO = Bytes.fromString("PrivacyKey");
|
|
18
19
|
|
|
19
|
-
const
|
|
20
|
-
const NONCE_MIC_LENGTH =
|
|
20
|
+
const NONCE_SESSION_ID_LENGTH = 2;
|
|
21
|
+
const NONCE_MIC_LENGTH = CRYPTO_PRIVACY_NONCE_LENGTH_BYTES - NONCE_SESSION_ID_LENGTH;
|
|
22
|
+
const NONCE_MIC_OFFSET = CRYPTO_AEAD_MIC_LENGTH_BYTES - NONCE_MIC_LENGTH;
|
|
21
23
|
|
|
22
24
|
/**
|
|
23
|
-
* Matter message privacy (spec §4.
|
|
25
|
+
* Matter message privacy (spec §4.9): obfuscation of the packet header for privacy-enhanced messages.
|
|
24
26
|
*/
|
|
25
27
|
export namespace MessagePrivacy {
|
|
26
28
|
/** Derive a privacy key from an encryption key: HKDF(key, salt=[], info="PrivacyKey", 16). */
|
|
@@ -18,11 +18,11 @@ import {
|
|
|
18
18
|
} from "@matter/general";
|
|
19
19
|
import {
|
|
20
20
|
EventNumber,
|
|
21
|
+
EventPath,
|
|
21
22
|
FabricIndex,
|
|
22
23
|
Priority,
|
|
23
24
|
resolveEventName,
|
|
24
25
|
TlvEventFilter,
|
|
25
|
-
TlvEventPath,
|
|
26
26
|
TypeFromSchema,
|
|
27
27
|
} from "@matter/types";
|
|
28
28
|
import { EventStore, OccurrenceSummary } from "./EventStore.js";
|
|
@@ -151,7 +151,7 @@ export class OccurrenceManager {
|
|
|
151
151
|
* @deprecated
|
|
152
152
|
*/
|
|
153
153
|
query(
|
|
154
|
-
eventPath:
|
|
154
|
+
eventPath: EventPath,
|
|
155
155
|
filters?: TypeFromSchema<typeof TlvEventFilter>[],
|
|
156
156
|
filterForFabricIndex?: FabricIndex,
|
|
157
157
|
): MaybePromise<NumberedOccurrence[]> {
|
|
@@ -7,10 +7,10 @@ import { Diagnostic, MatterFlowError } from "@matter/general";
|
|
|
7
7
|
import {
|
|
8
8
|
ArraySchema,
|
|
9
9
|
AttributeId,
|
|
10
|
+
AttributePath,
|
|
10
11
|
ClusterId,
|
|
11
12
|
EndpointNumber,
|
|
12
13
|
NodeId,
|
|
13
|
-
TlvAttributePath,
|
|
14
14
|
TlvAttributeReport,
|
|
15
15
|
TlvAttributeReportData,
|
|
16
16
|
TlvDataReport,
|
|
@@ -245,10 +245,10 @@ export function compressAttributeDataReportTags(data: AttributeReportPayload[])
|
|
|
245
245
|
|
|
246
246
|
/** Helper method to compress one path and preserve the state for the next path. */
|
|
247
247
|
function compressPath(
|
|
248
|
-
path:
|
|
248
|
+
path: AttributePath,
|
|
249
249
|
dataVersion: number | undefined,
|
|
250
250
|
lastFullPath: FullAttributePath | undefined,
|
|
251
|
-
): { path:
|
|
251
|
+
): { path: AttributePath; lastFullPath?: FullAttributePath } {
|
|
252
252
|
const { nodeId, endpointId, clusterId, attributeId } = path;
|
|
253
253
|
|
|
254
254
|
// Should never happen but typing likes it better that way
|
package/src/peer/Peer.ts
CHANGED
|
@@ -579,6 +579,7 @@ export class Peer {
|
|
|
579
579
|
|
|
580
580
|
done: PeerConnection(this, this.#context, {
|
|
581
581
|
network: options?.network,
|
|
582
|
+
additionalMrpDelay: options?.additionalMrpDelay,
|
|
582
583
|
timing: options?.timing,
|
|
583
584
|
requiredTransport: options?.requiredTransport,
|
|
584
585
|
preferredTransport: options?.preferredTransport,
|
|
@@ -621,6 +622,12 @@ export namespace Peer {
|
|
|
621
622
|
*/
|
|
622
623
|
network?: string;
|
|
623
624
|
|
|
625
|
+
/**
|
|
626
|
+
* Per-call override for the peer-medium MRP retransmission margin. When omitted the margin derives from
|
|
627
|
+
* the peer's network medium, independent of any {@link network} throttle override.
|
|
628
|
+
*/
|
|
629
|
+
additionalMrpDelay?: Duration;
|
|
630
|
+
|
|
624
631
|
/**
|
|
625
632
|
* A timeout relative to beginning of connection process.
|
|
626
633
|
*
|
|
@@ -109,6 +109,9 @@ export async function PeerConnection(
|
|
|
109
109
|
|
|
110
110
|
// Reserve network communication slot
|
|
111
111
|
let network = context.networks.select(peer, options?.network);
|
|
112
|
+
const mediumProfile = context.networks.forPeer(peer);
|
|
113
|
+
const peerAdditionalMrpDelay =
|
|
114
|
+
options?.additionalMrpDelay ?? mediumProfile.connect?.additionalMrpDelay ?? mediumProfile.additionalMrpDelay;
|
|
112
115
|
if (network.connect) {
|
|
113
116
|
network = network.connect;
|
|
114
117
|
}
|
|
@@ -303,8 +306,7 @@ export async function PeerConnection(
|
|
|
303
306
|
return;
|
|
304
307
|
}
|
|
305
308
|
const variants = expandAddresses(fallback);
|
|
306
|
-
//
|
|
307
|
-
// must match what comes back out of pendingAddresses.
|
|
309
|
+
// Intern so attempts/pendingAddresses key on one canonical object; fallback identity is matched by value.
|
|
308
310
|
attemptingFallback = addresses.add(variants[0]);
|
|
309
311
|
for (const variant of variants) {
|
|
310
312
|
pendingAddresses.add(variant);
|
|
@@ -406,7 +408,7 @@ export async function PeerConnection(
|
|
|
406
408
|
|
|
407
409
|
// If this is not the fallback address but we're still attempting to connect to the fallback, it means that
|
|
408
410
|
// we've discovered addresses that do not include the fallback; terminate the fallback attempt
|
|
409
|
-
if (attemptingFallback && address
|
|
411
|
+
if (attemptingFallback && !ServerAddress.isEqual(address, attemptingFallback)) {
|
|
410
412
|
deleteAddress(
|
|
411
413
|
attemptingFallback,
|
|
412
414
|
"Aborting attempt to last known address because device reports address change",
|
|
@@ -456,7 +458,13 @@ export async function PeerConnection(
|
|
|
456
458
|
isInitiator: true,
|
|
457
459
|
});
|
|
458
460
|
|
|
459
|
-
await using exchange = PeerConnection.createExchange(
|
|
461
|
+
await using exchange = PeerConnection.createExchange(
|
|
462
|
+
peer,
|
|
463
|
+
context.exchanges,
|
|
464
|
+
unsecuredSession,
|
|
465
|
+
network,
|
|
466
|
+
peerAdditionalMrpDelay,
|
|
467
|
+
);
|
|
460
468
|
|
|
461
469
|
info(
|
|
462
470
|
Diagnostic.via(`${peer.address.toString()}${exchange.via}`),
|
|
@@ -470,7 +478,7 @@ export async function PeerConnection(
|
|
|
470
478
|
}),
|
|
471
479
|
Diagnostic.asFlags({
|
|
472
480
|
[network.id]: true,
|
|
473
|
-
fallback: address
|
|
481
|
+
fallback: attemptingFallback !== undefined && ServerAddress.isEqual(address, attemptingFallback),
|
|
474
482
|
}),
|
|
475
483
|
);
|
|
476
484
|
|
|
@@ -492,6 +500,11 @@ export async function PeerConnection(
|
|
|
492
500
|
return;
|
|
493
501
|
}
|
|
494
502
|
|
|
503
|
+
if (exchange.retransmissionRestartSaving < context.timing.kickMinRestartSaving) {
|
|
504
|
+
debug(via, address, `Suppressing "${origin}" kick, restart would save too little time`);
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
|
|
495
508
|
const threshold =
|
|
496
509
|
origin === "discover"
|
|
497
510
|
? context.timing.kickRestartCooldown.addressChange
|
|
@@ -691,6 +704,13 @@ export namespace PeerConnection {
|
|
|
691
704
|
export interface Options {
|
|
692
705
|
abort?: AbortSignal;
|
|
693
706
|
network?: string;
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Per-call override for the peer-medium MRP retransmission margin. When omitted the margin derives from
|
|
710
|
+
* the peer's network medium, independent of any {@link network} throttle override.
|
|
711
|
+
*/
|
|
712
|
+
additionalMrpDelay?: Duration;
|
|
713
|
+
|
|
694
714
|
kicker?: Observable<[KickOrigin]>;
|
|
695
715
|
|
|
696
716
|
/** See {@link Peer.ConnectOptions.requiredTransport}. */
|
|
@@ -718,10 +738,17 @@ export namespace PeerConnection {
|
|
|
718
738
|
exchanges: ExchangeManager,
|
|
719
739
|
session: Session,
|
|
720
740
|
network: NetworkProfile,
|
|
741
|
+
peerAdditionalMrpDelay?: Duration,
|
|
721
742
|
protocol = SECURE_CHANNEL_PROTOCOL_ID,
|
|
722
743
|
addressOverride?: ServerAddressUdp,
|
|
723
744
|
) {
|
|
724
|
-
return exchanges.initiateExchangeForSession(session, protocol, {
|
|
745
|
+
return exchanges.initiateExchangeForSession(session, protocol, {
|
|
746
|
+
onSend,
|
|
747
|
+
onReceive,
|
|
748
|
+
network,
|
|
749
|
+
peerAdditionalMrpDelay,
|
|
750
|
+
addressOverride,
|
|
751
|
+
});
|
|
725
752
|
|
|
726
753
|
function onSend(_message: Message, retransmission: number) {
|
|
727
754
|
if (retransmission) {
|
|
@@ -51,6 +51,7 @@ export class PeerExchangeProvider extends ExchangeProvider {
|
|
|
51
51
|
await this.#peer.connect({
|
|
52
52
|
abort: options?.abort,
|
|
53
53
|
network: options?.network,
|
|
54
|
+
additionalMrpDelay: options?.additionalMrpDelay,
|
|
54
55
|
connectionTimeout: options?.connectionTimeout,
|
|
55
56
|
requiredTransport: options?.requiredTransport,
|
|
56
57
|
preferredTransport: options?.preferredTransport,
|
|
@@ -72,6 +73,8 @@ export class PeerExchangeProvider extends ExchangeProvider {
|
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
const network = this.#context.networks.select(this.#peer, options?.network);
|
|
76
|
+
const peerAdditionalMrpDelay =
|
|
77
|
+
options?.additionalMrpDelay ?? this.#context.networks.forPeer(this.#peer).additionalMrpDelay;
|
|
75
78
|
const slot = await network.semaphore.obtainSlot(abort);
|
|
76
79
|
|
|
77
80
|
try {
|
|
@@ -112,6 +115,7 @@ export class PeerExchangeProvider extends ExchangeProvider {
|
|
|
112
115
|
this.#context.exchanges,
|
|
113
116
|
session,
|
|
114
117
|
network,
|
|
118
|
+
peerAdditionalMrpDelay,
|
|
115
119
|
options?.protocol ?? INTERACTION_PROTOCOL_ID,
|
|
116
120
|
options?.addressOverride,
|
|
117
121
|
);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { Duration, merge as mergeObjects, Minutes, Seconds } from "@matter/general";
|
|
7
|
+
import { Duration, merge as mergeObjects, Millis, Minutes, Seconds } from "@matter/general";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Parameters that control network timing for Matter sessions controlled by matter.js.
|
|
@@ -72,6 +72,16 @@ export interface PeerTimingParameters {
|
|
|
72
72
|
*/
|
|
73
73
|
kickMinRetransmissions: number;
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Minimum time a kick-initiated restart must shave off the next retransmission to be worthwhile.
|
|
77
|
+
*
|
|
78
|
+
* Restarting resets MRP backoff to its base interval, so it only helps once backoff has grown well
|
|
79
|
+
* beyond that base. A kick whose restart would save less than this is suppressed — for an idle/sleepy
|
|
80
|
+
* peer the base interval is already large, so a restart gains nothing and needlessly tears down the
|
|
81
|
+
* in-flight exchange.
|
|
82
|
+
*/
|
|
83
|
+
kickMinRestartSaving: Duration;
|
|
84
|
+
|
|
75
85
|
/**
|
|
76
86
|
* Per-trigger cooldowns for kick-initiated CASE exchange restarts.
|
|
77
87
|
*
|
|
@@ -151,10 +161,12 @@ export namespace PeerTimingParameters {
|
|
|
151
161
|
return result;
|
|
152
162
|
}
|
|
153
163
|
|
|
164
|
+
const maxInitialContactRetryInterval = Minutes(2);
|
|
165
|
+
|
|
154
166
|
// TODO - tune these
|
|
155
167
|
export const defaults: PeerTimingParameters = {
|
|
156
168
|
defaultConnectionTimeout: Seconds(90),
|
|
157
|
-
maxDelayBetweenInitialContactRetries:
|
|
169
|
+
maxDelayBetweenInitialContactRetries: maxInitialContactRetryInterval,
|
|
158
170
|
|
|
159
171
|
// We assume 30s processing time on peer for single Sigma actions, so give one IP a bit of time
|
|
160
172
|
// to have a chance before potentially adding a load with a second try
|
|
@@ -164,6 +176,7 @@ export namespace PeerTimingParameters {
|
|
|
164
176
|
delayAfterUnhandledError: Minutes(2),
|
|
165
177
|
kickThrottleInterval: Seconds(3),
|
|
166
178
|
kickMinRetransmissions: 2,
|
|
179
|
+
kickMinRestartSaving: Millis(maxInitialContactRetryInterval / 2),
|
|
167
180
|
kickRestartCooldown: {
|
|
168
181
|
addressChange: Minutes(30),
|
|
169
182
|
connect: Minutes(10),
|
|
@@ -12,6 +12,7 @@ import { SecureChannelProtocol } from "#securechannel/SecureChannelProtocol.js";
|
|
|
12
12
|
import { PaseServer } from "#session/pase/PaseServer.js";
|
|
13
13
|
import { SessionManager } from "#session/SessionManager.js";
|
|
14
14
|
import {
|
|
15
|
+
CRYPTO_PBKDF_ITERATIONS_MIN,
|
|
15
16
|
Environment,
|
|
16
17
|
Environmental,
|
|
17
18
|
InternalError,
|
|
@@ -117,7 +118,7 @@ export class DeviceCommissioner {
|
|
|
117
118
|
|
|
118
119
|
this.#context.secureChannelProtocol.setPaseCommissioner(
|
|
119
120
|
await PaseServer.fromPin(this.#context.sessions, this.#context.commissioningConfig.values.passcode, {
|
|
120
|
-
iterations:
|
|
121
|
+
iterations: CRYPTO_PBKDF_ITERATIONS_MIN,
|
|
121
122
|
salt: this.#context.fabrics.crypto.randomBytes(32),
|
|
122
123
|
}),
|
|
123
124
|
);
|