LCOV - code coverage report
Current view: top level - ledger/ui/src - pin.c (source / functions) Hit Total Coverage
Test: powHSM firmware Lines: 24 30 80.0 %
Date: 2025-07-10 13:49:13 Functions: 5 6 83.3 %

          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 : }

Generated by: LCOV version 1.16