embed/bootloader: add information about firmware (version, vendor, etc.) to Features message

This commit is contained in:
Pavol Rusnak 2018-02-06 17:06:43 +01:00
parent 548b8cb25b
commit 1c5beb1c12
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
9 changed files with 93 additions and 48 deletions

View File

@ -150,6 +150,9 @@ static secbool bootloader_usb_loop(const vendor_header * const vhdr, const image
return sectrue; // jump to firmware
}
break;
case 55: // GetFeatures
process_msg_GetFeatures(USB_IFACE_NUM, msg_size, buf, vhdr, hdr);
break;
default:
process_msg_unknown(USB_IFACE_NUM, msg_size, buf);
break;

View File

@ -140,9 +140,13 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id, const pb_field_t fi
return sectrue;
}
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MSG_SEND_INIT(TYPE) TYPE msg_send = TYPE##_init_default
#define MSG_SEND_ASSIGN_VALUE(FIELD, VALUE) { msg_send.has_##FIELD = true; msg_send.FIELD = VALUE; }
#define MSG_SEND_ASSIGN_STRING(FIELD, VALUE) { msg_send.has_##FIELD = true; memset(msg_send.FIELD, 0, sizeof(msg_send.FIELD)); strncpy(msg_send.FIELD, VALUE, sizeof(msg_send.FIELD) - 1); }
#define MSG_SEND_ASSIGN_STRING_LEN(FIELD, VALUE, LEN) { msg_send.has_##FIELD = true; memset(msg_send.FIELD, 0, sizeof(msg_send.FIELD)); strncpy(msg_send.FIELD, VALUE, MIN(LEN, sizeof(msg_send.FIELD) - 1)); }
#define MSG_SEND_ASSIGN_BYTES(FIELD, VALUE, LEN) { msg_send.has_##FIELD = true; memset(msg_send.FIELD.bytes, 0, sizeof(msg_send.FIELD.bytes)); memcpy(msg_send.FIELD.bytes, VALUE, MIN(LEN, sizeof(msg_send.FIELD.bytes))); msg_send.FIELD.size = MIN(LEN, sizeof(msg_send.FIELD.bytes)); }
#define MSG_SEND(TYPE) _send_msg(iface_num, MessageType_MessageType_##TYPE, TYPE##_fields, &msg_send)
typedef struct {
@ -227,23 +231,46 @@ void send_user_abort(uint8_t iface_num, const char *msg)
MSG_SEND(Failure);
}
void process_msg_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const vendor_header * const vhdr, const image_header * const hdr)
static void send_msg_features(uint8_t iface_num, const vendor_header * const vhdr, const image_header * const hdr)
{
MSG_RECV_INIT(Initialize);
MSG_RECV(Initialize);
MSG_SEND_INIT(Features);
MSG_SEND_ASSIGN_STRING(vendor, "trezor.io");
MSG_SEND_ASSIGN_VALUE(major_version, VERSION_MAJOR);
MSG_SEND_ASSIGN_VALUE(minor_version, VERSION_MINOR);
MSG_SEND_ASSIGN_VALUE(patch_version, VERSION_PATCH);
MSG_SEND_ASSIGN_VALUE(bootloader_mode, true);
MSG_SEND_ASSIGN_VALUE(firmware_present, (vhdr && hdr));
MSG_SEND_ASSIGN_STRING(model, "T");
if (vhdr && hdr) {
MSG_SEND_ASSIGN_VALUE(firmware_present, true);
MSG_SEND_ASSIGN_VALUE(fw_major, (hdr->version & 0xFF));
MSG_SEND_ASSIGN_VALUE(fw_minor, ((hdr->version >> 8) & 0xFF));
MSG_SEND_ASSIGN_VALUE(fw_patch, ((hdr->version >> 16) & 0xFF));
MSG_SEND_ASSIGN_STRING_LEN(fw_vendor, vhdr->vstr, vhdr->vstr_len);
uint8_t hash[32];
vendor_keys_hash(vhdr, hash);
MSG_SEND_ASSIGN_BYTES(fw_vendor_keys, hash, 32);
} else {
MSG_SEND_ASSIGN_VALUE(firmware_present, false);
}
// TODO: pass info about installed firmware (vendor, version, etc.)
MSG_SEND(Features);
}
void process_msg_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const vendor_header * const vhdr, const image_header * const hdr)
{
MSG_RECV_INIT(Initialize);
MSG_RECV(Initialize);
send_msg_features(iface_num, vhdr, hdr);
}
void process_msg_GetFeatures(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const vendor_header * const vhdr, const image_header * const hdr)
{
MSG_RECV_INIT(GetFeatures);
MSG_RECV(GetFeatures);
send_msg_features(iface_num, vhdr, hdr);
}
void process_msg_Ping(uint8_t iface_num, uint32_t msg_size, uint8_t *buf)
{
MSG_RECV_INIT(Ping);

View File

@ -17,6 +17,7 @@ secbool msg_parse_header(const uint8_t *buf, uint16_t *msg_id, uint32_t *msg_siz
void send_user_abort(uint8_t iface_num, const char *msg);
void process_msg_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const vendor_header * const vhdr, const image_header * const hdr);
void process_msg_GetFeatures(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const vendor_header * const vhdr, const image_header * const hdr);
void process_msg_Ping(uint8_t iface_num, uint32_t msg_size, uint8_t *buf);
void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size, uint8_t *buf);
int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *buf);

