From be844485553c66a9d257e0a5b01027b716e1e307 Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Wed, 21 May 2025 15:08:24 +0200 Subject: [PATCH] api/firmware: add option to skip noise pairing confirmation When communicating over a secure paired Bluetooth connection, we don't need a noise pairing confirmation, as Bluetooth has its own. This does not prevent one from displaying the pairing code at any time after, but it allows starting communicating without an explicit pairing code confirmation. --- api/firmware/device.go | 8 ++++++++ api/firmware/options.go | 35 +++++++++++++++++++++++++++++++++++ api/firmware/pairing.go | 3 +-- 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 api/firmware/options.go diff --git a/api/firmware/device.go b/api/firmware/device.go index 4db88ca..e7172c0 100644 --- a/api/firmware/device.go +++ b/api/firmware/device.go @@ -108,6 +108,8 @@ type Device struct { mu sync.RWMutex onEvent func(Event, interface{}) log Logger + + options *deviceOptions } // BluetoothInfo contains Bluetooth-related info. @@ -144,10 +146,15 @@ func NewDevice( config ConfigInterface, communication Communication, log Logger, + opts ...DeviceOption, ) *Device { if (version == nil) != (product == nil) { panic("both version and product have to be specified, or none") } + options := &deviceOptions{} + for _, opt := range opts { + opt(options) + } return &Device{ communication: communication, version: version, @@ -155,6 +162,7 @@ func NewDevice( config: config, status: StatusConnected, log: log, + options: options, } } diff --git a/api/firmware/options.go b/api/firmware/options.go new file mode 100644 index 0000000..3a3112a --- /dev/null +++ b/api/firmware/options.go @@ -0,0 +1,35 @@ +// Copyright 2025 Shift Crypto AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package firmware + +type deviceOptions struct { + // If true, the host does not require noise pairing confirmation before communicating over the + // encrypted noise channel. + optionalNoisePairingConfirmation bool +} + +// DeviceOption provides functional options. +type DeviceOption func(*deviceOptions) + +// WithOptionalNoisePairingConfirmation allows the host to communicate over the encrypted noise +// channel without requiring a pairing confirmation on the BitBox. +// +// SECURITY NOTE: this enables a MITM in the noise channel to go undetected. Use only if the noise +// channel is wrapped in another secure transport layer, e.g. a paired Bluetooth connection. +func WithOptionalNoisePairingConfirmation() DeviceOption { + return func(o *deviceOptions) { + o.optionalNoisePairingConfirmation = true + } +} diff --git a/api/firmware/pairing.go b/api/firmware/pairing.go index 073cb1d..f49bf8b 100644 --- a/api/firmware/pairing.go +++ b/api/firmware/pairing.go @@ -101,8 +101,7 @@ func (device *Device) pair() error { panic(errp.New("expected 32 byte remote static pubkey")) } - pairingVerificationRequiredByApp := !device.config.ContainsDeviceStaticPubkey( - device.deviceNoiseStaticPubkey) + pairingVerificationRequiredByApp := !device.options.optionalNoisePairingConfirmation && !device.config.ContainsDeviceStaticPubkey(device.deviceNoiseStaticPubkey) pairingVerificationRequiredByDevice := string(responseBytes) == "\x01" if pairingVerificationRequiredByDevice || pairingVerificationRequiredByApp {