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 : #ifndef __TRUSTED_META_BC_H 26 : #define __TRUSTED_META_BC_H 27 : 28 : #include <stdlib.h> 29 : #include <stdint.h> 30 : #include <string.h> 31 : 32 : #include "meta_bc.h" 33 : 34 : #include "hal/exceptions.h" 35 : #include "hal/log.h" 36 : 37 : #include "apdu.h" 38 : #include "instructions.h" 39 : #include "err.h" 40 : 41 : #include "bc_advance.h" 42 : #include "bc_ancestor.h" 43 : #include "bc_err.h" 44 : 45 : #define MAX_CHUNK_SIZE 80 46 : #define CHUNK_OVERHEAD 5 47 : 48 24 : unsigned int do_meta_advupd(unsigned int rx) { 49 : uint8_t cmd; 50 : uint8_t internal_buffer[MAX_CHUNK_SIZE + CHUNK_OVERHEAD]; 51 : uint8_t* old_buffer; 52 : size_t old_buffer_size; 53 : 54 24 : cmd = APDU_CMD(); 55 : 56 : // Backup message buffer spec 57 24 : old_buffer = communication_get_msg_buffer(); 58 24 : old_buffer_size = communication_get_msg_buffer_size(); 59 : 60 : // Set new buffer 61 24 : communication_set_msg_buffer(internal_buffer, sizeof(internal_buffer)); 62 : 63 : // Send data in chunks 64 24 : unsigned int total_data = rx - DATA; 65 24 : unsigned int data_offset = 0; 66 24 : unsigned int chunk_size = 67 : total_data < MAX_CHUNK_SIZE ? total_data : MAX_CHUNK_SIZE; 68 : unsigned int irx; 69 : 70 : BEGIN_TRY { 71 24 : TRY { 72 56 : while (data_offset < total_data) { 73 48 : SET_APDU_CLA(); 74 48 : SET_APDU_CMD(cmd); 75 48 : SET_APDU_OP(old_buffer[OP]); 76 48 : if (chunk_size > APDU_TOTAL_DATA_SIZE) { 77 : // This shouldn't happen 78 1 : THROW(ERR_INTERNAL); 79 : } 80 47 : if (chunk_size > total_data - data_offset) { 81 : // Not enough data 82 1 : THROW(PROT_INVALID); 83 : } 84 92 : memcpy( 85 46 : APDU_DATA_PTR, &old_buffer[DATA + data_offset], chunk_size); 86 46 : irx = TX_FOR_DATA_SIZE(chunk_size); 87 : LOG_HEX("ITX >", internal_buffer, irx); 88 46 : switch (cmd) { 89 22 : case INS_ADVANCE: 90 22 : irx = bc_advance(irx); 91 21 : break; 92 23 : case INS_UPD_ANCESTOR: 93 23 : irx = bc_upd_ancestor(irx); 94 22 : break; 95 1 : default: 96 : // We should never reach this point 97 1 : THROW(ERR_INTERNAL); 98 : } 99 : LOG_HEX("ITX <", internal_buffer, irx); 100 : // Validate response 101 43 : if (irx != TX_FOR_TXLEN() && irx != TX_NO_DATA()) { 102 : LOG("Unexpected response size\n"); 103 1 : THROW(ERR_INTERNAL); 104 : } 105 42 : if (APDU_CLA() != CLA || APDU_CMD() != cmd) { 106 : LOG("Unexpected response command\n"); 107 2 : THROW(ERR_INTERNAL); 108 : } 109 : // Done? 110 40 : if (APDU_OP() != old_buffer[OP]) { 111 8 : break; 112 : } 113 32 : data_offset += chunk_size; 114 32 : chunk_size = APDU_TXLEN(); 115 : } 116 : 117 : // Restore message buffer 118 16 : communication_set_msg_buffer(old_buffer, old_buffer_size); 119 : 120 : // Response 121 16 : SET_APDU_OP(internal_buffer[OP]); 122 16 : if (irx == TX_FOR_DATA_SIZE(1)) { 123 8 : SET_APDU_TXLEN(internal_buffer[DATA]); 124 16 : return TX_FOR_TXLEN(); 125 : } else { 126 8 : return TX_NO_DATA(); 127 : } 128 : } 129 8 : CATCH_OTHER(e) { 130 : // Restore message buffer 131 8 : communication_set_msg_buffer(old_buffer, old_buffer_size); 132 : // Forward 133 8 : THROW(e); 134 : } 135 : FINALLY { 136 : } 137 : } 138 : END_TRY; 139 : } 140 : 141 : #endif // __TRUSTED_META_BC_H