Skip to content

Commit 2b90fad

Browse files
committed
Merge branch 'bb02p'
2 parents 0e6a62c + 9eeea4b commit 2b90fad

File tree

10 files changed

+88
-33
lines changed

10 files changed

+88
-33
lines changed

api/bootloader/device.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ const (
4444
)
4545

4646
var sigDataMagic = map[common.Product]uint32{
47-
common.ProductBitBox02Multi: 0x653f362b,
48-
common.ProductBitBox02BTCOnly: 0x11233B0B,
47+
common.ProductBitBox02Multi: 0x653f362b,
48+
common.ProductBitBox02BTCOnly: 0x11233B0B,
49+
common.ProductBitBox02PlusMulti: 0x5b648ceb,
50+
common.ProductBitBox02PlusBTCOnly: 0x48714774,
4951
}
5052

5153
// Communication contains functions needed to communicate with the device.

api/bootloader/device_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ func testConfigurations(t *testing.T, run func(*testing.T, *testEnv)) {
5858
for _, product := range []common.Product{
5959
common.ProductBitBox02Multi,
6060
common.ProductBitBox02BTCOnly,
61+
common.ProductBitBox02PlusMulti,
62+
common.ProductBitBox02PlusBTCOnly,
6163
} {
6264
var env testEnv
6365
env.product = product

api/common/common.go

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Copyright 2018-2019 Shift Cryptosecurity AG
2+
// Copyright 2025 Shift Crypto AG
23
//
34
// Licensed under the Apache License, Version 2.0 (the "License");
45
// you may not use this file except in compliance with the License.
@@ -27,28 +28,57 @@ const (
2728
// ProductBitBox02BTCOnly is the btc-only edition of the BitBox02, restricting functionality to
2829
// Bitcoin.
2930
ProductBitBox02BTCOnly Product = "bitbox02-btconly"
31+
32+
// ProductBitBox02PlusMulti is the multi edition of the BitBox02 Plus.
33+
ProductBitBox02PlusMulti Product = "bitbox02-plus-multi"
34+
// ProductBitBox02PlusBTCOnly is the btc-only edition of the BitBox02 Plus, restricting
35+
// functionality to Bitcoin.
36+
ProductBitBox02PlusBTCOnly Product = "bitbox02-plus-btconly"
3037
)
3138

3239
const (
33-
// FirmwareHIDProductStringStandard is the hid product string of the standard edition firmware.
34-
FirmwareHIDProductStringStandard = "BitBox02"
35-
// FirmwareHIDProductStringBTCOnly is the hid product string of the btc-only edition firmware.
36-
FirmwareHIDProductStringBTCOnly = "BitBox02BTC"
37-
38-
// BootloaderHIDProductStringStandard is the hid product string of the standard edition bootloader.
39-
BootloaderHIDProductStringStandard = "bb02-bootloader"
40-
// BootloaderHIDProductStringBTCOnly is the hid product string of the btc-only edition bootloader.
41-
BootloaderHIDProductStringBTCOnly = "bb02btc-bootloader"
40+
// FirmwareDeviceProductStringBitBox02Multi is the product string of the BitBox02 multi edition
41+
// firmware. It appears in the HID descriptor.
42+
FirmwareDeviceProductStringBitBox02Multi = "BitBox02"
43+
// FirmwareDeviceProductStringBitBox02BTCOnly is the product string of the BitBox02 btc-only
44+
// edition firmware. It appears in the HID descriptor.
45+
FirmwareDeviceProductStringBitBox02BTCOnly = "BitBox02BTC"
46+
47+
// BootloaderDeviceProductStringBitBox02Multi is the product string of the BitBox02 multi
48+
// edition bootloader. It appears in the HID descriptor.
49+
BootloaderDeviceProductStringBitBox02Multi = "bb02-bootloader"
50+
// BootloaderDeviceProductStringBitBox02BTCOnly is the product string of the BitBox02 btc-only
51+
// edition bootloader. It appears in the HID descriptor.
52+
BootloaderDeviceProductStringBitBox02BTCOnly = "bb02btc-bootloader"
53+
54+
// FirmwareDeviceProductStringBitBox02PlusMulti the product string of the "BitBox02 Plus" multi
55+
// edition firmware. It appears in the HID descriptor and the Bluetooth characteristic.
56+
FirmwareDeviceProductStringBitBox02PlusMulti = "bb02p-multi"
57+
// FirmwareDeviceProductStringBitBox02PlusBTCOnly is the product string of the "BitBox02 Plus"
58+
// btc-only edition firmware. It appears in the HID descriptor and the Bluetooth characteristic.
59+
FirmwareDeviceProductStringBitBox02PlusBTCOnly = "bb02p-btconly"
60+
61+
// BootloaderDeviceProductStringBitBox02Multi is the product string of the "BitBox02 Plus" multi
62+
// edition bootloader. It appears in the HID descriptor and the Bluetooth characteristic.
63+
BootloaderDeviceProductStringBitBox02PlusMulti = "bb02p-bl-multi"
64+
// BootloaderDeviceProductStringBitBox02BTCOnly is the product string of the "BitBox02 Plus"
65+
// btc-only edition bootloader. It appears in the HID descriptor and the Bluetooth
66+
// characteristic.
67+
BootloaderDeviceProductStringBitBox02PlusBTCOnly = "bb02p-bl-btconly"
4268
)
4369

44-
// ProductFromHIDProductString returns the firmware or bootloader product based on the usb HID
70+
// ProductFromDeviceProductString returns the firmware or bootloader product based on the usb Device
4571
// product string. Returns an error for an invalid/unrecognized product string.
46-
func ProductFromHIDProductString(productString string) (Product, error) {
72+
func ProductFromDeviceProductString(productString string) (Product, error) {
4773
switch productString {
48-
case FirmwareHIDProductStringStandard, BootloaderHIDProductStringStandard:
74+
case FirmwareDeviceProductStringBitBox02Multi, BootloaderDeviceProductStringBitBox02Multi:
4975
return ProductBitBox02Multi, nil
50-
case FirmwareHIDProductStringBTCOnly, BootloaderHIDProductStringBTCOnly:
76+
case FirmwareDeviceProductStringBitBox02BTCOnly, BootloaderDeviceProductStringBitBox02BTCOnly:
5177
return ProductBitBox02BTCOnly, nil
78+
case FirmwareDeviceProductStringBitBox02PlusMulti, BootloaderDeviceProductStringBitBox02PlusMulti:
79+
return ProductBitBox02PlusMulti, nil
80+
case FirmwareDeviceProductStringBitBox02PlusBTCOnly, BootloaderDeviceProductStringBitBox02PlusBTCOnly:
81+
return ProductBitBox02PlusBTCOnly, nil
5282
default:
5383
return "", errp.New("unrecognized product")
5484
}

api/firmware/device.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,16 @@ func (device *Device) info() (*semver.SemVer, common.Product, bool, error) {
167167
platformByte, response := response[0], response[1:]
168168
editionByte, response := response[0], response[1:]
169169
const platformBitBox02 = 0x00
170+
const platformBitBox02Plus = 0x02
170171
products := map[byte]map[byte]common.Product{
171172
platformBitBox02: {
172173
0x00: common.ProductBitBox02Multi,
173174
0x01: common.ProductBitBox02BTCOnly,
174175
},
176+
platformBitBox02Plus: {
177+
0x00: common.ProductBitBox02PlusMulti,
178+
0x01: common.ProductBitBox02PlusBTCOnly,
179+
},
175180
}
176181
editions, ok := products[platformByte]
177182
if !ok {
@@ -211,8 +216,8 @@ func (device *Device) inferVersionAndProduct() error {
211216
if device.version == nil {
212217
version, product, _, err := device.info()
213218
if err != nil {
214-
return errp.New(
215-
"OP_INFO unavailable; need to provide version and product via the USB HID descriptor")
219+
return errp.Newf(
220+
"OP_INFO unavailable; need to provide version and product via the USB HID descriptor.")
216221
}
217222
device.log.Info(fmt.Sprintf("OP_INFO: version=%s, product=%s", version, product))
218223

@@ -326,9 +331,13 @@ func (device *Device) Product() common.Product {
326331
return *device.product
327332
}
328333

334+
func (device *Device) isMultiEdition() bool {
335+
return *device.product == common.ProductBitBox02Multi || *device.product == common.ProductBitBox02PlusMulti
336+
}
337+
329338
// SupportsETH returns true if ETH is supported by the device api.
330339
func (device *Device) SupportsETH(chainID uint64) bool {
331-
if *device.product != common.ProductBitBox02Multi {
340+
if !device.isMultiEdition() {
332341
return false
333342
}
334343
if device.version.AtLeast(semver.NewSemVer(9, 10, 0)) {
@@ -348,7 +357,7 @@ func (device *Device) SupportsETH(chainID uint64) bool {
348357
// For now, this list only contains tokens relevant to the BitBoxApp, otherwise the bitbox02-api-js
349358
// library size would blow up. TODO: move this to the bitbox-wallet-app repo.
350359
func (device *Device) SupportsERC20(contractAddress string) bool {
351-
if *device.product != common.ProductBitBox02Multi {
360+
if !device.isMultiEdition() {
352361
return false
353362
}
354363
if device.version.AtLeast(semver.NewSemVer(4, 0, 0)) {
@@ -384,5 +393,5 @@ func (device *Device) SupportsERC20(contractAddress string) bool {
384393

385394
// SupportsLTC returns true if LTC is supported by the device api.
386395
func (device *Device) SupportsLTC() bool {
387-
return *device.product == common.ProductBitBox02Multi
396+
return device.isMultiEdition()
388397
}

api/firmware/device_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,10 @@ func newDevice(
371371

372372
{ // Test upgrade required and actual upgrade, which for the firmware only means to reboot into the bootloader.
373373
lowestSupported := map[common.Product]*semver.SemVer{
374-
common.ProductBitBox02Multi: lowestSupportedFirmwareVersion,
375-
common.ProductBitBox02BTCOnly: lowestSupportedFirmwareVersionBTCOnly,
374+
common.ProductBitBox02Multi: lowestSupportedFirmwareVersion,
375+
common.ProductBitBox02BTCOnly: lowestSupportedFirmwareVersionBTCOnly,
376+
common.ProductBitBox02PlusMulti: lowestSupportedFirmwareVersion,
377+
common.ProductBitBox02PlusBTCOnly: lowestSupportedFirmwareVersionBTCOnly,
376378
}
377379
lowestSupportedFirmwareVersion, ok := lowestSupported[product]
378380
require.True(t, ok)
@@ -453,6 +455,8 @@ func testConfigurations(t *testing.T, run func(*testing.T, *testEnv)) {
453455
products := []common.Product{
454456
common.ProductBitBox02Multi,
455457
common.ProductBitBox02BTCOnly,
458+
common.ProductBitBox02PlusMulti,
459+
common.ProductBitBox02PlusBTCOnly,
456460
}
457461
for _, version := range versions {
458462
for _, product := range products {

api/firmware/pairing.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@ func (device *Device) ChannelHashVerify(ok bool) {
157157
_ = device.config.AddDeviceStaticPubkey(device.deviceNoiseStaticPubkey)
158158
requireUpgrade := false
159159
switch *device.product {
160-
case common.ProductBitBox02Multi:
160+
case common.ProductBitBox02Multi, common.ProductBitBox02PlusMulti:
161161
requireUpgrade = !device.version.AtLeast(lowestSupportedFirmwareVersion)
162-
case common.ProductBitBox02BTCOnly:
162+
case common.ProductBitBox02BTCOnly, common.ProductBitBox02PlusBTCOnly:
163163
requireUpgrade = !device.version.AtLeast(lowestSupportedFirmwareVersionBTCOnly)
164164
default:
165165
device.log.Error(fmt.Sprintf("unrecognized product: %s", *device.product), nil)

cmd/bootloader/main.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ func errpanic(err error) {
4242
}
4343

4444
func isBitBox02Bootloader(deviceInfo *hid.DeviceInfo) bool {
45-
return (deviceInfo.Product == common.BootloaderHIDProductStringStandard ||
46-
deviceInfo.Product == common.BootloaderHIDProductStringBTCOnly) &&
45+
return (deviceInfo.Product == common.BootloaderDeviceProductStringBitBox02Multi ||
46+
deviceInfo.Product == common.BootloaderDeviceProductStringBitBox02BTCOnly ||
47+
deviceInfo.Product == common.BootloaderDeviceProductStringBitBox02PlusMulti ||
48+
deviceInfo.Product == common.BootloaderDeviceProductStringBitBox02PlusBTCOnly) &&
4749
deviceInfo.VendorID == bitbox02VendorID &&
4850
deviceInfo.ProductID == bitbox02ProductID &&
4951
(deviceInfo.UsagePage == 0xffff || deviceInfo.Interface == 0)
@@ -84,7 +86,7 @@ func main() {
8486
comm := u2fhid.NewCommunication(hidDevice, bitbox02BootloaderCMD)
8587
version, err := parseVersion(deviceInfo.Serial)
8688
errpanic(err)
87-
product, err := common.ProductFromHIDProductString(deviceInfo.Product)
89+
product, err := common.ProductFromDeviceProductString(deviceInfo.Product)
8890
errpanic(err)
8991
device := bootloader.NewDevice(version, product, comm, func(*bootloader.Status) {})
9092
firmwareVersion, signingPubkeysVersion, err := device.Versions()

cmd/miniscript/main.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,10 @@ func errpanic(err error) {
5656
}
5757

5858
func isBitBox02(deviceInfo *hid.DeviceInfo) bool {
59-
return (deviceInfo.Product == common.FirmwareHIDProductStringStandard ||
60-
deviceInfo.Product == common.FirmwareHIDProductStringBTCOnly) &&
59+
return (deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02Multi ||
60+
deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02BTCOnly ||
61+
deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02PlusMulti ||
62+
deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02PlusBTCOnly) &&
6163
deviceInfo.VendorID == bitbox02VendorID &&
6264
deviceInfo.ProductID == bitbox02ProductID &&
6365
(deviceInfo.UsagePage == 0xffff || deviceInfo.Interface == 0)

cmd/paymentrequest/main.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ func errpanic(err error) {
5858
}
5959

6060
func isBitBox02(deviceInfo *hid.DeviceInfo) bool {
61-
return (deviceInfo.Product == common.FirmwareHIDProductStringStandard ||
62-
deviceInfo.Product == common.FirmwareHIDProductStringBTCOnly) &&
61+
return (deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02Multi ||
62+
deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02BTCOnly ||
63+
deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02PlusMulti ||
64+
deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02PlusBTCOnly) &&
6365
deviceInfo.VendorID == bitbox02VendorID &&
6466
deviceInfo.ProductID == bitbox02ProductID &&
6567
(deviceInfo.UsagePage == 0xffff || deviceInfo.Interface == 0)

cmd/playground/main.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ func errpanic(err error) {
4646
}
4747

4848
func isBitBox02(deviceInfo *hid.DeviceInfo) bool {
49-
return (deviceInfo.Product == common.FirmwareHIDProductStringStandard ||
50-
deviceInfo.Product == common.FirmwareHIDProductStringBTCOnly) &&
49+
return (deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02Multi ||
50+
deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02BTCOnly ||
51+
deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02PlusMulti ||
52+
deviceInfo.Product == common.FirmwareDeviceProductStringBitBox02PlusBTCOnly) &&
5153
deviceInfo.VendorID == bitbox02VendorID &&
5254
deviceInfo.ProductID == bitbox02ProductID &&
5355
(deviceInfo.UsagePage == 0xffff || deviceInfo.Interface == 0)

0 commit comments

Comments
 (0)