From 8d2cb78b8565885f5cdb3b9a2d344538651157c8 Mon Sep 17 00:00:00 2001 From: cedwies Date: Thu, 20 Nov 2025 14:03:39 +0100 Subject: [PATCH] Add ChangePassword API method Add support for changing the device password on an initialized BitBox02. Changes: - Add ChangePasswordRequest protobuf message to bitbox02_system.proto - Add change_password field to Request oneof in hww.proto - Implement ChangePassword() method in system.go - Add firmware version check (requires v9.25.0+) - Add status validation (device must be StatusInitialized) - Add TestSimulatorChangePassword test coverage - Regenerate protobuf Go files The ChangePassword() method validates device state and firmware version before initiating the password change workflow on the device. --- api/firmware/messages/antiklepto.pb.go | 4 +- api/firmware/messages/backup_commands.pb.go | 4 +- api/firmware/messages/bitbox02_system.pb.go | 56 +++++++++-- api/firmware/messages/bitbox02_system.proto | 3 + api/firmware/messages/bluetooth.pb.go | 4 +- api/firmware/messages/btc.pb.go | 4 +- api/firmware/messages/cardano.pb.go | 4 +- api/firmware/messages/common.pb.go | 4 +- api/firmware/messages/eth.pb.go | 4 +- api/firmware/messages/hww.pb.go | 98 +++++++++++-------- api/firmware/messages/hww.proto | 1 + api/firmware/messages/keystore.pb.go | 4 +- api/firmware/messages/mnemonic.pb.go | 4 +- .../messages/perform_attestation.pb.go | 4 +- api/firmware/messages/system.pb.go | 4 +- api/firmware/system.go | 25 +++++ api/firmware/system_test.go | 16 +++ 17 files changed, 173 insertions(+), 70 deletions(-) diff --git a/api/firmware/messages/antiklepto.pb.go b/api/firmware/messages/antiklepto.pb.go index 612e1d1..73facf1 100644 --- a/api/firmware/messages/antiklepto.pb.go +++ b/api/firmware/messages/antiklepto.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: antiklepto.proto package messages diff --git a/api/firmware/messages/backup_commands.pb.go b/api/firmware/messages/backup_commands.pb.go index c347c8b..4258e2e 100644 --- a/api/firmware/messages/backup_commands.pb.go +++ b/api/firmware/messages/backup_commands.pb.go @@ -16,8 +16,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: backup_commands.proto package messages diff --git a/api/firmware/messages/bitbox02_system.pb.go b/api/firmware/messages/bitbox02_system.pb.go index 9b97f18..4087bfc 100644 --- a/api/firmware/messages/bitbox02_system.pb.go +++ b/api/firmware/messages/bitbox02_system.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: bitbox02_system.proto package messages @@ -503,6 +503,42 @@ func (x *SetPasswordRequest) GetEntropy() []byte { return nil } +type ChangePasswordRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ChangePasswordRequest) Reset() { + *x = ChangePasswordRequest{} + mi := &file_bitbox02_system_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ChangePasswordRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChangePasswordRequest) ProtoMessage() {} + +func (x *ChangePasswordRequest) ProtoReflect() protoreflect.Message { + mi := &file_bitbox02_system_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChangePasswordRequest.ProtoReflect.Descriptor instead. +func (*ChangePasswordRequest) Descriptor() ([]byte, []int) { + return file_bitbox02_system_proto_rawDescGZIP(), []int{9} +} + type DeviceInfoResponse_Bluetooth struct { state protoimpl.MessageState `protogen:"open.v1"` // Hash of the currently active Bluetooth firmware on the device. @@ -517,7 +553,7 @@ type DeviceInfoResponse_Bluetooth struct { func (x *DeviceInfoResponse_Bluetooth) Reset() { *x = DeviceInfoResponse_Bluetooth{} - mi := &file_bitbox02_system_proto_msgTypes[9] + mi := &file_bitbox02_system_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -529,7 +565,7 @@ func (x *DeviceInfoResponse_Bluetooth) String() string { func (*DeviceInfoResponse_Bluetooth) ProtoMessage() {} func (x *DeviceInfoResponse_Bluetooth) ProtoReflect() protoreflect.Message { - mi := &file_bitbox02_system_proto_msgTypes[9] + mi := &file_bitbox02_system_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -600,7 +636,8 @@ const file_bitbox02_system_proto_rawDesc = "" + "\x14SetDeviceNameRequest\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\".\n" + "\x12SetPasswordRequest\x12\x18\n" + - "\aentropy\x18\x01 \x01(\fR\aentropyb\x06proto3" + "\aentropy\x18\x01 \x01(\fR\aentropy\"\x17\n" + + "\x15ChangePasswordRequestb\x06proto3" var ( file_bitbox02_system_proto_rawDescOnce sync.Once @@ -615,7 +652,7 @@ func file_bitbox02_system_proto_rawDescGZIP() []byte { } var file_bitbox02_system_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_bitbox02_system_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_bitbox02_system_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_bitbox02_system_proto_goTypes = []any{ (InsertRemoveSDCardRequest_SDCardAction)(0), // 0: shiftcrypto.bitbox02.InsertRemoveSDCardRequest.SDCardAction (*CheckSDCardRequest)(nil), // 1: shiftcrypto.bitbox02.CheckSDCardRequest @@ -627,10 +664,11 @@ var file_bitbox02_system_proto_goTypes = []any{ (*SetDeviceLanguageRequest)(nil), // 7: shiftcrypto.bitbox02.SetDeviceLanguageRequest (*SetDeviceNameRequest)(nil), // 8: shiftcrypto.bitbox02.SetDeviceNameRequest (*SetPasswordRequest)(nil), // 9: shiftcrypto.bitbox02.SetPasswordRequest - (*DeviceInfoResponse_Bluetooth)(nil), // 10: shiftcrypto.bitbox02.DeviceInfoResponse.Bluetooth + (*ChangePasswordRequest)(nil), // 10: shiftcrypto.bitbox02.ChangePasswordRequest + (*DeviceInfoResponse_Bluetooth)(nil), // 11: shiftcrypto.bitbox02.DeviceInfoResponse.Bluetooth } var file_bitbox02_system_proto_depIdxs = []int32{ - 10, // 0: shiftcrypto.bitbox02.DeviceInfoResponse.bluetooth:type_name -> shiftcrypto.bitbox02.DeviceInfoResponse.Bluetooth + 11, // 0: shiftcrypto.bitbox02.DeviceInfoResponse.bluetooth:type_name -> shiftcrypto.bitbox02.DeviceInfoResponse.Bluetooth 0, // 1: shiftcrypto.bitbox02.InsertRemoveSDCardRequest.action:type_name -> shiftcrypto.bitbox02.InsertRemoveSDCardRequest.SDCardAction 2, // [2:2] is the sub-list for method output_type 2, // [2:2] is the sub-list for method input_type @@ -651,7 +689,7 @@ func file_bitbox02_system_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_bitbox02_system_proto_rawDesc), len(file_bitbox02_system_proto_rawDesc)), NumEnums: 1, - NumMessages: 10, + NumMessages: 11, NumExtensions: 0, NumServices: 0, }, diff --git a/api/firmware/messages/bitbox02_system.proto b/api/firmware/messages/bitbox02_system.proto index a5e8e55..aef431f 100644 --- a/api/firmware/messages/bitbox02_system.proto +++ b/api/firmware/messages/bitbox02_system.proto @@ -66,3 +66,6 @@ message SetDeviceNameRequest { message SetPasswordRequest { bytes entropy = 1; } + +message ChangePasswordRequest{ +} \ No newline at end of file diff --git a/api/firmware/messages/bluetooth.pb.go b/api/firmware/messages/bluetooth.pb.go index 883c0b0..dc07400 100644 --- a/api/firmware/messages/bluetooth.pb.go +++ b/api/firmware/messages/bluetooth.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: bluetooth.proto package messages diff --git a/api/firmware/messages/btc.pb.go b/api/firmware/messages/btc.pb.go index 311e39d..168ccfe 100644 --- a/api/firmware/messages/btc.pb.go +++ b/api/firmware/messages/btc.pb.go @@ -15,8 +15,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: btc.proto package messages diff --git a/api/firmware/messages/cardano.pb.go b/api/firmware/messages/cardano.pb.go index 3187b93..24156c0 100644 --- a/api/firmware/messages/cardano.pb.go +++ b/api/firmware/messages/cardano.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: cardano.proto package messages diff --git a/api/firmware/messages/common.pb.go b/api/firmware/messages/common.pb.go index b18b3f6..7be92fa 100644 --- a/api/firmware/messages/common.pb.go +++ b/api/firmware/messages/common.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: common.proto package messages diff --git a/api/firmware/messages/eth.pb.go b/api/firmware/messages/eth.pb.go index ad305e5..e782b28 100644 --- a/api/firmware/messages/eth.pb.go +++ b/api/firmware/messages/eth.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: eth.proto package messages diff --git a/api/firmware/messages/hww.pb.go b/api/firmware/messages/hww.pb.go index 0ceba6e..4416b40 100644 --- a/api/firmware/messages/hww.pb.go +++ b/api/firmware/messages/hww.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: hww.proto package messages @@ -154,6 +154,7 @@ type Request struct { // *Request_Cardano // *Request_Bip85 // *Request_Bluetooth + // *Request_ChangePassword Request isRequest_Request `protobuf_oneof:"request"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -439,6 +440,15 @@ func (x *Request) GetBluetooth() *BluetoothRequest { return nil } +func (x *Request) GetChangePassword() *ChangePasswordRequest { + if x != nil { + if x, ok := x.Request.(*Request_ChangePassword); ok { + return x.ChangePassword + } + } + return nil +} + type isRequest_Request interface { isRequest_Request() } @@ -553,6 +563,10 @@ type Request_Bluetooth struct { Bluetooth *BluetoothRequest `protobuf:"bytes,29,opt,name=bluetooth,proto3,oneof"` } +type Request_ChangePassword struct { + ChangePassword *ChangePasswordRequest `protobuf:"bytes,30,opt,name=change_password,json=changePassword,proto3,oneof"` +} + func (*Request_DeviceName) isRequest_Request() {} func (*Request_DeviceLanguage) isRequest_Request() {} @@ -607,6 +621,8 @@ func (*Request_Bip85) isRequest_Request() {} func (*Request_Bluetooth) isRequest_Request() {} +func (*Request_ChangePassword) isRequest_Request() {} + type Response struct { state protoimpl.MessageState `protogen:"open.v1"` // Types that are valid to be assigned to Response: @@ -922,7 +938,7 @@ const file_hww_proto_rawDesc = "" + "\x05Error\x12\x12\n" + "\x04code\x18\x01 \x01(\x05R\x04code\x12\x18\n" + "\amessage\x18\x02 \x01(\tR\amessage\"\t\n" + - "\aSuccess\"\xa7\x11\n" + + "\aSuccess\"\xff\x11\n" + "\aRequest\x12M\n" + "\vdevice_name\x18\x02 \x01(\v2*.shiftcrypto.bitbox02.SetDeviceNameRequestH\x00R\n" + "deviceName\x12Y\n" + @@ -953,7 +969,8 @@ const file_hww_proto_rawDesc = "" + "\x17electrum_encryption_key\x18\x1a \x01(\v22.shiftcrypto.bitbox02.ElectrumEncryptionKeyRequestH\x00R\x15electrumEncryptionKey\x12@\n" + "\acardano\x18\x1b \x01(\v2$.shiftcrypto.bitbox02.CardanoRequestH\x00R\acardano\x12:\n" + "\x05bip85\x18\x1c \x01(\v2\".shiftcrypto.bitbox02.BIP85RequestH\x00R\x05bip85\x12F\n" + - "\tbluetooth\x18\x1d \x01(\v2&.shiftcrypto.bitbox02.BluetoothRequestH\x00R\tbluetoothB\t\n" + + "\tbluetooth\x18\x1d \x01(\v2&.shiftcrypto.bitbox02.BluetoothRequestH\x00R\tbluetooth\x12V\n" + + "\x0fchange_password\x18\x1e \x01(\v2+.shiftcrypto.bitbox02.ChangePasswordRequestH\x00R\x0echangePasswordB\t\n" + "\arequestJ\x04\b\x01\x10\x02J\x04\b\x17\x10\x18\"\xaf\t\n" + "\bResponse\x129\n" + "\asuccess\x18\x01 \x01(\v2\x1d.shiftcrypto.bitbox02.SuccessH\x00R\asuccess\x123\n" + @@ -1022,20 +1039,21 @@ var file_hww_proto_goTypes = []any{ (*CardanoRequest)(nil), // 28: shiftcrypto.bitbox02.CardanoRequest (*BIP85Request)(nil), // 29: shiftcrypto.bitbox02.BIP85Request (*BluetoothRequest)(nil), // 30: shiftcrypto.bitbox02.BluetoothRequest - (*DeviceInfoResponse)(nil), // 31: shiftcrypto.bitbox02.DeviceInfoResponse - (*PubResponse)(nil), // 32: shiftcrypto.bitbox02.PubResponse - (*BTCSignNextResponse)(nil), // 33: shiftcrypto.bitbox02.BTCSignNextResponse - (*ListBackupsResponse)(nil), // 34: shiftcrypto.bitbox02.ListBackupsResponse - (*CheckBackupResponse)(nil), // 35: shiftcrypto.bitbox02.CheckBackupResponse - (*PerformAttestationResponse)(nil), // 36: shiftcrypto.bitbox02.PerformAttestationResponse - (*CheckSDCardResponse)(nil), // 37: shiftcrypto.bitbox02.CheckSDCardResponse - (*ETHResponse)(nil), // 38: shiftcrypto.bitbox02.ETHResponse - (*RootFingerprintResponse)(nil), // 39: shiftcrypto.bitbox02.RootFingerprintResponse - (*BTCResponse)(nil), // 40: shiftcrypto.bitbox02.BTCResponse - (*ElectrumEncryptionKeyResponse)(nil), // 41: shiftcrypto.bitbox02.ElectrumEncryptionKeyResponse - (*CardanoResponse)(nil), // 42: shiftcrypto.bitbox02.CardanoResponse - (*BIP85Response)(nil), // 43: shiftcrypto.bitbox02.BIP85Response - (*BluetoothResponse)(nil), // 44: shiftcrypto.bitbox02.BluetoothResponse + (*ChangePasswordRequest)(nil), // 31: shiftcrypto.bitbox02.ChangePasswordRequest + (*DeviceInfoResponse)(nil), // 32: shiftcrypto.bitbox02.DeviceInfoResponse + (*PubResponse)(nil), // 33: shiftcrypto.bitbox02.PubResponse + (*BTCSignNextResponse)(nil), // 34: shiftcrypto.bitbox02.BTCSignNextResponse + (*ListBackupsResponse)(nil), // 35: shiftcrypto.bitbox02.ListBackupsResponse + (*CheckBackupResponse)(nil), // 36: shiftcrypto.bitbox02.CheckBackupResponse + (*PerformAttestationResponse)(nil), // 37: shiftcrypto.bitbox02.PerformAttestationResponse + (*CheckSDCardResponse)(nil), // 38: shiftcrypto.bitbox02.CheckSDCardResponse + (*ETHResponse)(nil), // 39: shiftcrypto.bitbox02.ETHResponse + (*RootFingerprintResponse)(nil), // 40: shiftcrypto.bitbox02.RootFingerprintResponse + (*BTCResponse)(nil), // 41: shiftcrypto.bitbox02.BTCResponse + (*ElectrumEncryptionKeyResponse)(nil), // 42: shiftcrypto.bitbox02.ElectrumEncryptionKeyResponse + (*CardanoResponse)(nil), // 43: shiftcrypto.bitbox02.CardanoResponse + (*BIP85Response)(nil), // 44: shiftcrypto.bitbox02.BIP85Response + (*BluetoothResponse)(nil), // 45: shiftcrypto.bitbox02.BluetoothResponse } var file_hww_proto_depIdxs = []int32{ 4, // 0: shiftcrypto.bitbox02.Request.device_name:type_name -> shiftcrypto.bitbox02.SetDeviceNameRequest @@ -1065,27 +1083,28 @@ var file_hww_proto_depIdxs = []int32{ 28, // 24: shiftcrypto.bitbox02.Request.cardano:type_name -> shiftcrypto.bitbox02.CardanoRequest 29, // 25: shiftcrypto.bitbox02.Request.bip85:type_name -> shiftcrypto.bitbox02.BIP85Request 30, // 26: shiftcrypto.bitbox02.Request.bluetooth:type_name -> shiftcrypto.bitbox02.BluetoothRequest - 1, // 27: shiftcrypto.bitbox02.Response.success:type_name -> shiftcrypto.bitbox02.Success - 0, // 28: shiftcrypto.bitbox02.Response.error:type_name -> shiftcrypto.bitbox02.Error - 31, // 29: shiftcrypto.bitbox02.Response.device_info:type_name -> shiftcrypto.bitbox02.DeviceInfoResponse - 32, // 30: shiftcrypto.bitbox02.Response.pub:type_name -> shiftcrypto.bitbox02.PubResponse - 33, // 31: shiftcrypto.bitbox02.Response.btc_sign_next:type_name -> shiftcrypto.bitbox02.BTCSignNextResponse - 34, // 32: shiftcrypto.bitbox02.Response.list_backups:type_name -> shiftcrypto.bitbox02.ListBackupsResponse - 35, // 33: shiftcrypto.bitbox02.Response.check_backup:type_name -> shiftcrypto.bitbox02.CheckBackupResponse - 36, // 34: shiftcrypto.bitbox02.Response.perform_attestation:type_name -> shiftcrypto.bitbox02.PerformAttestationResponse - 37, // 35: shiftcrypto.bitbox02.Response.check_sdcard:type_name -> shiftcrypto.bitbox02.CheckSDCardResponse - 38, // 36: shiftcrypto.bitbox02.Response.eth:type_name -> shiftcrypto.bitbox02.ETHResponse - 39, // 37: shiftcrypto.bitbox02.Response.fingerprint:type_name -> shiftcrypto.bitbox02.RootFingerprintResponse - 40, // 38: shiftcrypto.bitbox02.Response.btc:type_name -> shiftcrypto.bitbox02.BTCResponse - 41, // 39: shiftcrypto.bitbox02.Response.electrum_encryption_key:type_name -> shiftcrypto.bitbox02.ElectrumEncryptionKeyResponse - 42, // 40: shiftcrypto.bitbox02.Response.cardano:type_name -> shiftcrypto.bitbox02.CardanoResponse - 43, // 41: shiftcrypto.bitbox02.Response.bip85:type_name -> shiftcrypto.bitbox02.BIP85Response - 44, // 42: shiftcrypto.bitbox02.Response.bluetooth:type_name -> shiftcrypto.bitbox02.BluetoothResponse - 43, // [43:43] is the sub-list for method output_type - 43, // [43:43] is the sub-list for method input_type - 43, // [43:43] is the sub-list for extension type_name - 43, // [43:43] is the sub-list for extension extendee - 0, // [0:43] is the sub-list for field type_name + 31, // 27: shiftcrypto.bitbox02.Request.change_password:type_name -> shiftcrypto.bitbox02.ChangePasswordRequest + 1, // 28: shiftcrypto.bitbox02.Response.success:type_name -> shiftcrypto.bitbox02.Success + 0, // 29: shiftcrypto.bitbox02.Response.error:type_name -> shiftcrypto.bitbox02.Error + 32, // 30: shiftcrypto.bitbox02.Response.device_info:type_name -> shiftcrypto.bitbox02.DeviceInfoResponse + 33, // 31: shiftcrypto.bitbox02.Response.pub:type_name -> shiftcrypto.bitbox02.PubResponse + 34, // 32: shiftcrypto.bitbox02.Response.btc_sign_next:type_name -> shiftcrypto.bitbox02.BTCSignNextResponse + 35, // 33: shiftcrypto.bitbox02.Response.list_backups:type_name -> shiftcrypto.bitbox02.ListBackupsResponse + 36, // 34: shiftcrypto.bitbox02.Response.check_backup:type_name -> shiftcrypto.bitbox02.CheckBackupResponse + 37, // 35: shiftcrypto.bitbox02.Response.perform_attestation:type_name -> shiftcrypto.bitbox02.PerformAttestationResponse + 38, // 36: shiftcrypto.bitbox02.Response.check_sdcard:type_name -> shiftcrypto.bitbox02.CheckSDCardResponse + 39, // 37: shiftcrypto.bitbox02.Response.eth:type_name -> shiftcrypto.bitbox02.ETHResponse + 40, // 38: shiftcrypto.bitbox02.Response.fingerprint:type_name -> shiftcrypto.bitbox02.RootFingerprintResponse + 41, // 39: shiftcrypto.bitbox02.Response.btc:type_name -> shiftcrypto.bitbox02.BTCResponse + 42, // 40: shiftcrypto.bitbox02.Response.electrum_encryption_key:type_name -> shiftcrypto.bitbox02.ElectrumEncryptionKeyResponse + 43, // 41: shiftcrypto.bitbox02.Response.cardano:type_name -> shiftcrypto.bitbox02.CardanoResponse + 44, // 42: shiftcrypto.bitbox02.Response.bip85:type_name -> shiftcrypto.bitbox02.BIP85Response + 45, // 43: shiftcrypto.bitbox02.Response.bluetooth:type_name -> shiftcrypto.bitbox02.BluetoothResponse + 44, // [44:44] is the sub-list for method output_type + 44, // [44:44] is the sub-list for method input_type + 44, // [44:44] is the sub-list for extension type_name + 44, // [44:44] is the sub-list for extension extendee + 0, // [0:44] is the sub-list for field type_name } func init() { file_hww_proto_init() } @@ -1132,6 +1151,7 @@ func file_hww_proto_init() { (*Request_Cardano)(nil), (*Request_Bip85)(nil), (*Request_Bluetooth)(nil), + (*Request_ChangePassword)(nil), } file_hww_proto_msgTypes[3].OneofWrappers = []any{ (*Response_Success)(nil), diff --git a/api/firmware/messages/hww.proto b/api/firmware/messages/hww.proto index 4088ae3..ea7177e 100644 --- a/api/firmware/messages/hww.proto +++ b/api/firmware/messages/hww.proto @@ -69,6 +69,7 @@ message Request { CardanoRequest cardano = 27; BIP85Request bip85 = 28; BluetoothRequest bluetooth = 29; + ChangePasswordRequest change_password = 30; } } diff --git a/api/firmware/messages/keystore.pb.go b/api/firmware/messages/keystore.pb.go index 907dd1f..3207c39 100644 --- a/api/firmware/messages/keystore.pb.go +++ b/api/firmware/messages/keystore.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: keystore.proto package messages diff --git a/api/firmware/messages/mnemonic.pb.go b/api/firmware/messages/mnemonic.pb.go index 5318c5f..5412491 100644 --- a/api/firmware/messages/mnemonic.pb.go +++ b/api/firmware/messages/mnemonic.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: mnemonic.proto package messages diff --git a/api/firmware/messages/perform_attestation.pb.go b/api/firmware/messages/perform_attestation.pb.go index fb20e51..ce3e08c 100644 --- a/api/firmware/messages/perform_attestation.pb.go +++ b/api/firmware/messages/perform_attestation.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: perform_attestation.proto package messages diff --git a/api/firmware/messages/system.pb.go b/api/firmware/messages/system.pb.go index 20321c1..ceea785 100644 --- a/api/firmware/messages/system.pb.go +++ b/api/firmware/messages/system.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.9 -// protoc v3.21.12 +// protoc-gen-go v1.36.10 +// protoc v6.33.1 // source: system.proto package messages diff --git a/api/firmware/system.go b/api/firmware/system.go index ee9d5b8..0c9f23e 100644 --- a/api/firmware/system.go +++ b/api/firmware/system.go @@ -122,6 +122,31 @@ func (device *Device) SetPassword(seedLen int) error { return nil } +// ChangePassword invokes the password change workflow on the device. Should be called only if +// the device is initialized (deviceInfo.Initialized is true). +func (device *Device) ChangePassword() error { + if !device.version.AtLeast(semver.NewSemVer(9, 25, 0)) { + return UnsupportedError("9.25.0") + } + if device.status != StatusInitialized { + return errp.New("invalid status") + } + request := &messages.Request{ + Request: &messages.Request_ChangePassword{ + ChangePassword: &messages.ChangePasswordRequest{}, + }, + } + response, err := device.query(request) + if err != nil { + return err + } + _, ok := response.Response.(*messages.Response_Success) + if !ok { + return errp.New("unexpected response") + } + return nil +} + func (device *Device) reboot(purpose messages.RebootRequest_Purpose) error { request := &messages.Request{ Request: &messages.Request_Reboot{ diff --git a/api/firmware/system_test.go b/api/firmware/system_test.go index 27515ab..2fa11d8 100644 --- a/api/firmware/system_test.go +++ b/api/firmware/system_test.go @@ -20,6 +20,7 @@ import ( "testing" "github.com/BitBoxSwiss/bitbox02-api-go/api/common" + "github.com/BitBoxSwiss/bitbox02-api-go/util/semver" "github.com/stretchr/testify/require" ) @@ -57,3 +58,18 @@ func TestSimulatorSetPassword(t *testing.T) { }) } } + +func TestSimulatorChangePassword(t *testing.T) { + testInitializedSimulators(t, func(t *testing.T, device *Device, stdOut *bytes.Buffer) { + t.Helper() + err := device.ChangePassword() + if device.Version().AtLeast(semver.NewSemVer(9, 25, 0)) { + require.NoError(t, err) + // Status should remain StatusInitialized + require.Equal(t, StatusInitialized, device.Status()) + } else { + // Old firmware versions don't support ChangePassword + require.EqualError(t, err, UnsupportedError("9.25.0").Error()) + } + }) +}