Add encryption support#84
Conversation
| - **Per-method failure counter.** The client maintains a failure counter for each PIN-pairing method family (`static_pin` and `dynamic_pin` tracked independently). The counter is persisted across reboots. It is not partitioned by `server_id` or source IP: a single per-method counter for the device. | ||
| - **Increment.** The counter for a method increments on each inner-authentication failure observed in that method's flow. | ||
| - **Reset.** The counter for a method resets to zero on a successful pairing finalization for that method. | ||
| - **Terminal lockout.** When a method's counter reaches **10**, the method enters a **terminal lockout** state: the client refuses all pairing attempts for that method indefinitely. Exit requires a deliberate, local operator action (manufacturer-defined), or writing `locked_out: false` for the method via [`management/set-pairing-config`](#server--client-managementset-pairing-config) from an `owner`-trust server; on successful exit the counter resets to zero. The client SHOULD surface the lockout to the operator via a device-local mechanism (LED, on-screen indicator, audible cue). If a server initiates a pairing-mode connection during terminal lockout, the client sends [`pair/abort`](#client--server-pairabort) with reason `locked_out` and closes. |
There was a problem hiding this comment.
This seams a bit dangerous if the client doesn't have an owner to reset the lockout (or the user doesn't know where to find this option).
Also not sure if this should be signaled by an LED or audible cue, especially if Sendspin isn't the only protocol implemented on the device. There will potentially be an always glowing red LED on the device until you do a factory reset.
Can we make this silent and reset on reboot? The default action is to restart hardware if something stops working.
I know that a local action must be provided by the client/device, but having to do a full reset is a pretty bad experience. And requiring manufacturers to create a Sendspin-only reset shortcut is also difficult.
There was a problem hiding this comment.
I softened the indicator requirements here.
|
|
||
| All Sendspin connections use end-to-end encryption based on the [Noise Protocol Framework](https://noiseprotocol.org/noise.html). Encryption is mandatory for all connections established through the standard discovery mechanisms described in [Establishing a Connection](#establishing-a-connection). | ||
|
|
||
| Specialized deployments where the connection is tunneled through a separately authenticated and encrypted channel may expose a non-standard endpoint that omits the Noise handshake; such endpoints must not be advertised via mDNS, and the operator is responsible for ensuring the tunnel provides equivalent security guarantees. |
There was a problem hiding this comment.
I think that we should drop this from the spec. If these kind of things are done, they are not spec compliant and it's up to the project to make sure it works.
|
|
||
| **Security properties.** Forward secrecy is provided by the ephemeral-key DH in each handshake: compromise of static keys or the PSK does not retroactively decrypt prior sessions. Replay protection is provided by Noise's per-direction transport counter; a repeated or out-of-order ciphertext fails AEAD decryption and aborts the connection. | ||
|
|
||
| ### Cipher Suites |
There was a problem hiding this comment.
Some headers have been adjusted to lowercase the 2nd word, here we capitalize 2nd word.
| Server->>Client: server/hello (name) | ||
| Client->>Server: client/hello (supported_pair_methods) | ||
| Note over Server: Operator picks dynamic PIN | ||
| Server->>Client: server/activate (activities=['pairing'], selected_pair_method=dynamic_pin) |
There was a problem hiding this comment.
why is this server/activate and not server/pair ? And if we receive that, track that current client is in pairing mode.
One thing we see by re-using server/activate for multiple purposes, is that we are including fields for one of the purpopses (ie selected_pair_method)
Paulus does not want to gate controller here.
| **Note:** Servers normally activate the client's [preferred](#priority-and-activation) version of each role, but MAY omit a role at their discretion (e.g., based on trust level, deployment context, or operator policy). Checking `active_roles` is therefore required to determine what the client may actually use on this session. | ||
|
|
||
| **Note:** Servers will always activate the client's [preferred](#priority-and-activation) version of each role. Checking `active_roles` is only necessary to detect outdated servers or confirm activation of [application-specific roles](#application-specific-roles). | ||
| **Note:** When a `server/activate` removes a role from `active_roles`, the server first sends [`stream/end`](#server--client-streamend) for any stream that role still has open, so the client never holds a live stream for an inactive role. |
There was a problem hiding this comment.
stream/end only applies to binary message roles. Should we specify roles that just send JSON; e.g., color and metadata, should clear all fields before removing those roles?
Add encryption support