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 "runtime.h" 26 : #include "apdu.h" 27 : #include "ui_comm.h" 28 : #include "modes.h" 29 : 30 : /** 31 : * Implement the RSK ECHO command. 32 : * 33 : * @arg[in] rx number of received bytes from the Host 34 : * @returns number of transmited bytes to the host 35 : */ 36 1 : unsigned int echo(unsigned int rx) { 37 1 : return rx; 38 : } 39 : 40 : /** 41 : * Implement the RSK MODE command 42 : * to be used from the bootloader. 43 : * 44 : * This always returns bootloader mode. 45 : * 46 : * @returns number of transmited bytes to the host 47 : */ 48 1 : unsigned int get_mode_bootloader() { 49 1 : unsigned char output_index = CMDPOS; 50 1 : SET_APDU_AT(output_index++, APP_MODE_BOOTLOADER); 51 1 : return output_index; 52 : } 53 : 54 : /** 55 : * Implement the RSK MODE command 56 : * to be used from the heartbeat main. 57 : * 58 : * This always returns heartbeat mode. 59 : * 60 : * @returns number of transmited bytes to the host 61 : */ 62 1 : unsigned int get_mode_heartbeat() { 63 1 : unsigned char output_index = CMDPOS; 64 1 : SET_APDU_AT(output_index++, APP_MODE_UI_HEARTBEAT); 65 1 : return output_index; 66 : } 67 : 68 : /** 69 : * Implement the RSK RETRIES command. 70 : * 71 : * Returns the current number of pin retries for the device 72 : * 73 : * @returns number of transmited bytes to the host 74 : */ 75 1 : unsigned int get_retries() { 76 1 : unsigned char output_index = OP; 77 1 : SET_APDU_AT(output_index++, (unsigned char)os_global_pin_retries()); 78 1 : return output_index; 79 : } 80 : 81 : /** 82 : * Process an exception generated by running a command. 83 : * This could be used either from the bootloader 84 : * or from the UI heartbeat main. 85 : * 86 : * @arg[in] ex the exception to process 87 : * @arg[in] tx the current APDU buffer size 88 : * @arg[in] comm_reset_cb callback to reset the state 89 : * @returns the resulting APDU buffer size 90 : */ 91 5 : unsigned int ui_process_exception(unsigned short ex, 92 : unsigned int tx, 93 : comm_reset_cb_t comm_reset_cb) { 94 5 : unsigned short sw = 0; 95 : 96 : // Reset the state in case of an error 97 5 : if (ex != APDU_OK || tx + 2 > APDU_TOTAL_SIZE) { 98 4 : comm_reset_cb(); 99 : } 100 : 101 5 : switch (ex & 0xF000) { 102 4 : case 0x6000: 103 : case 0x9000: 104 4 : sw = ex; 105 4 : break; 106 1 : default: 107 1 : sw = 0x6800 | (ex & 0x7FF); 108 1 : break; 109 : } 110 : 111 : // Unexpected exception => report 112 : // (check for a potential overflow first) 113 5 : if (tx + 2 > APDU_TOTAL_SIZE) { 114 1 : tx = 0; 115 1 : sw = 0x6983; 116 : } 117 5 : SET_APDU_AT(tx++, sw >> 8); 118 5 : SET_APDU_AT(tx++, sw); 119 : 120 5 : return tx; 121 : }