Skip to content

Commit 65d42d3

Browse files
committed
Merge branch 'eip712-newlines'
2 parents 3b6db91 + 732c33f commit 65d42d3

File tree

2 files changed

+140
-16
lines changed

2 files changed

+140
-16
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ customers cannot upgrade their bootloader, its changes are recorded separately.
77
## Firmware
88

99
### [Unreleased]
10+
- Ethereum: allow signing EIP-712 messages containing multi-line strings
1011

1112
### 9.18.0
1213
- Add support for deriving BIP-39 mnemonics according to BIP-85

src/rust/bitbox02-rust/src/hww/api/ethereum/sign_typed_msg.rs

Lines changed: 139 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ fn encode_value(typ: &MemberType, value: Vec<u8>) -> Result<(Vec<u8>, String), E
257257
)
258258
}
259259
DataType::String => {
260-
if !util::ascii::is_printable_ascii(&value, util::ascii::Charset::All) {
260+
if !util::ascii::is_printable_ascii(&value, util::ascii::Charset::AllNewline) {
261261
return Err(Error::InvalidInput);
262262
}
263263
(
@@ -312,18 +312,30 @@ async fn encode_member<U: sha3::digest::Update>(
312312
} else {
313313
let value = get_value_from_host(root_object, path).await?;
314314
let (value_encoded, value_formatted) = encode_value(member_type, value)?;
315-
confirm::confirm(&confirm::Params {
316-
title: &format!(
317-
"{}{}",
318-
confirm_title(root_object),
319-
title_suffix.as_deref().unwrap_or("")
320-
),
321-
body: &format!("{}: {}", formatted_path.join("."), value_formatted),
322-
scrollable: true,
323-
accept_is_nextarrow: true,
324-
..Default::default()
325-
})
326-
.await?;
315+
let lines: Vec<&str> = value_formatted.split('\n').collect();
316+
for (i, &line) in lines.iter().enumerate() {
317+
confirm::confirm(&confirm::Params {
318+
title: &format!(
319+
"{}{}",
320+
confirm_title(root_object),
321+
title_suffix.as_deref().unwrap_or("")
322+
),
323+
body: &format!(
324+
"{}{}: {}",
325+
formatted_path.join("."),
326+
if lines.len() > 1 {
327+
format!(", line {}/{}", i + 1, lines.len())
328+
} else {
329+
"".into()
330+
},
331+
line
332+
),
333+
scrollable: true,
334+
accept_is_nextarrow: true,
335+
..Default::default()
336+
})
337+
.await?;
338+
}
327339
hasher.update(&value_encoded);
328340
}
329341
Ok(())
@@ -1031,7 +1043,7 @@ mod tests {
10311043
/// str: 'str',
10321044
/// emptyArray: [],
10331045
/// name_address: '0xa21A16EC22a940990922220E4ab5bF4C2310F556',
1034-
/// name_string: ['', 'a', 'aa', '|@#!$', 'long long long long long long long long'],
1046+
/// name_string: ['', 'a', 'aa', '|@#!$', 'long long long long long long long long', 'multi\n\nline'],
10351047
/// name_bytes: ['', '0xaabbcc'],
10361048
/// name_bytes1: '0xaa',
10371049
/// name_bytes10: '0x112233445566778899aa',
@@ -1058,6 +1070,109 @@ mod tests {
10581070
/// ```
10591071
#[test]
10601072
fn test_exhaustive_data() {
1073+
const EXPECTED_DIALOGS: &[(&str, &str)] = &[
1074+
("Domain (1/4)", "name: Ether Mail"),
1075+
("Domain (2/4)", "version: 1"),
1076+
("Domain (3/4)", "chainId: 1"),
1077+
(
1078+
"Domain (4/4)",
1079+
"verifyingContract: 0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
1080+
),
1081+
("Message (1/23)", "str: str"),
1082+
("Message (2/23)", "emptyArray: (empty list)"),
1083+
("Message (3/23)", "name_address: 0xa21A16EC22a940990922220E4ab5bF4C2310F556"),
1084+
("Message (4/23)", "name_string: list with 6 elements"),
1085+
("Message (4/23)", "name_string[1/6]: "),
1086+
("Message (4/23)", "name_string[2/6]: a"),
1087+
("Message (4/23)", "name_string[3/6]: aa"),
1088+
("Message (4/23)", "name_string[4/6]: |@#!$"),
1089+
("Message (4/23)", "name_string[5/6]: long long long long long long long long"),
1090+
("Message (4/23)", "name_string[6/6], line 1/3: multi"),
1091+
("Message (4/23)", "name_string[6/6], line 2/3: "),
1092+
("Message (4/23)", "name_string[6/6], line 3/3: line"),
1093+
("Message (5/23)", "name_bytes: list with 2 elements"),
1094+
("Message (5/23)", "name_bytes[1/2]: 0x"),
1095+
("Message (5/23)", "name_bytes[2/2]: 0xaabbcc"),
1096+
("Message (6/23)", "name_bytes1: 0xaa"),
1097+
("Message (7/23)", "name_bytes10: 0x112233445566778899aa"),
1098+
("Message (8/23)", "name_bytes32: 0xd0f02988fd881565e927c7473c287322db166901bac03bef55d7a52a5c750ab4"),
1099+
("Message (9/23)", "name_uint8: list with 4 elements"),
1100+
("Message (9/23)", "name_uint8[1/4]: 0"),
1101+
("Message (9/23)", "name_uint8[2/4]: 1"),
1102+
("Message (9/23)", "name_uint8[3/4]: 10"),
1103+
("Message (9/23)", "name_uint8[4/4]: 255"),
1104+
("Message (10/23)", "name_uint32: list with 4 elements"),
1105+
("Message (10/23)", "name_uint32[1/4]: 0"),
1106+
("Message (10/23)", "name_uint32[2/4]: 256"),
1107+
("Message (10/23)", "name_uint32[3/4]: 65536"),
1108+
("Message (10/23)", "name_uint32[4/4]: 4294967295"),
1109+
("Message (11/23)", "name_uint64: 18446744073709551615"),
1110+
("Message (12/23)", "name_uint128: 340282366920938463463374607431768211455"),
1111+
("Message (13/23)", "name_uint256: 115792089237316195423570985008687907853269984665640564039457584007913129639935"),
1112+
("Message (14/23)", "name_int8: list with 5 elements"),
1113+
("Message (14/23)", "name_int8[1/5]: 0"),
1114+
("Message (14/23)", "name_int8[2/5]: 10"),
1115+
("Message (14/23)", "name_int8[3/5]: -10"),
1116+
("Message (14/23)", "name_int8[4/5]: 127"),
1117+
("Message (14/23)", "name_int8[5/5]: -128"),
1118+
("Message (15/23)", "name_int32: list with 2 elements"),
1119+
("Message (15/23)", "name_int32[1/2]: 2147483647"),
1120+
("Message (15/23)", "name_int32[2/2]: -2147483648"),
1121+
("Message (16/23)", "name_int64: list with 4 elements"),
1122+
("Message (16/23)", "name_int64[1/4]: 500"),
1123+
("Message (16/23)", "name_int64[2/4]: -500"),
1124+
("Message (16/23)", "name_int64[3/4]: 9223372036854775807"),
1125+
("Message (16/23)", "name_int64[4/4]: -9223372036854775808"),
1126+
("Message (17/23)", "name_int128: list with 2 elements"),
1127+
("Message (17/23)", "name_int128[1/2]: 170141183460469231731687303715884105727"),
1128+
("Message (17/23)", "name_int128[2/2]: -170141183460469231731687303715884105728"),
1129+
("Message (18/23)", "name_int256: list with 2 elements"),
1130+
("Message (18/23)", "name_int256[1/2]: 57896044618658097711785492504343953926634992332820282019728792003956564819967"),
1131+
("Message (18/23)", "name_int256[2/2]: -57896044618658097711785492504343953926634992332820282019728792003956564819968"),
1132+
("Message (19/23)", "name_bool: list with 2 elements"),
1133+
("Message (19/23)", "name_bool[1/2]: false"),
1134+
("Message (19/23)", "name_bool[2/2]: true"),
1135+
("Message (20/23)", "name_struct.name: struct name"),
1136+
("Message (20/23)", "name_struct.arr: (empty list)"),
1137+
("Message (21/23)", "arrayOfStructs: list with 3 elements"),
1138+
("Message (21/23)", "arrayOfStructs[1/3].name: name 1"),
1139+
("Message (21/23)", "arrayOfStructs[1/3].arr: (empty list)"),
1140+
("Message (21/23)", "arrayOfStructs[2/3].name: name 2"),
1141+
("Message (21/23)", "arrayOfStructs[2/3].arr: list with 1 elements"),
1142+
("Message (21/23)", "arrayOfStructs[2/3].arr[1/1]: false"),
1143+
("Message (21/23)", "arrayOfStructs[3/3].name: name 3"),
1144+
("Message (21/23)", "arrayOfStructs[3/3].arr: list with 2 elements"),
1145+
("Message (21/23)", "arrayOfStructs[3/3].arr[1/2]: false"),
1146+
("Message (21/23)", "arrayOfStructs[3/3].arr[2/2]: true"),
1147+
("Message (22/23)", "fixedArrayOfStructs: list with 2 elements"),
1148+
("Message (22/23)", "fixedArrayOfStructs[1/2].name: name 1"),
1149+
("Message (22/23)", "fixedArrayOfStructs[1/2].arr: (empty list)"),
1150+
("Message (22/23)", "fixedArrayOfStructs[2/2].name: name 2"),
1151+
("Message (22/23)", "fixedArrayOfStructs[2/2].arr: list with 3 elements"),
1152+
("Message (22/23)", "fixedArrayOfStructs[2/2].arr[1/3]: false"),
1153+
("Message (22/23)", "fixedArrayOfStructs[2/2].arr[2/3]: false"),
1154+
("Message (22/23)", "fixedArrayOfStructs[2/2].arr[3/3]: true"),
1155+
("Message (23/23)", "nestedArray: list with 3 elements"),
1156+
("Message (23/23)", "nestedArray[1/3]: list with 2 elements"),
1157+
("Message (23/23)", "nestedArray[1/3][1/2]: list with 2 elements"),
1158+
("Message (23/23)", "nestedArray[1/3][1/2][1/2]: 1"),
1159+
("Message (23/23)", "nestedArray[1/3][1/2][2/2]: 2"),
1160+
("Message (23/23)", "nestedArray[1/3][2/2]: list with 3 elements"),
1161+
("Message (23/23)", "nestedArray[1/3][2/2][1/3]: 3"),
1162+
("Message (23/23)", "nestedArray[1/3][2/2][2/3]: 4"),
1163+
("Message (23/23)", "nestedArray[1/3][2/2][3/3]: 5"),
1164+
("Message (23/23)", "nestedArray[2/3]: list with 2 elements"),
1165+
("Message (23/23)", "nestedArray[2/3][1/2]: list with 2 elements"),
1166+
("Message (23/23)", "nestedArray[2/3][1/2][1/2]: 6"),
1167+
("Message (23/23)", "nestedArray[2/3][1/2][2/2]: 7"),
1168+
("Message (23/23)", "nestedArray[2/3][2/2]: list with 1 elements"),
1169+
("Message (23/23)", "nestedArray[2/3][2/2][1/1]: 8"),
1170+
("Message (23/23)", "nestedArray[3/3]: list with 2 elements"),
1171+
("Message (23/23)", "nestedArray[3/3][1/2]: (empty list)"),
1172+
("Message (23/23)", "nestedArray[3/3][2/2]: list with 1 elements"),
1173+
("Message (23/23)", "nestedArray[3/3][2/2][1/1]: 9"),
1174+
];
1175+
10611176
let bytes32 = b"\xd0\xf0\x29\x88\xfd\x88\x15\x65\xe9\x27\xc7\x47\x3c\x28\x73\x22\xdb\x16\x69\x01\xba\xc0\x3b\xef\x55\xd7\xa5\x2a\x5c\x75\x0a\xb4";
10621177
let bigint256_positive = b"\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
10631178
let bigint256_negative = b"\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
@@ -1152,6 +1267,7 @@ mod tests {
11521267
Object::String("aa"),
11531268
Object::String("|@#!$"),
11541269
Object::String("long long long long long long long long"),
1270+
Object::String("multi\n\nline"),
11551271
]),
11561272
// name_bytes
11571273
Object::List(vec![Object::Bytes(b""), Object::Bytes(b"\xaa\xbb\xcc")]),
@@ -1290,16 +1406,23 @@ mod tests {
12901406
Ok(typed_msg.handle_host_response(&response).unwrap())
12911407
}));
12921408
}
1409+
static mut UI_COUNTER: usize = 0;
12931410
mock(Data {
1294-
ui_confirm_create: Some(Box::new(|_params| true)),
1411+
ui_confirm_create: Some(Box::new(|params| unsafe {
1412+
let expected = EXPECTED_DIALOGS[UI_COUNTER];
1413+
assert_eq!((params.title, params.body), expected);
1414+
UI_COUNTER += 1;
1415+
true
1416+
})),
12951417
..Default::default()
12961418
});
12971419
let typed_msg = typed_msg.borrow();
12981420
let sighash = block_on(eip712_sighash(&typed_msg.types, typed_msg.primary_type)).unwrap();
12991421
assert_eq!(
13001422
sighash,
1301-
*b"\xc5\x4f\xa7\x87\x13\x18\xb6\xc2\xd8\x71\x62\xde\xbe\xff\x4c\xdf\x13\xf2\x85\x45\x12\xf3\x43\x6a\x04\xa6\x0c\xd1\xa7\xcf\x47\xc5",
1423+
*b"\x0e\xfe\x31\xa8\x81\x9b\x6c\x38\x1c\x9e\x97\xcf\xd2\x99\x5a\xa6\xf2\x1e\x4a\x72\x87\x9a\xc1\x31\xb2\xf6\x48\xd0\x83\x28\x1c\x83",
13021424
);
1425+
assert_eq!(unsafe { UI_COUNTER }, EXPECTED_DIALOGS.len());
13031426
}
13041427

13051428
/// Test case whree primaryType=='EIP712Domain'.

0 commit comments

Comments
 (0)