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 <string.h> 26 : 27 : #include "apdu.h" 28 : #include "os.h" 29 : #include "ui_err.h" 30 : #include "pin.h" 31 : #include "pin_policy.h" 32 : 33 : #define PIN_BUFFER_LENGTH (MAX_PIN_LENGTH + 2) 34 : // Internal PIN buffer used for authenticated operations 35 : unsigned char G_pin_buffer[PIN_BUFFER_LENGTH]; 36 : // Helper macros for pin manipulation when prepended length is used 37 : #define GET_PIN() ((unsigned char *)(G_pin_buffer + 1)) 38 : #define GET_PIN_LENGTH() strlen((const char *)GET_PIN()) 39 : 40 : /* 41 : * Implements RSK PIN command. 42 : * 43 : * Receives one byte at a time and updates the pin context, adding a null byte 44 : * at the end. 45 : * 46 : * @arg[in] rx number of received bytes from the Host 47 : * @ret number of transmited bytes to the host 48 : */ 49 240 : unsigned int update_pin_buffer(volatile unsigned int rx) { 50 : // Should receive 1 byte per call 51 240 : if (APDU_DATA_SIZE(rx) != 1) { 52 0 : THROW(ERR_UI_PROT_INVALID); 53 : } 54 : 55 240 : unsigned char index = APDU_OP(); 56 240 : if ((index >= 0) && (index <= MAX_PIN_LENGTH)) { 57 223 : G_pin_buffer[index] = APDU_AT(DATA); 58 223 : G_pin_buffer[index + 1] = 0; 59 : } 60 : 61 240 : return 3; 62 : } 63 : 64 : /* 65 : * Implements RSK NEW PIN command. 66 : * 67 : * Sets and checks the device pin. 68 : * 69 : * @ret number of transmited bytes to the host 70 : */ 71 5 : unsigned int set_pin() { 72 : #ifndef DEBUG_BUILD 73 5 : if (!is_pin_valid()) { 74 1 : THROW(ERR_UI_INVALID_PIN); 75 : } 76 : #endif 77 : // Set PIN 78 4 : os_perso_set_pin(0, GET_PIN(), GET_PIN_LENGTH()); 79 : // check PIN 80 4 : os_global_pin_invalidate(); 81 4 : unsigned char output_index = CMDPOS; 82 4 : SET_APDU_AT(output_index++, 2); 83 4 : SET_APDU_AT(output_index++, 84 : os_global_pin_check(GET_PIN(), GET_PIN_LENGTH())); 85 4 : return output_index; 86 : } 87 : 88 : /* 89 : * Validates that the pin curently saved to the internal buffer 90 : * is valid according to the current pin policy 91 : * (see pin_policy for details) 92 : * 93 : * @returns true if pin is valid, false otherwise 94 : */ 95 25 : bool is_pin_valid() { 96 25 : return pin_policy_is_valid_pin((const char *)GET_PIN(), GET_PIN_LENGTH()); 97 : } 98 : 99 : /* 100 : * Fills the internal pin buffer with zeroes 101 : */ 102 0 : void clear_pin() { 103 0 : explicit_bzero(G_pin_buffer, sizeof(G_pin_buffer)); 104 0 : } 105 : 106 : /* 107 : * Uses the pin currently saved to the internal pin buffer to unlock the device 108 : * 109 : * @arg[in] prepended_length true if the internal buffer includes a prepended 110 : * length byte, false otherwise 111 : * @ret 1 if pin validated successfully, 0 otherwise 112 : */ 113 4 : unsigned int unlock_with_pin(bool prepended_length) { 114 4 : if (prepended_length) { 115 4 : return os_global_pin_check(GET_PIN(), GET_PIN_LENGTH()); 116 : } else { 117 0 : return os_global_pin_check(G_pin_buffer, 118 0 : strlen((const char *)G_pin_buffer)); 119 : } 120 : } 121 : 122 : /* 123 : * Sets the pin currently saved to the internal pin buffer as the device's pin. 124 : * This function assumes the pin is saved with a prepended length byte. 125 : */ 126 1 : void set_device_pin() { 127 1 : os_perso_set_pin(0, GET_PIN(), GET_PIN_LENGTH()); 128 1 : }