-
Notifications
You must be signed in to change notification settings - Fork 266
Expand file tree
/
Copy pathcommands_712.c
More file actions
318 lines (302 loc) · 10.6 KB
/
Copy pathcommands_712.c
File metadata and controls
318 lines (302 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
#include "apdu_constants.h" // APDU response codes
#include "context_712.h"
#include "field_hash.h"
#include "path.h"
#include "ui_logic.h"
#include "typed_data.h"
#include "schema_hash.h"
#include "filtering.h"
#include "common_ui.h" // ui_idle
#include "manage_asset_info.h"
#include "ui_callbacks.h"
#include "tx_ctx.h" // get_tx_ctx_count
// APDUs P1
#define P1_COMPLETE 0x00
#define P1_PARTIAL 0xFF
#define P1_DISCARDED 0x01
// APDUs P2
#define P2_DEF_NAME 0x00
#define P2_DEF_FIELD 0xFF
#define P2_IMPL_NAME P2_DEF_NAME
#define P2_IMPL_ARRAY 0x0F
#define P2_IMPL_FIELD P2_DEF_FIELD
#define P2_FILT_ACTIVATE 0x00
#define P2_FILT_DISCARDED_PATH 0x01
#define P2_FILT_MESSAGE_INFO 0x0F
#define P2_FILT_CALLDATA_SPENDER 0xF4
#define P2_FILT_CALLDATA_AMOUNT 0xF5
#define P2_FILT_CALLDATA_SELECTOR 0xF6
#define P2_FILT_CALLDATA_CHAIN_ID 0xF7
#define P2_FILT_CALLDATA_CALLEE 0xF8
#define P2_FILT_CALLDATA_VALUE 0xF9
#define P2_FILT_CALLDATA_INFO 0xFA
#define P2_FILT_CONTRACT_NAME 0xFB
#define P2_FILT_DATE_TIME 0xFC
#define P2_FILT_AMOUNT_JOIN_TOKEN 0xFD
#define P2_FILT_AMOUNT_JOIN_VALUE 0xFE
#define P2_FILT_RAW_FIELD 0xFF
/**
* Send the response to the previous APDU command
*
* In case of an error it uses the global variable to retrieve the error code and resets
* the app context
*
* @param[in] success whether the command was successful
*/
static void apdu_reply(bool success) {
bool home = true;
if (success) {
apdu_response_code = SWO_SUCCESS;
} else {
if (apdu_response_code == SWO_SUCCESS) { // somehow not set
apdu_response_code = SWO_PARAMETER_ERROR_NO_INFO;
}
if (eip712_context != NULL) {
home = eip712_context->go_home_on_failure;
}
eip712_context_deinit();
if (home) ui_idle();
}
}
/**
* Send the response to the previous APDU command
*
* In case of an error it uses the global variable to retrieve the error code and resets
* the app context
*
* @param[in] success whether the command was successful
*/
void handle_eip712_return_code(bool success) {
apdu_reply(success);
io_seproxyhal_send_status(apdu_response_code, 0, false, false);
}
/**
* Process the EIP712 struct definition command
*
* @param[in] p2 instruction parameter 2
* @param[in] cdata command data
* @param[in] length length of the command data
* @return whether the command was successful or not
*/
uint16_t handle_eip712_struct_def(uint8_t p2, const uint8_t *cdata, uint8_t length) {
bool ret = true;
if (eip712_context == NULL) {
ret = eip712_context_init();
}
if (struct_state == DEFINED) {
ret = false;
}
if (ret) {
switch (p2) {
case P2_DEF_NAME:
ret = set_struct_name(length, cdata);
break;
case P2_DEF_FIELD:
ret = set_struct_field(length, cdata);
break;
default:
PRINTF("Unknown P2 0x%x\n", p2);
apdu_response_code = SWO_WRONG_P1_P2;
ret = false;
}
}
apdu_reply(ret);
return apdu_response_code;
}
/**
* Process the EIP712 struct implementation command
*
* @param[in] p1 instruction parameter 1
* @param[in] p2 instruction parameter 2
* @param[in] cdata command data
* @param[in] length length of the command data
* @return whether the command was successful or not
*/
uint16_t handle_eip712_struct_impl(uint8_t p1,
uint8_t p2,
const uint8_t *cdata,
uint8_t length,
uint32_t *flags) {
bool ret = false;
bool reply_apdu = true;
if (eip712_context == NULL) {
apdu_response_code = SWO_COMMAND_NOT_ALLOWED;
} else {
switch (p2) {
case P2_IMPL_NAME:
// set root type
ret = path_set_root((char *) cdata, length);
if (ret) {
#ifdef SCREEN_SIZE_WALLET
if (ui_712_get_filtering_mode() == EIP712_FILTERING_BASIC) {
#else
if (N_storage.verbose_eip712) {
#endif
if ((ret = ui_712_review_struct(path_get_root()))) {
reply_apdu = false;
}
}
if ((path_get_root_type() == ROOT_MESSAGE) &&
(ui_712_get_filtering_mode() == EIP712_FILTERING_FULL)) {
ret = ui_712_review_network(&eip712_context->chain_id);
}
ui_712_field_flags_reset();
}
break;
case P2_IMPL_FIELD:
if ((ret = field_hash(cdata, length, p1 != P1_COMPLETE))) {
reply_apdu = false;
}
break;
case P2_IMPL_ARRAY:
ret = path_new_array_depth(cdata, length);
break;
default:
PRINTF("Unknown P2 0x%x\n", p2);
apdu_response_code = SWO_WRONG_P1_P2;
}
}
if (reply_apdu) {
apdu_reply(ret);
return apdu_response_code;
}
*flags |= IO_ASYNCH_REPLY;
return APDU_NO_RESPONSE;
}
/**
* Process the EIP712 filtering command
*
* @param[in] p1 instruction parameter 1
* @param[in] p2 instruction parameter 2
* @param[in] cdata command data
* @param[in] length length of the command data
* @return whether the command was successful or not
*/
uint16_t handle_eip712_filtering(uint8_t p1,
uint8_t p2,
const uint8_t *cdata,
uint8_t length,
uint32_t *flags) {
bool ret = true;
bool reply_apdu = true;
uint32_t path_crc = 0;
if (eip712_context == NULL) {
apdu_reply(false);
return SWO_COMMAND_NOT_ALLOWED;
}
if ((p2 != P2_FILT_ACTIVATE) && (ui_712_get_filtering_mode() != EIP712_FILTERING_FULL)) {
return SWO_SUCCESS;
}
switch (p2) {
case P2_FILT_ACTIVATE:
if (!N_storage.verbose_eip712) {
ui_712_set_filtering_mode(EIP712_FILTERING_FULL);
ret = compute_schema_hash();
}
forget_known_assets();
break;
case P2_FILT_DISCARDED_PATH:
ret = filtering_discarded_path(cdata, length);
break;
case P2_FILT_MESSAGE_INFO:
ret = filtering_message_info(cdata, length);
if (ret) {
reply_apdu = false;
}
break;
case P2_FILT_CALLDATA_SPENDER:
ret = filtering_calldata_spender(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
case P2_FILT_CALLDATA_AMOUNT:
ret = filtering_calldata_amount(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
case P2_FILT_CALLDATA_SELECTOR:
ret = filtering_calldata_selector(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
case P2_FILT_CALLDATA_CHAIN_ID:
ret = filtering_calldata_chain_id(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
case P2_FILT_CALLDATA_CALLEE:
ret = filtering_calldata_callee(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
case P2_FILT_CALLDATA_VALUE:
ret = filtering_calldata_value(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
case P2_FILT_CALLDATA_INFO:
ret = filtering_calldata_info(cdata, length);
break;
case P2_FILT_CONTRACT_NAME:
ret = filtering_trusted_name(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
case P2_FILT_DATE_TIME:
ret = filtering_date_time(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
case P2_FILT_AMOUNT_JOIN_TOKEN:
ret = filtering_amount_join_token(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
case P2_FILT_AMOUNT_JOIN_VALUE:
ret = filtering_amount_join_value(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
case P2_FILT_RAW_FIELD:
ret = filtering_raw_field(cdata, length, p1 == P1_DISCARDED, &path_crc);
break;
default:
PRINTF("Unknown P2 0x%x\n", p2);
apdu_response_code = SWO_WRONG_P1_P2;
ret = false;
}
if ((p2 > P2_FILT_MESSAGE_INFO) && (p2 != P2_FILT_CALLDATA_INFO) && ret) {
if (!ui_712_push_new_filter_path(path_crc)) {
ret = false;
}
}
if (reply_apdu) {
apdu_reply(ret);
return apdu_response_code;
}
*flags |= IO_ASYNCH_REPLY;
return APDU_NO_RESPONSE;
}
/**
* Process the EIP712 sign command
*
* @param[in] apdu_buf the APDU payload
* @return whether the command was successful or not
*/
uint16_t handle_eip712_sign(const uint8_t *cdata, uint8_t length, uint32_t *flags) {
bool ret = false;
if (eip712_context == NULL) {
apdu_response_code = SWO_COMMAND_NOT_ALLOWED;
}
// if the final hashes are still zero or if there are some unimplemented fields
else if (allzeroes(tmpCtx.messageSigningContext712.domainHash,
sizeof(tmpCtx.messageSigningContext712.domainHash)) ||
allzeroes(tmpCtx.messageSigningContext712.messageHash,
sizeof(tmpCtx.messageSigningContext712.messageHash)) ||
(path_get_field() != NULL)) {
apdu_response_code = SWO_INCORRECT_DATA;
} else if ((ui_712_get_filtering_mode() == EIP712_FILTERING_FULL) &&
(!ui_712_message_info_received() || (ui_712_remaining_filters() != 0))) {
PRINTF("%d EIP712 filters are missing\n", ui_712_remaining_filters());
apdu_response_code = SWO_REFERENCED_DATA_NOT_FOUND;
} else if (!all_calldata_info_processed() || (get_tx_ctx_count() != 0)) {
PRINTF("Unprocessed calldata\n");
apdu_response_code = SWO_REFERENCED_DATA_NOT_FOUND;
} else if (parseBip32(cdata, &length, &tmpCtx.messageSigningContext.bip32) == NULL) {
apdu_response_code = SWO_INCORRECT_DATA;
} else {
ret = true;
#ifndef SCREEN_SIZE_WALLET
if (!N_storage.verbose_eip712 && (ui_712_get_filtering_mode() == EIP712_FILTERING_BASIC)) {
ret = ui_712_message_hash();
}
#endif
ui_712_end_sign();
}
if (!ret) {
apdu_reply(false);
return apdu_response_code;
}
*flags |= IO_ASYNCH_REPLY;
return APDU_NO_RESPONSE;
}