LCOV - code coverage report
Current view: top level - ledger/ui/src - onboard.c (source / functions) Hit Total Coverage
Test: powHSM firmware Lines: 44 45 97.8 %
Date: 2025-07-10 13:49:13 Functions: 4 4 100.0 %

          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 "bolos_ux_onboarding_seed_bip39.h"
      29             : #include "defs.h"
      30             : #include "ui_err.h"
      31             : #include "os.h"
      32             : #include "onboard.h"
      33             : #include "runtime.h"
      34             : 
      35             : // Global onboarding flag
      36             : NON_VOLATILE unsigned char N_onboarded_ui[1];
      37             : 
      38             : /*
      39             :  * Reset the given onboard context
      40             :  *
      41             :  * @arg[out] onboard_ctx onboard context
      42             :  */
      43           5 : void reset_onboard_ctx(onboard_t *onboard_ctx) {
      44           5 :     explicit_bzero(onboard_ctx, sizeof(onboard_t));
      45           5 : }
      46             : 
      47             : /*
      48             :  * Implement the RSK WIPE command.
      49             :  *
      50             :  * Wipes and onboards the device.
      51             :  *
      52             :  * @arg[out] onboard_ctx onboard context
      53             :  * @ret                  number of transmited bytes to the host
      54             :  */
      55           2 : unsigned int onboard_device(onboard_t *onboard_ctx) {
      56           2 :     volatile unsigned char onboarded_flag = 0;
      57             : 
      58             :     // Reset the onboarding flag to mark onboarding
      59             :     // hasn't been done just in case something fails
      60           2 :     nvm_write((void *)PIC(N_onboarded_ui),
      61             :               (void *)&onboarded_flag,
      62             :               sizeof(onboarded_flag));
      63             : 
      64             : #ifndef DEBUG_BUILD
      65           2 :     if (!is_pin_valid()) {
      66           1 :         THROW(ERR_UI_INVALID_PIN);
      67             :     }
      68             : #endif
      69             : 
      70             :     // Wipe device
      71           1 :     os_global_pin_invalidate();
      72           1 :     os_perso_wipe();
      73             :     // Generate 32 bytes of random with onboard rng
      74           1 :     cx_rng((unsigned char *)onboard_ctx->seed, sizeof(onboard_ctx->seed));
      75             :     // XOR with host-generated 32 bytes random
      76          33 :     for (unsigned int i = 0; i < sizeof(onboard_ctx->seed); i++) {
      77          32 :         onboard_ctx->seed[i] ^= onboard_ctx->host_seed[i];
      78             :     }
      79             :     // The seed is now in onboard_ctx->seed, generate the mnemonic
      80           1 :     explicit_bzero(onboard_ctx->words_buffer,
      81             :                    sizeof(onboard_ctx->words_buffer));
      82           1 :     onboard_ctx->words_buffer_length =
      83           1 :         bolos_ux_mnemonic_from_data((unsigned char *)onboard_ctx->seed,
      84             :                                     sizeof(onboard_ctx->seed),
      85           1 :                                     (unsigned char *)onboard_ctx->words_buffer,
      86             :                                     sizeof(onboard_ctx->words_buffer));
      87             :     // Clear the seed
      88           1 :     explicit_bzero(onboard_ctx->seed, sizeof(onboard_ctx->seed));
      89             : 
      90             :     // Set seed from mnemonic
      91           1 :     os_perso_derive_and_set_seed(0,
      92             :                                  NULL,
      93             :                                  0,
      94             :                                  NULL,
      95             :                                  0,
      96           1 :                                  (const char *)onboard_ctx->words_buffer,
      97             :                                  onboard_ctx->words_buffer_length);
      98             : 
      99             :     // Clear the mnemonic
     100           1 :     explicit_bzero(onboard_ctx->words_buffer,
     101             :                    sizeof(onboard_ctx->words_buffer));
     102           1 :     onboard_ctx->words_buffer_length = 0;
     103             : 
     104             :     // Set PIN
     105           1 :     set_device_pin();
     106             :     // Finalize onboarding
     107           1 :     os_perso_finalize();
     108           1 :     os_global_pin_invalidate();
     109           1 :     unsigned char output_index = CMDPOS;
     110           1 :     SET_APDU_AT(output_index++, 2);
     111           1 :     SET_APDU_AT(output_index++, unlock_with_pin(true));
     112             : 
     113             :     // Turn the onboarding flag on to mark onboarding
     114             :     // has been done using the UI
     115           1 :     onboarded_flag = 1;
     116           1 :     nvm_write((void *)PIC(N_onboarded_ui),
     117             :               (void *)&onboarded_flag,
     118             :               sizeof(onboarded_flag));
     119             : 
     120           1 :     return output_index;
     121             : }
     122             : 
     123             : /*
     124             :  * Implement the RSK SEED command.
     125             :  *
     126             :  * Receives one byte at a time and fills host_seed with the host-generated
     127             :  * seed.
     128             :  *
     129             :  * @arg[in]  rx          number of received bytes from the Host
     130             :  * @arg[out] onboard_ctx onboard context
     131             :  * @ret                  number of transmited bytes to the host
     132             :  */
     133         128 : unsigned int set_host_seed(volatile unsigned int rx, onboard_t *onboard_ctx) {
     134             :     // Should receive 1 byte per call
     135         128 :     if (APDU_DATA_SIZE(rx) != 1) {
     136           0 :         THROW(ERR_UI_PROT_INVALID);
     137             :     }
     138             : 
     139         128 :     unsigned char index = APDU_OP();
     140         128 :     if ((index >= 0) && ((size_t)index < sizeof(onboard_ctx->host_seed))) {
     141         128 :         onboard_ctx->host_seed[index] = APDU_AT(3);
     142             :     }
     143             : 
     144             :     // No bytes transmited to host
     145         128 :     return 0;
     146             : }
     147             : 
     148             : /*
     149             :  * Implement the RSK IS_ONBOARD command.
     150             :  *
     151             :  * Returns onboard status to host
     152             :  *
     153             :  * @ret number of transmited bytes to the host
     154             :  */
     155           2 : unsigned int is_onboarded() {
     156           2 :     uint8_t output_index = CMDPOS;
     157           2 :     SET_APDU_AT(output_index++, os_perso_isonboarded());
     158           2 :     SET_APDU_AT(output_index++, VERSION_MAJOR);
     159           2 :     SET_APDU_AT(output_index++, VERSION_MINOR);
     160           2 :     SET_APDU_AT(output_index++, VERSION_PATCH);
     161           2 :     return output_index;
     162             : }

Generated by: LCOV version 1.16