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