Line data Source code
1 : /**
2 : * The MIT License (MIT)
3 : *
4 : * Copyright (c) 2021 RSK Labs Ltd
5 : *
6 : * Permission is hereby granted, free of charge, to any person obtaining a copy
7 : * of this software and associated documentation files (the "Software"), to
8 : * deal in the Software without restriction, including without limitation the
9 : * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 : * sell copies of the Software, and to permit persons to whom the Software is
11 : * furnished to do so, subject to the following conditions:
12 : *
13 : * The above copyright notice and this permission notice shall be included in
14 : * all copies or substantial portions of the Software.
15 : *
16 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 : * IN THE SOFTWARE.
23 : */
24 :
25 : #include "hal/hash.h"
26 : #include "hal/platform.h"
27 : #include "hal/exceptions.h"
28 :
29 : #include "auth.h"
30 : #include "svarint.h"
31 : #include "mem.h"
32 : #include "memutil.h"
33 :
34 : #include "hal/log.h"
35 :
36 : // IMPORTANT: This callback only executes for the scriptSig at the desired input
37 : // (the one that is requested to sign)
38 : // In all the other cases the parser is not even initialized or called,
39 : // so it is not possible for this callback to execute.
40 9714 : static void btcscript_cb(const btcscript_cb_event_t event) {
41 : uint8_t redeemscript_length_size;
42 : uint8_t redeemscript_length[MAX_SVARINT_ENCODING_SIZE];
43 :
44 9714 : if (event == BTCSCRIPT_EV_OPCODE && auth.tx.script_ctx.operand_size > 0 &&
45 60 : auth.tx.script_ctx.operand_size == auth.tx.script_ctx.bytes_remaining) {
46 : // This is a push of exactly the remaining script bytes => this is the
47 : // last push of the script => this is the redeemScript
48 42 : auth.tx.redeemscript_found = 1;
49 : // Hash the script size using the size of the operand (redeemScript)
50 : redeemscript_length_size =
51 42 : svarint_encode(auth.tx.script_ctx.operand_size,
52 : redeemscript_length,
53 : sizeof(redeemscript_length));
54 42 : hash_sha256_update(&auth.tx.sig_hash_ctx,
55 : redeemscript_length,
56 : redeemscript_length_size);
57 9672 : } else if (event == BTCSCRIPT_EV_OPERAND && auth.tx.redeemscript_found) {
58 7752 : hash_sha256_update(&auth.tx.sig_hash_ctx,
59 : &auth.tx.script_ctx.operand_byte,
60 : sizeof(auth.tx.script_ctx.operand_byte));
61 : }
62 9714 : }
63 :
64 89616 : static void btctx_cb(const btctx_cb_event_t event) {
65 : // Update txhash
66 89616 : hash_sha256_update(
67 89616 : &auth.tx.tx_hash_ctx, auth.tx.ctx.raw, auth.tx.ctx.raw_size);
68 :
69 : // The bridge currently only generates pegout transactions with
70 : // versions 1 or 2. Validate that.
71 89616 : if (event == BTCTX_EV_VERSION && auth.tx.ctx.parsed.version != 1 &&
72 18 : auth.tx.ctx.parsed.version != 2) {
73 2 : LOG("[E] Unsupported TX Version: %u\n", auth.tx.ctx.parsed.version);
74 2 : THROW(ERR_AUTH_INVALID_TX_VERSION);
75 : }
76 :
77 : // Validate that the input index to sign is valid
78 89614 : if (event == BTCTX_EV_VIN_COUNT &&
79 46 : auth.input_index_to_sign >= auth.tx.ctx.parsed.varint.value) {
80 0 : LOG("[E] Input index to sign > number of inputs.\n");
81 0 : THROW(ERR_AUTH_INVALID_TX_INPUT_INDEX);
82 : }
83 :
84 : // Update sighash
85 89614 : if (event == BTCTX_EV_VIN_SLENGTH) {
86 556 : if (auth.tx.ctx.inout_current == auth.input_index_to_sign) {
87 : // Parse this scriptSig
88 46 : auth.tx.redeemscript_found = 0;
89 46 : btcscript_init(&auth.tx.script_ctx,
90 : &btcscript_cb,
91 : auth.tx.ctx.parsed.varint.value);
92 : } else {
93 : // All other scriptSigs get replaced by an empty scriptSig
94 : // when calculating the sigHash
95 510 : hash_sha256_update(&auth.tx.sig_hash_ctx, (uint8_t[]){0x00}, 1);
96 : }
97 89058 : } else if (event == BTCTX_EV_VIN_SCRIPT_DATA &&
98 66628 : auth.tx.ctx.inout_current == auth.input_index_to_sign) {
99 9716 : if (btcscript_consume(auth.tx.ctx.raw, auth.tx.ctx.raw_size) !=
100 9716 : auth.tx.ctx.raw_size) {
101 0 : LOG("[E] Expected to consume %u bytes from the script but didn't",
102 0 : auth.tx.ctx.raw_size);
103 0 : THROW(ERR_AUTH_TX_HASH_MISMATCH);
104 : }
105 :
106 9716 : if (btcscript_result() < 0) {
107 2 : LOG("[E] Error %u parsing the scriptSig", btcscript_result());
108 2 : THROW(ERR_AUTH_TX_HASH_MISMATCH);
109 : }
110 :
111 9714 : if (auth.tx.ctx.script_remaining == 0) {
112 42 : if (btcscript_result() != BTCSCRIPT_ST_DONE) {
113 0 : LOG("[E] No more scriptSig bytes to parse but "
114 : "the script parser isn't finished");
115 0 : THROW(ERR_AUTH_TX_HASH_MISMATCH);
116 : }
117 42 : if (!auth.tx.redeemscript_found) {
118 0 : LOG("[E] Finished parsing the scriptSig "
119 : "but the redeemScript was not found");
120 0 : THROW(ERR_AUTH_TX_HASH_MISMATCH);
121 : }
122 : }
123 79342 : } else if (event != BTCTX_EV_VIN_SCRIPT_DATA) {
124 22430 : hash_sha256_update(
125 22430 : &auth.tx.sig_hash_ctx, auth.tx.ctx.raw, auth.tx.ctx.raw_size);
126 : }
127 89612 : }
128 :
129 76204 : static void btctx_cb_segwit(const btctx_cb_event_t event) {
130 : // Update txhash
131 76204 : hash_sha256_update(
132 76204 : &auth.tx.tx_hash_ctx, auth.tx.ctx.raw, auth.tx.ctx.raw_size);
133 :
134 76204 : if (event == BTCTX_EV_VERSION) {
135 12 : hash_sha256_update(
136 12 : &auth.tx.sig_hash_ctx, auth.tx.ctx.raw, auth.tx.ctx.raw_size);
137 : }
138 :
139 76204 : if (event == BTCTX_EV_VIN_COUNT) {
140 12 : hash_sha256_init(&auth.tx.prevouts_hash_ctx);
141 12 : hash_sha256_init(&auth.tx.sequence_hash_ctx);
142 12 : auth.tx.aux_offset = 0;
143 : }
144 :
145 76204 : if (event == BTCTX_EV_VIN_TXH_DATA || event == BTCTX_EV_VIN_TXIX) {
146 17160 : hash_sha256_update(
147 17160 : &auth.tx.prevouts_hash_ctx, auth.tx.ctx.raw, auth.tx.ctx.raw_size);
148 :
149 17160 : if (auth.tx.ctx.inout_current == auth.input_index_to_sign) {
150 792 : SAFE_MEMMOVE(auth.tx.ip_prevout,
151 : sizeof(auth.tx.ip_prevout),
152 : auth.tx.aux_offset,
153 : auth.tx.ctx.raw,
154 : sizeof(auth.tx.ctx.raw),
155 : MEMMOVE_ZERO_OFFSET,
156 : auth.tx.ctx.raw_size,
157 : THROW(ERR_AUTH_INVALID_DATA_SIZE));
158 396 : auth.tx.aux_offset += auth.tx.ctx.raw_size;
159 : }
160 : }
161 :
162 76204 : if (event == BTCTX_EV_VIN_SEQNO) {
163 520 : hash_sha256_update(
164 520 : &auth.tx.sequence_hash_ctx, auth.tx.ctx.raw, auth.tx.ctx.raw_size);
165 :
166 520 : if (auth.tx.ctx.inout_current == auth.input_index_to_sign) {
167 24 : SAFE_MEMMOVE(auth.tx.ip_seqno,
168 : sizeof(auth.tx.ip_seqno),
169 : MEMMOVE_ZERO_OFFSET,
170 : auth.tx.ctx.raw,
171 : sizeof(auth.tx.ctx.raw),
172 : MEMMOVE_ZERO_OFFSET,
173 : auth.tx.ctx.raw_size,
174 : THROW(ERR_AUTH_INVALID_DATA_SIZE));
175 : }
176 : }
177 :
178 76204 : if (event == BTCTX_EV_VOUT_COUNT) {
179 12 : hash_sha256_final(&auth.tx.prevouts_hash_ctx, auth.tx.aux_hash);
180 12 : hash_sha256_init(&auth.tx.prevouts_hash_ctx);
181 12 : hash_sha256_update(&auth.tx.prevouts_hash_ctx,
182 : auth.tx.aux_hash,
183 : sizeof(auth.tx.aux_hash));
184 12 : hash_sha256_final(&auth.tx.prevouts_hash_ctx, auth.tx.aux_hash);
185 12 : hash_sha256_update(
186 : &auth.tx.sig_hash_ctx, auth.tx.aux_hash, sizeof(auth.tx.aux_hash));
187 :
188 12 : hash_sha256_final(&auth.tx.sequence_hash_ctx, auth.tx.aux_hash);
189 12 : hash_sha256_init(&auth.tx.sequence_hash_ctx);
190 12 : hash_sha256_update(&auth.tx.sequence_hash_ctx,
191 : auth.tx.aux_hash,
192 : sizeof(auth.tx.aux_hash));
193 12 : hash_sha256_final(&auth.tx.sequence_hash_ctx, auth.tx.aux_hash);
194 12 : hash_sha256_update(
195 : &auth.tx.sig_hash_ctx, auth.tx.aux_hash, sizeof(auth.tx.aux_hash));
196 :
197 : // Previously saved outpoint of input to sign
198 12 : hash_sha256_update(&auth.tx.sig_hash_ctx,
199 : auth.tx.ip_prevout,
200 : sizeof(auth.tx.ip_prevout));
201 :
202 12 : hash_sha256_init(&auth.tx.outputs_hash_ctx);
203 : }
204 :
205 76204 : if (event == BTCTX_EV_VOUT_VALUE || event == BTCTX_EV_VOUT_SLENGTH ||
206 : event == BTCTX_EV_VOUT_SCRIPT_DATA) {
207 640 : hash_sha256_update(
208 640 : &auth.tx.outputs_hash_ctx, auth.tx.ctx.raw, auth.tx.ctx.raw_size);
209 : }
210 :
211 76204 : if (event == BTCTX_EV_LOCKTIME) {
212 12 : hash_sha256_final(&auth.tx.outputs_hash_ctx, auth.tx.outputs_hash);
213 12 : hash_sha256_init(&auth.tx.outputs_hash_ctx);
214 12 : hash_sha256_update(&auth.tx.outputs_hash_ctx,
215 : auth.tx.outputs_hash,
216 : sizeof(auth.tx.outputs_hash));
217 12 : hash_sha256_final(&auth.tx.outputs_hash_ctx, auth.tx.outputs_hash);
218 :
219 24 : SAFE_MEMMOVE(auth.tx.lock_time,
220 : sizeof(auth.tx.lock_time),
221 : MEMMOVE_ZERO_OFFSET,
222 : auth.tx.ctx.raw,
223 : sizeof(auth.tx.ctx.raw),
224 : MEMMOVE_ZERO_OFFSET,
225 : auth.tx.ctx.raw_size,
226 : THROW(ERR_AUTH_INVALID_DATA_SIZE));
227 : }
228 76204 : }
229 :
230 : /*
231 : * Implement the BTC tx parsing and calculations portion
232 : * of the signing authorization protocol.
233 : *
234 : * @arg[in] rx number of received bytes from the host
235 : * @ret number of transmited bytes to the host
236 : */
237 2200 : unsigned int auth_sign_handle_btctx(volatile unsigned int rx) {
238 2200 : uint8_t apdu_offset = 0;
239 :
240 : #define TX_METADATA_SIZE \
241 : (BTCTX_LENGTH_SIZE + SIGHASH_COMP_MODE_SIZE + EXTRADATA_SIZE)
242 :
243 2200 : if (auth.state != STATE_AUTH_BTCTX) {
244 0 : LOG("[E] Expected to be in the BTC tx state\n");
245 0 : THROW(ERR_AUTH_INVALID_STATE);
246 : }
247 :
248 2200 : if (!auth.tx.segwit_processing_extradata) {
249 : // Read little endian TX length
250 : // (part of the legacy protocol, includes this length)
251 2162 : if (auth.tx.remaining_bytes == 0) {
252 300 : for (uint8_t i = 0; i < BTCTX_LENGTH_SIZE; i++) {
253 240 : auth.tx.remaining_bytes += APDU_DATA_PTR[i] << (8 * i);
254 : }
255 60 : if (auth.tx.remaining_bytes <= TX_METADATA_SIZE) {
256 : // Prevent underflow
257 0 : LOG("[E] BTC transaction length too small\n");
258 0 : THROW(ERR_AUTH_INVALID_DATA_SIZE);
259 : }
260 : // BTC tx length includes the length of the length
261 : // and the length of the sighash computation mode and
262 : // extradata length
263 60 : auth.tx.remaining_bytes -= TX_METADATA_SIZE;
264 : // Init both hash operations
265 60 : hash_sha256_init(&auth.tx.tx_hash_ctx);
266 60 : hash_sha256_init(&auth.tx.sig_hash_ctx);
267 60 : apdu_offset = BTCTX_LENGTH_SIZE;
268 : // Following three bytes indicate the sighash computation
269 : // mode (1 byte) and extradata size (2 bytes LE, for segwit)
270 60 : auth.tx.sighash_computation_mode = APDU_DATA_PTR[apdu_offset++];
271 60 : auth.tx.segwit_processing_extradata = false;
272 60 : auth.tx.segwit_extradata_size = 0;
273 60 : auth.tx.segwit_extradata_size += APDU_DATA_PTR[apdu_offset++];
274 60 : auth.tx.segwit_extradata_size += APDU_DATA_PTR[apdu_offset++] << 8;
275 : // Validate computation mode and init tx parsing context
276 60 : switch (auth.tx.sighash_computation_mode) {
277 48 : case SIGHASH_COMPUTE_MODE_LEGACY:
278 48 : btctx_init(&auth.tx.ctx, &btctx_cb);
279 48 : break;
280 12 : case SIGHASH_COMPUTE_MODE_SEGWIT:
281 12 : btctx_init(&auth.tx.ctx, &btctx_cb_segwit);
282 12 : if (!auth.tx.segwit_extradata_size) {
283 0 : LOG("[E] Invalid extradata size for segwit");
284 0 : THROW(ERR_AUTH_INVALID_EXTRADATA_SIZE);
285 : }
286 12 : break;
287 0 : default:
288 0 : LOG("[E] Invalid sighash computation mode\n");
289 0 : THROW(ERR_AUTH_INVALID_SIGHASH_COMPUTATION_MODE);
290 : }
291 : }
292 :
293 6482 : auth.tx.remaining_bytes -= btctx_consume(
294 2162 : APDU_DATA_PTR + apdu_offset, APDU_DATA_SIZE(rx) - apdu_offset);
295 :
296 2158 : if (btctx_result() < 0) {
297 0 : LOG("[E] Error parsing BTC tx: %d\n", btctx_result());
298 : // To comply with the legacy implementation
299 0 : THROW(ERR_AUTH_TX_HASH_MISMATCH);
300 : }
301 :
302 2158 : if (btctx_result() == BTCTX_ST_DONE) {
303 54 : if (auth.tx.remaining_bytes > 0) {
304 2 : LOG("[E] Error parsing BTC tx: more bytes reported "
305 : "than actual tx bytes\n");
306 : // To comply with the legacy implementation
307 2 : THROW(ERR_AUTH_INVALID_DATA_SIZE);
308 : }
309 :
310 : // Finalize TX hash computation
311 52 : hash_sha256_final(&auth.tx.tx_hash_ctx, auth.tx_hash);
312 52 : hash_sha256_init(&auth.tx.tx_hash_ctx);
313 52 : hash_sha256_update(&auth.tx.tx_hash_ctx, auth.tx_hash, 32);
314 52 : hash_sha256_final(&auth.tx.tx_hash_ctx, auth.tx_hash);
315 884 : for (int j = 0; j < 16; j++) {
316 832 : uint8_t aux = auth.tx_hash[j];
317 832 : auth.tx_hash[j] = auth.tx_hash[31 - j];
318 832 : auth.tx_hash[31 - j] = aux;
319 : }
320 :
321 : // Segwit?
322 52 : if (auth.tx.sighash_computation_mode ==
323 : SIGHASH_COMPUTE_MODE_SEGWIT) {
324 12 : auth.tx.segwit_processing_extradata = true;
325 12 : auth.tx.remaining_bytes =
326 12 : (uint32_t)auth.tx.segwit_extradata_size;
327 : } else {
328 40 : auth.tx.finalise = true;
329 : }
330 : }
331 : } else {
332 : // Hash extradata
333 0 : hash_sha256_update(
334 38 : &auth.tx.sig_hash_ctx, APDU_DATA_PTR, APDU_DATA_SIZE(rx));
335 38 : auth.tx.remaining_bytes -= APDU_DATA_SIZE(rx);
336 38 : if (auth.tx.remaining_bytes == 0) {
337 12 : auth.tx.finalise = true;
338 : }
339 : }
340 :
341 2194 : if (auth.tx.finalise) {
342 52 : if (auth.tx.sighash_computation_mode == SIGHASH_COMPUTE_MODE_SEGWIT) {
343 : // Remaining tx items to hash for segwit
344 12 : hash_sha256_update(&auth.tx.sig_hash_ctx,
345 : auth.tx.ip_seqno,
346 : sizeof(auth.tx.ip_seqno));
347 12 : hash_sha256_update(&auth.tx.sig_hash_ctx,
348 : auth.tx.outputs_hash,
349 : sizeof(auth.tx.outputs_hash));
350 12 : hash_sha256_update(&auth.tx.sig_hash_ctx,
351 : auth.tx.lock_time,
352 : sizeof(auth.tx.lock_time));
353 : }
354 :
355 : // Add SIGHASH_ALL hash type at the end
356 52 : hash_sha256_update(&auth.tx.sig_hash_ctx,
357 52 : (uint8_t[])SIGHASH_ALL_BYTES,
358 : sizeof(SIGHASH_ALL_SIZE));
359 52 : hash_sha256_final(&auth.tx.sig_hash_ctx, auth.sig_hash);
360 :
361 52 : hash_sha256_init(&auth.tx.sig_hash_ctx);
362 52 : hash_sha256_update(&auth.tx.sig_hash_ctx, auth.sig_hash, 32);
363 52 : hash_sha256_final(&auth.tx.sig_hash_ctx, auth.sig_hash);
364 :
365 : // Log hashes for debugging purposes
366 52 : LOG_HEX("TX hash: ", auth.tx_hash, sizeof(auth.tx_hash));
367 52 : LOG_HEX("TX sig hash: ", auth.sig_hash, sizeof(auth.sig_hash));
368 :
369 : // Request RSK transaction receipt
370 52 : SET_APDU_OP(P1_RECEIPT);
371 52 : SET_APDU_TXLEN(AUTH_MAX_EXCHANGE_SIZE);
372 52 : auth.expected_bytes = APDU_TXLEN();
373 52 : auth_transition_to(STATE_AUTH_RECEIPT);
374 52 : return TX_FOR_TXLEN();
375 : }
376 :
377 2142 : if (auth.tx.remaining_bytes == 0) {
378 2 : LOG("[E] Error parsing BTC tx: no more bytes should "
379 : "remain but haven't finished parsing\n");
380 : // To comply with the legacy implementation
381 2 : THROW(ERR_AUTH_TX_HASH_MISMATCH);
382 : }
383 :
384 2140 : SET_APDU_TXLEN(MIN(auth.tx.remaining_bytes, AUTH_MAX_EXCHANGE_SIZE));
385 2140 : auth.expected_bytes = APDU_TXLEN();
386 2140 : return TX_FOR_TXLEN();
387 : }
|