View File

@ -5,6 +5,8 @@ Features.label max_size:33
Features.revision max_size:20
Features.bootloader_hash max_size:32
Features.model max_size:17
Features.fw_vendor max_size:256
Features.fw_vendor_keys max_size:32
Ping.message max_size:256

View File

@ -18,25 +18,24 @@ const pb_field_t GetFeatures_fields[1] = {
PB_LAST_FIELD
};
const pb_field_t Features_fields[19] = {
const pb_field_t Features_fields[18] = {
PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, Features, vendor, vendor, 0),
PB_FIELD( 2, UINT32 , OPTIONAL, STATIC , OTHER, Features, major_version, vendor, 0),
PB_FIELD( 3, UINT32 , OPTIONAL, STATIC , OTHER, Features, minor_version, major_version, 0),
PB_FIELD( 4, UINT32 , OPTIONAL, STATIC , OTHER, Features, patch_version, minor_version, 0),
PB_FIELD( 5, BOOL , OPTIONAL, STATIC , OTHER, Features, bootloader_mode, patch_version, 0),
PB_FIELD( 6, STRING , OPTIONAL, STATIC , OTHER, Features, device_id, bootloader_mode, 0),
PB_FIELD( 7, BOOL , OPTIONAL, STATIC , OTHER, Features, pin_protection, device_id, 0),
PB_FIELD( 8, BOOL , OPTIONAL, STATIC , OTHER, Features, passphrase_protection, pin_protection, 0),
PB_FIELD( 9, STRING , OPTIONAL, STATIC , OTHER, Features, language, passphrase_protection, 0),
PB_FIELD( 9, STRING , OPTIONAL, STATIC , OTHER, Features, language, device_id, 0),
PB_FIELD( 10, STRING , OPTIONAL, STATIC , OTHER, Features, label, language, 0),
PB_FIELD( 12, BOOL , OPTIONAL, STATIC , OTHER, Features, initialized, label, 0),
PB_FIELD( 13, BYTES , OPTIONAL, STATIC , OTHER, Features, revision, initialized, 0),
PB_FIELD( 14, BYTES , OPTIONAL, STATIC , OTHER, Features, bootloader_hash, revision, 0),
PB_FIELD( 15, BOOL , OPTIONAL, STATIC , OTHER, Features, imported, bootloader_hash, 0),
PB_FIELD( 16, BOOL , OPTIONAL, STATIC , OTHER, Features, pin_cached, imported, 0),
PB_FIELD( 17, BOOL , OPTIONAL, STATIC , OTHER, Features, passphrase_cached, pin_cached, 0),
PB_FIELD( 18, BOOL , OPTIONAL, STATIC , OTHER, Features, firmware_present, passphrase_cached, 0),
PB_FIELD( 18, BOOL , OPTIONAL, STATIC , OTHER, Features, firmware_present, revision, 0),
PB_FIELD( 21, STRING , OPTIONAL, STATIC , OTHER, Features, model, firmware_present, 0),
PB_FIELD( 22, UINT32 , OPTIONAL, STATIC , OTHER, Features, fw_major, model, 0),
PB_FIELD( 23, UINT32 , OPTIONAL, STATIC , OTHER, Features, fw_minor, fw_major, 0),
PB_FIELD( 24, UINT32 , OPTIONAL, STATIC , OTHER, Features, fw_patch, fw_minor, 0),
PB_FIELD( 25, STRING , OPTIONAL, STATIC , OTHER, Features, fw_vendor, fw_patch, 0),
PB_FIELD( 26, BYTES , OPTIONAL, STATIC , OTHER, Features, fw_vendor_keys, fw_vendor, 0),
PB_LAST_FIELD
};

