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 "bolos_ux_common.h" 26 : 27 : #include "apdu.h" 28 : #include "ux_handlers.h" 29 : #include "bootloader.h" 30 : #include "ui_instructions.h" 31 : #include "defs.h" 32 : #include "ui_err.h" 33 : #include "ui_comm.h" 34 : #include "unlock.h" 35 : 36 : // Attestation context shorthand 37 : #define attestation_ctx (G_bolos_ux_context.attestation) 38 : 39 : // Signer authorization context shorthand 40 : #define sigaut_ctx (G_bolos_ux_context.sigaut) 41 : 42 : // Onboard context shorthand 43 : #define onboard_ctx (G_bolos_ux_context.onboard) 44 : 45 : // Operation being currently executed 46 : static unsigned char current_cmd; 47 : // Flag used to prevent executing commands after the onboard is performed 48 : static bool onboard_performed = false; 49 : 50 : // Macro that throws an error unless 51 : // the device is not onboarded 52 : #define REQUIRE_NOT_ONBOARDED() \ 53 : if (os_perso_isonboarded() == 1) \ 54 : THROW(ERR_UI_DEVICE_ONBOARDED); 55 : 56 : /* 57 : * Reset all reseteable operations, only if the given operation is starting. 58 : * 59 : * @arg[in] cmd operation code 60 : */ 61 16 : static void reset_if_starting(unsigned char cmd) { 62 : // Reset only if starting new operation (cmd != current_cmd). 63 : // Otherwise we already reset when current_cmd started. 64 16 : if (cmd != current_cmd) { 65 16 : current_cmd = cmd; 66 16 : reset_attestation(&attestation_ctx); 67 16 : reset_signer_authorization(&sigaut_ctx); 68 16 : reset_onboard_ctx(&onboard_ctx); 69 : } 70 16 : } 71 : 72 0 : static void reset_state() { 73 0 : reset_if_starting(0); 74 0 : } 75 : 76 20 : void bootloader_init() { 77 20 : current_cmd = 0; 78 20 : onboard_performed = false; 79 : 80 20 : reset_attestation(&attestation_ctx); 81 20 : reset_signer_authorization(&sigaut_ctx); 82 20 : reset_onboard_ctx(&onboard_ctx); 83 20 : } 84 : 85 24 : unsigned int bootloader_process_apdu(volatile unsigned int rx, 86 : bootloader_mode_t mode) { 87 24 : unsigned int tx = 0; 88 : 89 : // no apdu received, or bigger-than-apdu-buffer bytes received => 90 : // well, reset the session, and reset the bootloader configuration 91 24 : if (rx == 0 || rx > APDU_TOTAL_SIZE) { 92 2 : THROW(ERR_INVALID_BUFFER); 93 : } 94 : 95 22 : if (APDU_CLA() != CLA) { 96 1 : THROW(ERR_UI_INVALID_CLA); 97 : } 98 : 99 : // We don't accept any command after onboard is performed in 100 : // onboard mode, the user is required to unplug the device 101 : // before proceeding 102 21 : if (mode == BOOTLOADER_MODE_ONBOARD && onboard_performed) { 103 1 : THROW(ERR_INS_NOT_SUPPORTED); 104 : } 105 : 106 : // unauthenticated instruction 107 20 : switch (APDU_CMD()) { 108 2 : case RSK_SEED_CMD: // Send wordlist 109 2 : REQUIRE_NOT_ONBOARDED(); 110 1 : reset_if_starting(RSK_META_CMD_UIOP); 111 1 : tx = set_host_seed(rx, &onboard_ctx); 112 1 : break; 113 1 : case RSK_PIN_CMD: // Send pin_buffer 114 1 : reset_if_starting(RSK_META_CMD_UIOP); 115 1 : tx = update_pin_buffer(rx); 116 1 : break; 117 2 : case RSK_IS_ONBOARD: // Wheter it's onboarded or not 118 2 : reset_if_starting(RSK_IS_ONBOARD); 119 2 : tx = is_onboarded(); 120 2 : break; 121 5 : case RSK_WIPE: //--- wipe and onboard device --- 122 5 : REQUIRE_NOT_ONBOARDED(); 123 3 : reset_if_starting(RSK_META_CMD_UIOP); 124 3 : tx = onboard_device(&onboard_ctx); 125 3 : clear_pin(); 126 3 : onboard_performed = true; 127 3 : break; 128 1 : case RSK_NEWPIN: 129 1 : reset_if_starting(RSK_META_CMD_UIOP); 130 1 : tx = set_pin(); 131 1 : clear_pin(); 132 1 : break; 133 1 : case RSK_ECHO_CMD: // echo 134 1 : reset_if_starting(RSK_ECHO_CMD); 135 1 : tx = echo(rx); 136 1 : break; 137 1 : case RSK_MODE_CMD: // print mode 138 1 : reset_if_starting(RSK_MODE_CMD); 139 1 : tx = get_mode_bootloader(); 140 1 : break; 141 1 : case INS_ATTESTATION: 142 1 : reset_if_starting(INS_ATTESTATION); 143 1 : tx = get_attestation(rx, &attestation_ctx); 144 1 : break; 145 1 : case INS_SIGNER_AUTHORIZATION: 146 1 : reset_if_starting(INS_SIGNER_AUTHORIZATION); 147 1 : tx = do_authorize_signer(rx, &sigaut_ctx); 148 1 : break; 149 1 : case RSK_RETRIES: 150 1 : reset_if_starting(RSK_RETRIES); 151 1 : tx = get_retries(); 152 1 : break; 153 1 : case RSK_UNLOCK_CMD: // Unlock 154 1 : reset_if_starting(RSK_META_CMD_UIOP); 155 1 : tx = unlock(); 156 : // The pin value could also be used in 157 : // BOLOS_UX_CONSENT_APP_ADD command, so we can't wipe the 158 : // pin buffer here 159 1 : break; 160 1 : case RSK_END_CMD: // return to dashboard and run the app 161 1 : reset_if_starting(RSK_END_CMD); 162 1 : set_dashboard_action(DASHBOARD_ACTION_APP); 163 1 : THROW(EX_BOOTLOADER_RSK_END); 164 1 : case RSK_END_CMD_NOSIG: // return to dashboard 165 1 : reset_if_starting(RSK_END_CMD_NOSIG); 166 1 : set_dashboard_action(DASHBOARD_ACTION_DASHBOARD); 167 1 : THROW(EX_BOOTLOADER_RSK_END); 168 1 : default: 169 1 : THROW(ERR_INS_NOT_SUPPORTED); 170 : break; 171 : } 172 : 173 14 : return tx; 174 : } 175 : 176 : // Main function for the bootloader. If mode == BOOTLOADER_MODE_ONBOARD, 177 : // commands are not accepted after the onboard is performed. 178 0 : void bootloader_main(bootloader_mode_t mode) { 179 0 : volatile unsigned int rx = 0; 180 0 : volatile unsigned int tx = 0; 181 : 182 : // Initialize current operation 183 0 : current_cmd = 0; // 0 = no operation being executed 184 : 185 : // Initialize signer authorization 186 0 : init_signer_authorization(); 187 : 188 : // DESIGN NOTE: the bootloader ignores the way APDU are fetched. The only 189 : // goal is to retrieve APDU. 190 : // When APDU are to be fetched from multiple IOs, like NFC+USB+BLE, make 191 : // sure the io_event is called with a 192 : // switch event, before the apdu is replied to the bootloader. This avoid 193 : // APDU injection faults. 194 : for (;;) { 195 0 : BEGIN_TRY { 196 0 : TRY { 197 0 : rx = tx; 198 0 : tx = 0; // ensure no race in catch_other if io_exchange throws 199 : // an error 200 0 : rx = io_exchange(CHANNEL_APDU, rx); 201 : 202 0 : tx = bootloader_process_apdu(rx, mode); 203 0 : THROW(APDU_OK); 204 : } 205 0 : CATCH(EX_BOOTLOADER_RSK_END) { 206 0 : break; 207 : } 208 0 : CATCH_OTHER(e) { 209 0 : tx = ui_process_exception(e, tx, &reset_state); 210 : } 211 0 : FINALLY { 212 : } 213 : } 214 0 : END_TRY; 215 : } 216 0 : }