diff --git a/.gitignore b/.gitignore index e0baf9ab7d..02982714d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +_attic/ *.o *.a *.d diff --git a/Makefile.include b/Makefile.include index 7651370950..7f4d4f1ed9 100644 --- a/Makefile.include +++ b/Makefile.include @@ -90,8 +90,8 @@ flash2: $(NAME).hex -c "reset" \ -c "shutdown" -upload: - ../../python-trezor/trezorctl firmware_update -f $(NAME).bin +upload: sign + trezorctl firmware_update -f $(NAME).bin sign: $(NAME).bin ../bootloader/firmware_sign.py -f $(NAME).bin @@ -118,10 +118,10 @@ $(NAME).elf: $(OBJS) $(LDSCRIPT) $(TOOLCHAIN_DIR)/lib/libopencm3_stm32f2.a $(TOP $(LD) -o $(NAME).elf $(OBJS) -ltrezor -lopencm3_stm32f2 $(LDFLAGS) %.o: %.c Makefile - $(CC) $(CFLAGS) -o $@ -c $< + $(CC) $(CFLAGS) -MMD -o $@ -c $< %.small.o: %.c Makefile - $(CC) $(CFLAGS) -o $@ -c $< + $(CC) $(CFLAGS) -MMD -o $@ -c $< clean: rm -f $(OBJS) @@ -133,3 +133,5 @@ clean: rm -f *.list rm -f *.log rm -f *.srec + +-include $(OBJS:.o=.d) diff --git a/README.md b/README.md index e198cd421e..0b1c82d7a9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/trezor/trezor-mcu.svg?branch=master)](https://travis-ci.org/trezor/trezor-mcu) [![gitter](https://badges.gitter.im/trezor/community.svg)](https://gitter.im/trezor/community) -http://bitcointrezor.com/ +https://trezor.io/ ## How to build TREZOR firmware? @@ -24,8 +24,8 @@ This creates file `output/bootloader.bin` and prints its fingerprint and size at ## How to get fingerprint of firmware signed and distributed by SatoshiLabs? -1. Pick version of firmware binary listed on https://wallet.mytrezor.com/data/firmware/releases.json -2. Download it: `wget -O trezor.signed.bin https://wallet.mytrezor.com/data/firmware/trezor-1.3.6.bin` +1. Pick version of firmware binary listed on https://wallet.trezor.io/data/firmware/releases.json +2. Download it: `wget -O trezor.signed.bin https://wallet.trezor.io/data/firmware/trezor-1.3.6.bin` 3. `./firmware-fingerprint.sh trezor.signed.bin` Step 3 should produce the same sha256 fingerprint like your local build (for the same version tag). diff --git a/bootloader/ChangeLog b/bootloader/ChangeLog new file mode 100644 index 0000000000..15453e7ac1 --- /dev/null +++ b/bootloader/ChangeLog @@ -0,0 +1,19 @@ +Version 1.3.1 +* Fix button testing so it does not break USB communication + +Version 1.3.0 +* Add test for buttons +* Clean USB descriptor +* Return firmware_present in Features response +* Don't halt on broken firware, stay in bootloader + +Version 1.2.7 +* Optimize speed of firmware update + +Version 1.2.6 +* Show hash of unofficial firmware +* Use stack protector +* Clean USB descriptor + +Version 1.2.5 +* Initial import of code diff --git a/bootloader/bootloader.c b/bootloader/bootloader.c index cf1e7d1e0e..a87135917a 100644 --- a/bootloader/bootloader.c +++ b/bootloader/bootloader.c @@ -50,7 +50,7 @@ void layoutFirmwareHash(uint8_t *hash) void show_halt(void) { - layoutDialog(&bmp_icon_error, NULL, NULL, NULL, "Unofficial firmware", "aborted.", NULL, "Unplug your TREZOR", "and see our support", "page at mytrezor.com"); + layoutDialog(&bmp_icon_error, NULL, NULL, NULL, "Unofficial firmware", "aborted.", NULL, "Unplug your TREZOR", "contact our support.", NULL); system_halt(); } diff --git a/bootloader/combine/prepare.py b/bootloader/combine/prepare.py index 0d463117c2..eb073e9820 100755 --- a/bootloader/combine/prepare.py +++ b/bootloader/combine/prepare.py @@ -1,10 +1,12 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python +from __future__ import print_function + bl = open('bl.bin').read() fw = open('fw.bin').read() combined = bl + fw[:256] + (32768-256)*'\x00' + fw[256:] open('combined.bin', 'w').write(combined) -print 'bootloader : %d bytes' % len(bl) -print 'firmware : %d bytes' % len(fw) -print 'combined : %d bytes' % len(combined) +print('bootloader : %d bytes' % len(bl)) +print('firmware : %d bytes' % len(fw)) +print('combined : %d bytes' % len(combined)) diff --git a/bootloader/firmware_align.py b/bootloader/firmware_align.py index d0376784fa..5be6e7163d 100755 --- a/bootloader/firmware_align.py +++ b/bootloader/firmware_align.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python import sys import os diff --git a/bootloader/firmware_sign.py b/bootloader/firmware_sign.py index 7ccd8e99a3..09650a6ab7 100755 --- a/bootloader/firmware_sign.py +++ b/bootloader/firmware_sign.py @@ -1,10 +1,16 @@ -#!/usr/bin/env python2 +#!/usr/bin/python +from __future__ import print_function import argparse import hashlib import struct import binascii import ecdsa +try: + raw_input +except: + raw_input = input + SLOTS = 3 pubkeys = { @@ -31,17 +37,17 @@ def prepare(data): # Takes raw OR signed firmware and clean out metadata structure # This produces 'clean' data for signing - meta = 'TRZR' # magic - if data[:4] == 'TRZR': + meta = b'TRZR' # magic + if data[:4] == b'TRZR': meta += data[4:4 + struct.calcsize(' FLASH_TOTAL_SIZE + FLASH_META_DESC_LEN - (FLASH_APP_START - FLASH_ORIGIN)) { // firmware is too big send_msg_failure(dev); flash_state = STATE_END; - layoutDialog(&bmp_icon_error, NULL, NULL, NULL, "Firmware is too big.", NULL, "Get official firmware", "from mytrezor.com", NULL, NULL); + layoutDialog(&bmp_icon_error, NULL, NULL, NULL, "Firmware is too big.", NULL, "Get official firmware", "from trezor.io/start", NULL, NULL); return; } sha256_Init(&ctx); diff --git a/ChangeLog b/firmware/ChangeLog similarity index 93% rename from ChangeLog rename to firmware/ChangeLog index 8e2842eb8d..9627710d08 100644 --- a/ChangeLog +++ b/firmware/ChangeLog @@ -1,3 +1,9 @@ +Version 1.4.2 +* Stable release, optional update +* New Matrix-based recovery method +* Minor Ethereum fixes (including EIP-155 replay protection) +* Minor USB, U2F and GPG fixes + Version 1.4.1 * Stable release, optional update * Support for Zcash JoinSplit transactions @@ -36,7 +42,7 @@ Version 1.3.4 * Updated maxfee per kb for coins Version 1.3.3 -* Stable release, optional update +* Stable release, required update * Ask for PIN on GetAddress and GetPublicKey * Signing speed improved diff --git a/firmware/ethereum.c b/firmware/ethereum.c index 5284795b84..a7342391ad 100644 --- a/firmware/ethereum.c +++ b/firmware/ethereum.c @@ -35,6 +35,7 @@ static bool ethereum_signing = false; static uint32_t data_total, data_left; static EthereumTxRequest resp; static uint8_t privkey[32]; +static uint8_t chain_id; struct SHA3_CTX keccak_ctx; static inline void hash_data(const uint8_t *buf, size_t size) @@ -150,6 +151,15 @@ static void send_signature(void) uint8_t hash[32], sig[64]; uint8_t v; layoutProgress("Signing", 1000); + + /* eip-155 replay protection */ + if (chain_id != 0) { + /* hash v=chain_id, r=0, s=0 */ + hash_rlp_field(&chain_id, 1); + hash_rlp_length(0, 0); + hash_rlp_length(0, 0); + } + keccak_Final(&keccak_ctx, hash); if (ecdsa_sign_digest(&secp256k1, privkey, hash, sig, &v, ethereum_is_canonic) != 0) { fsm_sendFailure(FailureType_Failure_Other, "Signing failed"); @@ -163,7 +173,11 @@ static void send_signature(void) resp.has_data_length = false; resp.has_signature_v = true; - resp.signature_v = v + 27; + if (chain_id) { + resp.signature_v = v + 2 * chain_id + 35; + } else { + resp.signature_v = v + 27; + } resp.has_signature_r = true; resp.signature_r.size = 32; @@ -228,7 +242,11 @@ static void ethereumFormatAmount(bignum256 *val, char buffer[25]) // remove trailing dot. if (value_ptr[-1] == '.') value_ptr--; - strcpy(value_ptr, " ETH"); + if (chain_id == 61 || chain_id == 62) { + strcpy(value_ptr, " ETC"); + } else { + strcpy(value_ptr, " ETH"); + } // value is at most 16 + 4 + 1 characters long } else { // value is bigger than 1e9 ETH => won't fit on display (probably won't happen unless you are Vitalik) @@ -383,7 +401,7 @@ static void layoutEthereumFee(const uint8_t *value, uint32_t value_len, static bool ethereum_signing_check(EthereumSignTx *msg) { - if (!msg->has_nonce || !msg->has_gas_price || !msg->has_gas_limit) { + if (!msg->has_gas_price || !msg->has_gas_limit) { return false; } @@ -418,13 +436,22 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) msg->data_initial_chunk.size = 0; if (!msg->has_to) msg->to.size = 0; + if (!msg->has_nonce) + msg->nonce.size = 0; - if (msg->has_data_length) { - if (msg->data_length == 0) { - fsm_sendFailure(FailureType_Failure_Other, "Invalid data length provided"); + /* eip-155 chain id */ + if (msg->has_chain_id) { + if (msg->chain_id < 1 || msg->chain_id > 109) { + fsm_sendFailure(FailureType_Failure_Other, "Chain Id out of bounds"); ethereum_signing_abort(); return; } + chain_id = (uint8_t) msg->chain_id; + } else { + chain_id = 0; + } + + if (msg->has_data_length && msg->data_length > 0) { if (!msg->has_data_initial_chunk || msg->data_initial_chunk.size == 0) { fsm_sendFailure(FailureType_Failure_Other, "Data length provided, but no initial chunk"); ethereum_signing_abort(); @@ -491,6 +518,11 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) rlp_length += rlp_calculate_length(msg->to.size, msg->to.bytes[0]); rlp_length += rlp_calculate_length(msg->value.size, msg->value.bytes[0]); rlp_length += rlp_calculate_length(data_total, msg->data_initial_chunk.bytes[0]); + if (chain_id) { + rlp_length += rlp_calculate_length(1, chain_id); + rlp_length += rlp_calculate_length(0, 0); + rlp_length += rlp_calculate_length(0, 0); + } /* Stage 2: Store header fields */ hash_rlp_list_length(rlp_length); diff --git a/firmware/layout2.c b/firmware/layout2.c index 7bedc833b8..bb6516a9ec 100644 --- a/firmware/layout2.c +++ b/firmware/layout2.c @@ -65,7 +65,7 @@ void layoutHome(void) oledSwipeLeft(); } layoutLast = layoutHome; - const char *label = storage_isInitialized() ? storage_getLabel() : "Go to mytrezor.com"; + const char *label = storage_isInitialized() ? storage_getLabel() : "Go to trezor.io/start"; const uint8_t *homescreen = storage_getHomescreen(); if (homescreen) { BITMAP b; @@ -319,10 +319,12 @@ void layoutSignIdentity(const IdentityType *identity, const char *challenge) char row_hostport[64 + 6 + 1]; char row_user[64 + 8 + 1]; + bool is_gpg = (strcmp(identity->proto, "gpg") == 0); + if (identity->has_proto && identity->proto[0]) { if (strcmp(identity->proto, "https") == 0) { strlcpy(row_proto, "Web sign in to:", sizeof(row_proto)); - } else if (strcmp(identity->proto, "gpg") == 0) { + } else if (is_gpg) { strlcpy(row_proto, "GPG sign for:", sizeof(row_proto)); } else { strlcpy(row_proto, identity->proto, sizeof(row_proto)); @@ -351,6 +353,21 @@ void layoutSignIdentity(const IdentityType *identity, const char *challenge) row_user[0] = 0; } + if (is_gpg) { + // Split "First Last " into 2 lines: + // "First Last" + // "first@last.com" + char *email_start = strchr(row_hostport, '<'); + if (email_start) { + strlcpy(row_user, email_start + 1, sizeof(row_user)); + *email_start = 0; + char *email_end = strchr(row_user, '>'); + if (email_end) { + *email_end = 0; + } + } + } + layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", "Do you want to sign in?", row_proto[0] ? row_proto : NULL, diff --git a/firmware/protob/Makefile b/firmware/protob/Makefile index f9dd9c718a..5b8d69e038 100644 --- a/firmware/protob/Makefile +++ b/firmware/protob/Makefile @@ -1,7 +1,7 @@ all: messages.pb.c storage.pb.c types.pb.c %.pb.c: %.pb %.options - nanopb $< -L '#include "%s"' -T + nanopb_generator.py $< -L '#include "%s"' -T %.pb: %.proto protoc -I/usr/include -I. $< -o $@ diff --git a/firmware/protob/messages.pb.c b/firmware/protob/messages.pb.c index 7decf55dc0..7011ece5d2 100644 --- a/firmware/protob/messages.pb.c +++ b/firmware/protob/messages.pb.c @@ -336,7 +336,7 @@ const pb_field_t TxAck_fields[2] = { PB_LAST_FIELD }; -const pb_field_t EthereumSignTx_fields[9] = { +const pb_field_t EthereumSignTx_fields[10] = { PB_FIELD2( 1, UINT32 , REPEATED, STATIC , FIRST, EthereumSignTx, address_n, address_n, 0), PB_FIELD2( 2, BYTES , OPTIONAL, STATIC , OTHER, EthereumSignTx, nonce, address_n, 0), PB_FIELD2( 3, BYTES , OPTIONAL, STATIC , OTHER, EthereumSignTx, gas_price, nonce, 0), @@ -345,6 +345,7 @@ const pb_field_t EthereumSignTx_fields[9] = { PB_FIELD2( 6, BYTES , OPTIONAL, STATIC , OTHER, EthereumSignTx, value, to, 0), PB_FIELD2( 7, BYTES , OPTIONAL, STATIC , OTHER, EthereumSignTx, data_initial_chunk, value, 0), PB_FIELD2( 8, UINT32 , OPTIONAL, STATIC , OTHER, EthereumSignTx, data_length, data_initial_chunk, 0), + PB_FIELD2( 9, UINT32 , OPTIONAL, STATIC , OTHER, EthereumSignTx, chain_id, data_length, 0), PB_LAST_FIELD }; diff --git a/firmware/protob/messages.pb.h b/firmware/protob/messages.pb.h index fe362eb84a..3afe901140 100644 --- a/firmware/protob/messages.pb.h +++ b/firmware/protob/messages.pb.h @@ -460,6 +460,8 @@ typedef struct _EthereumSignTx { EthereumSignTx_data_initial_chunk_t data_initial_chunk; bool has_data_length; uint32_t data_length; + bool has_chain_id; + uint32_t chain_id; } EthereumSignTx; typedef struct { @@ -894,7 +896,7 @@ extern const uint32_t SimpleSignTx_lock_time_default; #define SimpleSignTx_init_default {0, {}, 0, {}, 0, {}, false, "Bitcoin", false, 1u, false, 0u} #define TxRequest_init_default {false, (RequestType)0, false, TxRequestDetailsType_init_default, false, TxRequestSerializedType_init_default} #define TxAck_init_default {false, TransactionType_init_default} -#define EthereumSignTx_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, 0} +#define EthereumSignTx_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, 0, false, 0} #define EthereumTxRequest_init_default {false, 0, false, 0, false, {0, {0}}, false, {0, {0}}} #define EthereumTxAck_init_default {false, {0, {0}}} #define SignIdentity_init_default {false, IdentityType_init_default, false, {0, {0}}, false, "", false, ""} @@ -960,7 +962,7 @@ extern const uint32_t SimpleSignTx_lock_time_default; #define SimpleSignTx_init_zero {0, {}, 0, {}, 0, {}, false, "", false, 0, false, 0} #define TxRequest_init_zero {false, (RequestType)0, false, TxRequestDetailsType_init_zero, false, TxRequestSerializedType_init_zero} #define TxAck_init_zero {false, TransactionType_init_zero} -#define EthereumSignTx_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, 0} +#define EthereumSignTx_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, {0, {0}}, false, 0, false, 0} #define EthereumTxRequest_init_zero {false, 0, false, 0, false, {0, {0}}, false, {0, {0}}} #define EthereumTxAck_init_zero {false, {0, {0}}} #define SignIdentity_init_zero {false, IdentityType_init_zero, false, {0, {0}}, false, "", false, ""} @@ -1049,6 +1051,7 @@ extern const uint32_t SimpleSignTx_lock_time_default; #define EthereumSignTx_value_tag 6 #define EthereumSignTx_data_initial_chunk_tag 7 #define EthereumSignTx_data_length_tag 8 +#define EthereumSignTx_chain_id_tag 9 #define EthereumTxAck_data_chunk_tag 1 #define EthereumTxRequest_data_length_tag 1 #define EthereumTxRequest_signature_v_tag 2 @@ -1204,7 +1207,7 @@ extern const pb_field_t SignTx_fields[6]; extern const pb_field_t SimpleSignTx_fields[7]; extern const pb_field_t TxRequest_fields[4]; extern const pb_field_t TxAck_fields[2]; -extern const pb_field_t EthereumSignTx_fields[9]; +extern const pb_field_t EthereumSignTx_fields[10]; extern const pb_field_t EthereumTxRequest_fields[5]; extern const pb_field_t EthereumTxAck_fields[2]; extern const pb_field_t SignIdentity_fields[5]; @@ -1272,7 +1275,7 @@ extern const pb_field_t DebugLinkFlashErase_fields[2]; #define SimpleSignTx_size (31 + 0*TxInputType_size + 0*TxOutputType_size + 0*TransactionType_size) #define TxRequest_size (18 + TxRequestDetailsType_size + TxRequestSerializedType_size) #define TxAck_size (6 + TransactionType_size) -#define EthereumSignTx_size 1239 +#define EthereumSignTx_size 1245 #define EthereumTxRequest_size 80 #define EthereumTxAck_size 1027 #define SignIdentity_size (558 + IdentityType_size) diff --git a/firmware/recovery.c b/firmware/recovery.c index 17e68385f7..41083dd23e 100644 --- a/firmware/recovery.c +++ b/firmware/recovery.c @@ -214,7 +214,7 @@ static void display_choices(bool twoColumn, char choices[9][12], int num) format_number(desc, nr); layoutDialogSwipe(&bmp_icon_info, NULL, NULL, NULL, "Please enter the", (nr < 10 ? desc + 1 : desc), "of your mnemonic", NULL, NULL, NULL); } else { - oledBox(0, 18, 127, 63, false); + oledBox(0, 27, 127, 63, false); } for (row = 0; row < 3; row ++) { @@ -224,6 +224,11 @@ static void display_choices(bool twoColumn, char choices[9][12], int num) int choice = word_matrix[nColumns*row + col]; const char *text = choice < num ? choices[choice] : "-"; oledDrawString(x - oledStringWidth(text)/2, y, text); + if (twoColumn) { + oledInvert(x - 32 + 1, y - 1, x - 32 + 63 - 1, y + 8); + } else { + oledInvert(x - 22 + 1, y - 1, x - 22 + 41 - 1, y + 8); + } } } oledRefresh(); @@ -324,7 +329,7 @@ static void recovery_digit(const char digit) { /* received final word */ int y = 54 - ((digit - '1')/3)*11; int x = 64 * (((digit - '1') % 3) > 0); - oledInvert(x, y, x + 63, y + 9); + oledInvert(x + 1, y, x + 62, y + 9); oledRefresh(); usbSleep(250); diff --git a/firmware/trezor.c b/firmware/trezor.c index 6e491691a7..56c74d491a 100644 --- a/firmware/trezor.c +++ b/firmware/trezor.c @@ -99,11 +99,8 @@ int main(void) timer_init(); -#if DEBUG_LOG - oledSetDebug(1); -#endif - #if DEBUG_LINK + oledSetDebugLink(1); storage_reset(); // wipe storage if debug link storage_reset_uuid(); storage_commit(); diff --git a/firmware/trezor.h b/firmware/trezor.h index 72cc0fb9ce..4303afc601 100644 --- a/firmware/trezor.h +++ b/firmware/trezor.h @@ -22,7 +22,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 4 -#define VERSION_PATCH 1 +#define VERSION_PATCH 2 #define STR(X) #X #define VERSTR(X) STR(X) diff --git a/firmware/u2f.c b/firmware/u2f.c index ddf560209e..6c246175c7 100644 --- a/firmware/u2f.c +++ b/firmware/u2f.c @@ -505,6 +505,12 @@ const HDNode *validateKeyHandle(const uint8_t app_id[], const uint8_t key_handle uint32_t key_path[KEY_PATH_ENTRIES]; key_path[0] = U2F_KEY_PATH; memcpy(&key_path[1], key_handle, KEY_PATH_LEN); + for (unsigned int i = 1; i < KEY_PATH_ENTRIES; i++) { + // check high bit for hardened keys + if (! (key_path[i] & 0x80000000)) { + return NULL; + } + } const HDNode *node = getDerivedNode(key_path, KEY_PATH_ENTRIES); if (!node) diff --git a/firmware/usb.c b/firmware/usb.c index 77576e48e8..0bd7aed821 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -44,6 +44,27 @@ #define ENDPOINT_ADDRESS_U2F_IN (0x83) #define ENDPOINT_ADDRESS_U2F_OUT (0x03) +#define USB_STRINGS \ + X(MANUFACTURER, "SatoshiLabs") \ + X(PRODUCT, "TREZOR") \ + X(SERIAL_NUMBER, storage_uuid_str) \ + X(INTERFACE_MAIN, "TREZOR Interface") \ + X(INTERFACE_DEBUG, "TREZOR Debug Link Interface") \ + X(INTERFACE_U2F, "U2F Interface") + +#define X(name, value) USB_STRING_##name, +enum { + USB_STRING_LANGID_CODES, // LANGID code array + USB_STRINGS +}; +#undef X + +#define X(name, value) value, +static const char *usb_strings[] = { + USB_STRINGS +}; +#undef X + static const struct usb_device_descriptor dev_descr = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, @@ -55,9 +76,9 @@ static const struct usb_device_descriptor dev_descr = { .idVendor = 0x534c, .idProduct = 0x0001, .bcdDevice = 0x0100, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, + .iManufacturer = USB_STRING_MANUFACTURER, + .iProduct = USB_STRING_PRODUCT, + .iSerialNumber = USB_STRING_SERIAL_NUMBER, .bNumConfigurations = 1, }; @@ -186,7 +207,7 @@ static const struct usb_interface_descriptor hid_iface[] = {{ .bInterfaceClass = USB_CLASS_HID, .bInterfaceSubClass = 0, .bInterfaceProtocol = 0, - .iInterface = 0, + .iInterface = USB_STRING_INTERFACE_MAIN, .endpoint = hid_endpoints, .extra = &hid_function, .extralen = sizeof(hid_function), @@ -217,7 +238,7 @@ static const struct usb_interface_descriptor hid_iface_u2f[] = {{ .bInterfaceClass = USB_CLASS_HID, .bInterfaceSubClass = 0, .bInterfaceProtocol = 0, - .iInterface = 0, + .iInterface = USB_STRING_INTERFACE_U2F, .endpoint = hid_endpoints_u2f, .extra = &hid_function_u2f, .extralen = sizeof(hid_function_u2f), @@ -249,7 +270,7 @@ static const struct usb_interface_descriptor hid_iface_debug[] = {{ .bInterfaceClass = USB_CLASS_HID, .bInterfaceSubClass = 0, .bInterfaceProtocol = 0, - .iInterface = 0, + .iInterface = USB_STRING_INTERFACE_DEBUG, .endpoint = hid_endpoints_debug, .extra = &hid_function, .extralen = sizeof(hid_function), @@ -285,12 +306,6 @@ static const struct usb_config_descriptor config = { .interface = ifaces, }; -static const char *usb_strings[] = { - "SatoshiLabs", - "TREZOR", - (const char *)storage_uuid_str, -}; - static int hid_control_request(usbd_device *dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, usbd_control_complete_callback *complete) { (void)complete; @@ -388,7 +403,7 @@ static uint8_t usbd_control_buffer[128]; void usbInit(void) { - usbd_dev = usbd_init(&otgfs_usb_driver, &dev_descr, &config, usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer)); + usbd_dev = usbd_init(&otgfs_usb_driver, &dev_descr, &config, usb_strings, sizeof(usb_strings) / sizeof(*usb_strings), usbd_control_buffer, sizeof(usbd_control_buffer)); usbd_register_set_config_callback(usbd_dev, hid_set_config); } diff --git a/gen/bitmaps/generate.py b/gen/bitmaps/generate.py index bc987dd59f..21d72a6def 100755 --- a/gen/bitmaps/generate.py +++ b/gen/bitmaps/generate.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python +from __future__ import print_function import glob import os from PIL import Image @@ -10,14 +11,14 @@ imgs = [] def encode_pixels(img): r = '' img = [ (x[0] + x[1] + x[2] > 384 and '1' or '0') for x in img] - for i in range(len(img) / 8): + for i in range(len(img) // 8): c = ''.join(img[i * 8 : i * 8 + 8]) r += '0x%02x, ' % int(c, 2) return r cnt = 0 for fn in sorted(glob.glob('*.png')): - print 'Processing:', fn + print('Processing:', fn) im = Image.open(fn) name = os.path.splitext(fn)[0] w, h = im.size diff --git a/gen/fonts/generate.py b/gen/fonts/generate.py index 8f166f82a7..ec8b0aa4bf 100755 --- a/gen/fonts/generate.py +++ b/gen/fonts/generate.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python +from __future__ import print_function from PIL import Image class Img(object): @@ -23,12 +24,12 @@ cur = '' for i in range(256): x = (i % 16) * 10 - y = (i / 16) * 10 + y = (i // 16) * 10 cur = '' while img.pixel(x, y) != None: val = ''.join(img.pixel(x, y + j) for j in range(8)) x += 1 cur += '\\x%02x' % int(val, 2) - cur = '\\x%02x' % (len(cur) / 4) + cur + cur = '\\x%02x' % (len(cur) // 4) + cur ch = chr(i) if i >= 32 and i <= 126 else '_' - print '\t/* 0x%02x %c */ (uint8_t *)"%s",' % (i, ch , cur) + print('\t/* 0x%02x %c */ (uint8_t *)"%s",' % (i, ch , cur)) diff --git a/gen/handlers/handlers.py b/gen/handlers/handlers.py index ae1635b5f5..5e79610675 100755 --- a/gen/handlers/handlers.py +++ b/gen/handlers/handlers.py @@ -1,4 +1,6 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python +from __future__ import print_function + handlers = [ 'hard_fault_handler', 'mem_manage_handler', diff --git a/memory.c b/memory.c index c9ed483a6f..f779c2037c 100644 --- a/memory.c +++ b/memory.c @@ -27,13 +27,23 @@ void memory_protect(void) { + // Reference STM32F205 Flash programming manual revision 5 http://www.st.com/resource/en/programming_manual/cd00233952.pdf + // Section 2.6 Option bytes // set RDP level 2 WRP for sectors 0 and 1 - if ((((*OPTION_BYTES_1) & 0xFFFF) == 0xCCFF) && (((*OPTION_BYTES_2) & 0xFFFF) == 0xFFFC)) { + if ((((*OPTION_BYTES_1) & 0xFFEC) == 0xCCEC) && (((*OPTION_BYTES_2) & 0xFFF) == 0xFFC)) { return; // already set up correctly - bail out } flash_unlock_option_bytes(); - // WRP + RDP - flash_program_option_bytes(0xFFFC0000 + 0xCCFF); + // Section 2.8.6 Flash option control register (FLASH_OPTCR) + // Bits 31:28 Reserved, must be kept cleared. + // Bits 27:16 nWRP: Not write protect: write protect bootloader code in flash main memory sectors 0 and 1 (Section 2.3; table 2) + // Bits 15:8 RDP: Read protect: level 2 chip read protection active + // Bits 7:5 USER: User option bytes: no reset on standby, no reset on stop, software watchdog + // Bit 4 Reserved, must be kept cleared. + // Bits 3:2 BOR_LEV: BOR reset Level: BOR off + // Bit 1 OPTSTRT: Option start: ignored by flash_program_option_bytes + // Bit 0 OPTLOCK: Option lock: ignored by flash_program_option_bytes + flash_program_option_bytes(0x0FFCCCEC); flash_lock_option_bytes(); } diff --git a/oled.c b/oled.c index 926428e775..095bb02fda 100644 --- a/oled.c +++ b/oled.c @@ -74,7 +74,7 @@ #define OLED_BUFTGL(X,Y) _oledbuffer[OLED_BUFSIZE - 1 - (X) - ((Y)/8)*OLED_WIDTH] ^= (1 << (7 - (Y)%8)) static uint8_t _oledbuffer[OLED_BUFSIZE]; -static bool is_debug_mode = 0; +static bool is_debug_link = 0; /* * Send a block of data via the SPI bus. @@ -161,7 +161,7 @@ void oledRefresh() static uint8_t s[3] = {OLED_SETLOWCOLUMN | 0x00, OLED_SETHIGHCOLUMN | 0x00, OLED_SETSTARTLINE | 0x00}; // draw triangle in upper right corner - if (is_debug_mode) { + if (is_debug_link) { OLED_BUFTGL(OLED_WIDTH - 5, 0); OLED_BUFTGL(OLED_WIDTH - 4, 0); OLED_BUFTGL(OLED_WIDTH - 3, 0); OLED_BUFTGL(OLED_WIDTH - 2, 0); OLED_BUFTGL(OLED_WIDTH - 1, 0); OLED_BUFTGL(OLED_WIDTH - 4, 1); OLED_BUFTGL(OLED_WIDTH - 3, 1); OLED_BUFTGL(OLED_WIDTH - 2, 1); OLED_BUFTGL(OLED_WIDTH - 1, 1); OLED_BUFTGL(OLED_WIDTH - 3, 2); OLED_BUFTGL(OLED_WIDTH - 2, 2); OLED_BUFTGL(OLED_WIDTH - 1, 2); @@ -180,7 +180,7 @@ void oledRefresh() gpio_clear(OLED_DC_PORT, OLED_DC_PIN); // set to CMD // return it back - if (is_debug_mode) { + if (is_debug_link) { OLED_BUFTGL(OLED_WIDTH - 5, 0); OLED_BUFTGL(OLED_WIDTH - 4, 0); OLED_BUFTGL(OLED_WIDTH - 3, 0); OLED_BUFTGL(OLED_WIDTH - 2, 0); OLED_BUFTGL(OLED_WIDTH - 1, 0); OLED_BUFTGL(OLED_WIDTH - 4, 1); OLED_BUFTGL(OLED_WIDTH - 3, 1); OLED_BUFTGL(OLED_WIDTH - 2, 1); OLED_BUFTGL(OLED_WIDTH - 1, 1); OLED_BUFTGL(OLED_WIDTH - 3, 2); OLED_BUFTGL(OLED_WIDTH - 2, 2); OLED_BUFTGL(OLED_WIDTH - 1, 2); @@ -194,9 +194,9 @@ const uint8_t *oledGetBuffer() return _oledbuffer; } -void oledSetDebug(bool set) +void oledSetDebugLink(bool set) { - is_debug_mode = set; + is_debug_link = set; oledRefresh(); } diff --git a/oled.h b/oled.h index 6fccc363ad..05b8b0b376 100644 --- a/oled.h +++ b/oled.h @@ -34,7 +34,7 @@ void oledInit(void); void oledClear(void); void oledRefresh(void); -void oledSetDebug(bool set); +void oledSetDebugLink(bool set); void oledSetBuffer(uint8_t *buf); const uint8_t *oledGetBuffer(void); void oledDrawPixel(int x, int y); diff --git a/vendor/trezor-common b/vendor/trezor-common index 61af3d5e93..9d2ab7318d 160000 --- a/vendor/trezor-common +++ b/vendor/trezor-common @@ -1 +1 @@ -Subproject commit 61af3d5e931ab41f0b81f462fbdc626d6bbec4f4 +Subproject commit 9d2ab7318db08a47b35588b0593fb66129214f8d