View File

@ -67,7 +67,7 @@ typedef struct _Failure {
} Failure;
typedef PB_BYTES_ARRAY_T(20) Features_revision_t;
typedef PB_BYTES_ARRAY_T(32) Features_bootloader_hash_t;
typedef PB_BYTES_ARRAY_T(32) Features_fw_vendor_keys_t;
typedef struct _Features {
bool has_vendor;
char vendor[33];
@ -81,10 +81,6 @@ typedef struct _Features {
bool bootloader_mode;
bool has_device_id;
char device_id[25];
bool has_pin_protection;
bool pin_protection;
bool has_passphrase_protection;
bool passphrase_protection;
bool has_language;
char language[17];
bool has_label;
@ -93,18 +89,20 @@ typedef struct _Features {
bool initialized;
bool has_revision;
Features_revision_t revision;
bool has_bootloader_hash;
Features_bootloader_hash_t bootloader_hash;
bool has_imported;
bool imported;
bool has_pin_cached;
bool pin_cached;
bool has_passphrase_cached;
bool passphrase_cached;
bool has_firmware_present;
bool firmware_present;
bool has_model;
char model[17];
bool has_fw_major;
uint32_t fw_major;
bool has_fw_minor;
uint32_t fw_minor;
bool has_fw_patch;
uint32_t fw_patch;
bool has_fw_vendor;
char fw_vendor[256];
bool has_fw_vendor_keys;
Features_fw_vendor_keys_t fw_vendor_keys;
/* @@protoc_insertion_point(struct:Features) */
} Features;
@ -153,7 +151,7 @@ typedef struct _Success {
/* Initializer values for message structs */
#define Initialize_init_default {0}
#define GetFeatures_init_default {0}
#define Features_init_default {false, "", false, 0, false, 0, false, 0, false, 0, false, "", false, 0, false, 0, false, "", false, "", false, 0, false, {0, {0}}, false, {0, {0}}, false, 0, false, 0, false, 0, false, 0, false, ""}
#define Features_init_default {false, "", false, 0, false, 0, false, 0, false, 0, false, "", false, "", false, "", false, 0, false, {0, {0}}, false, 0, false, "", false, 0, false, 0, false, 0, false, "", false, {0, {0}}}
#define Ping_init_default {false, "", false, 0, false, 0, false, 0}
#define Success_init_default {false, ""}
#define Failure_init_default {false, (FailureType)0, false, ""}
@ -164,7 +162,7 @@ typedef struct _Success {
#define FirmwareUpload_init_default {{{NULL}, NULL}, false, {0, {0}}}
#define Initialize_init_zero {0}
#define GetFeatures_init_zero {0}
#define Features_init_zero {false, "", false, 0, false, 0, false, 0, false, 0, false, "", false, 0, false, 0, false, "", false, "", false, 0, false, {0, {0}}, false, {0, {0}}, false, 0, false, 0, false, 0, false, 0, false, ""}
#define Features_init_zero {false, "", false, 0, false, 0, false, 0, false, 0, false, "", false, "", false, "", false, 0, false, {0, {0}}, false, 0, false, "", false, 0, false, 0, false, 0, false, "", false, {0, {0}}}
#define Ping_init_zero {false, "", false, 0, false, 0, false, 0}
#define Success_init_zero {false, ""}
#define Failure_init_zero {false, (FailureType)0, false, ""}
@ -185,18 +183,17 @@ typedef struct _Success {
#define Features_patch_version_tag 4
#define Features_bootloader_mode_tag 5
#define Features_device_id_tag 6
#define Features_pin_protection_tag 7
#define Features_passphrase_protection_tag 8
#define Features_language_tag 9
#define Features_label_tag 10
#define Features_initialized_tag 12
#define Features_revision_tag 13
#define Features_bootloader_hash_tag 14
#define Features_imported_tag 15
#define Features_pin_cached_tag 16
#define Features_passphrase_cached_tag 17
#define Features_firmware_present_tag 18
#define Features_model_tag 21
#define Features_fw_major_tag 22
#define Features_fw_minor_tag 23
#define Features_fw_patch_tag 24
#define Features_fw_vendor_tag 25
#define Features_fw_vendor_keys_tag 26
#define FirmwareErase_length_tag 1
#define FirmwareRequest_offset_tag 1
#define FirmwareRequest_length_tag 2
@ -211,7 +208,7 @@ typedef struct _Success {
/* Struct field encoding specification for nanopb */
extern const pb_field_t Initialize_fields[1];
extern const pb_field_t GetFeatures_fields[1];
extern const pb_field_t Features_fields[19];
extern const pb_field_t Features_fields[18];
extern const pb_field_t Ping_fields[5];
extern const pb_field_t Success_fields[2];
extern const pb_field_t Failure_fields[3];
@ -224,7 +221,7 @@ extern const pb_field_t FirmwareUpload_fields[3];
/* Maximum encoded size of messages (where known) */
#define Initialize_size 0
#define GetFeatures_size 0
#define Features_size 229
#define Features_size 499
#define Ping_size 265
#define Success_size 259
#define Failure_size 270

View File

@ -37,27 +37,32 @@ message GetFeatures {
* @prev GetFeatures
*/
message Features {
optional string vendor = 1; // name of the manufacturer, e.g. "bitcointrezor.com"
optional uint32 major_version = 2; // major version of the device, e.g. 1
optional uint32 minor_version = 3; // minor version of the device, e.g. 0
optional uint32 patch_version = 4; // patch version of the device, e.g. 0
optional string vendor = 1; // name of the manufacturer, e.g. "trezor.io"
optional uint32 major_version = 2; // major version of the firmware/bootloader, e.g. 1
optional uint32 minor_version = 3; // minor version of the firmware/bootloader, e.g. 0
optional uint32 patch_version = 4; // patch version of the firmware/bootloader, e.g. 0
optional bool bootloader_mode = 5; // is device in bootloader mode?
optional string device_id = 6; // device's unique identifier
optional bool pin_protection = 7; // is device protected by PIN?
optional bool passphrase_protection = 8; // is node/mnemonic encrypted using passphrase?
// optional bool pin_protection = 7; // is device protected by PIN?
// optional bool passphrase_protection = 8; // is node/mnemonic encrypted using passphrase?
optional string language = 9; // device language
optional string label = 10; // device description label
// repeated CoinType coins = 11; // supported coins
optional bool initialized = 12; // does device contain seed?
optional bytes revision = 13; // SCM revision of firmware
optional bytes bootloader_hash = 14; // hash of the bootloader
optional bool imported = 15; // was storage imported from an external source?
optional bool pin_cached = 16; // is PIN already cached in session?
optional bool passphrase_cached = 17; // is passphrase already cached in session?
// optional bytes bootloader_hash = 14; // hash of the bootloader
// optional bool imported = 15; // was storage imported from an external source?
// optional bool pin_cached = 16; // is PIN already cached in session?
// optional bool passphrase_cached = 17; // is passphrase already cached in session?
optional bool firmware_present = 18; // is valid firmware loaded?
// optional bool needs_backup = 19; // does storage need backup? (equals to Storage.needs_backup)
// optional uint32 flags = 20; // device flags (equals to Storage.flags)
optional string model = 21; // device hardware model
optional uint32 fw_major = 22; // reported firmware version if in bootloader mode
optional uint32 fw_minor = 23; // reported firmware version if in bootloader mode
optional uint32 fw_patch = 24; // reported firmware version if in bootloader mode
optional string fw_vendor = 25; // reported firmware vendor if in bootloader mode
optional bytes fw_vendor_keys = 26; // reported firmware vendor keys (their hash)
}
/**

View File

@ -219,6 +219,7 @@ class VendorHeader(object):
for i in range(self.vsig_n):
print(' * vpub #%d :' % (i + 1), binascii.hexlify(self.vpub[i]).decode())
print(' * vstr :', self.vstr.decode())
print(' * vhash :', binascii.hexlify(self.vhash()).decode())
print(' * vimg : (%d bytes)' % len(self.vimg))
print(' * sigmask :', format_sigmask(self.sigmask))
print(' * sig :', binascii.hexlify(self.sig).decode())
@ -246,6 +247,16 @@ class VendorHeader(object):
def fingerprint(self):
return pyblake2.blake2s(self.serialize_header(sig=False)).hexdigest()
def vhash(self):
h = pyblake2.blake2s()
h.update(struct.pack('<BB', self.vsig_m, self.vsig_n))
for i in range(8):
if i < self.vsig_n:
h.update(self.vpub[i])
else:
h.update(b'\x00' * 32)
return h.digest()
def sign(self, sigmask, signature):
header = self.serialize_header(sig=False)
assert len(header) == self.hdrlen

@ -1 +1 @@
Subproject commit 13499e256acfdde662b98ea402146ca105fb03b3
Subproject commit 8652df0c692ea4f13042539dcb6bde57b79137bc