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 {