@@ -108,16 +108,27 @@ static uint8_t* _get_bip39_seed(void)
108
108
return _retained_bip39_seed ;
109
109
}
110
110
111
- static bool _stretch_password (const char * password , uint8_t * kdf_out )
111
+ /**
112
+ * Stretch the user password using the securechip, putting the result in `kdf_out`, which must be 32
113
+ * bytes. `securechip_result_out`, if not NULL, will contain the error code from `securechip_kdf()`
114
+ * if there was a secure chip error, and 0 otherwise.
115
+ */
116
+ static keystore_error_t _stretch_password (
117
+ const char * password ,
118
+ uint8_t * kdf_out ,
119
+ int * securechip_result_out )
112
120
{
121
+ if (securechip_result_out != NULL ) {
122
+ * securechip_result_out = 0 ;
123
+ }
113
124
uint8_t password_salted_hashed [32 ] = {0 };
114
125
UTIL_CLEANUP_32 (password_salted_hashed );
115
126
if (!salt_hash_data (
116
127
(const uint8_t * )password ,
117
128
strlen (password ),
118
129
"keystore_seed_access_in" ,
119
130
password_salted_hashed )) {
120
- return false ;
131
+ return KEYSTORE_ERR_SALT ;
121
132
}
122
133
123
134
uint8_t kdf_in [32 ] = {0 };
@@ -126,14 +137,22 @@ static bool _stretch_password(const char* password, uint8_t* kdf_out)
126
137
127
138
// First KDF on SECURECHIP_SLOT_ROLLKEY increments the monotonic
128
139
// counter. Call only once!
129
- if (!securechip_kdf (SECURECHIP_SLOT_ROLLKEY , kdf_in , 32 , kdf_out )) {
130
- return false;
140
+ int securechip_result = securechip_kdf (SECURECHIP_SLOT_ROLLKEY , kdf_in , 32 , kdf_out );
141
+ if (securechip_result ) {
142
+ if (securechip_result_out != NULL ) {
143
+ * securechip_result_out = securechip_result ;
144
+ }
145
+ return KEYSTORE_ERR_SC_KDF ;
131
146
}
132
147
// Second KDF does not use the counter and we call it multiple times.
133
148
for (int i = 0 ; i < KDF_NUM_ITERATIONS ; i ++ ) {
134
149
memcpy (kdf_in , kdf_out , 32 );
135
- if (!securechip_kdf (SECURECHIP_SLOT_KDF , kdf_in , 32 , kdf_out )) {
136
- return false;
150
+ securechip_result = securechip_kdf (SECURECHIP_SLOT_KDF , kdf_in , 32 , kdf_out );
151
+ if (securechip_result ) {
152
+ if (securechip_result_out != NULL ) {
153
+ * securechip_result_out = securechip_result ;
154
+ }
155
+ return KEYSTORE_ERR_SC_KDF ;
137
156
}
138
157
}
139
158
@@ -142,50 +161,59 @@ static bool _stretch_password(const char* password, uint8_t* kdf_out)
142
161
strlen (password ),
143
162
"keystore_seed_access_out" ,
144
163
password_salted_hashed )) {
145
- return false ;
164
+ return KEYSTORE_ERR_SALT ;
146
165
}
147
166
if (wally_hmac_sha256 (
148
167
password_salted_hashed , sizeof (password_salted_hashed ), kdf_out , 32 , kdf_out , 32 ) !=
149
168
WALLY_OK ) {
150
- return false ;
169
+ return KEYSTORE_ERR_HASH ;
151
170
}
152
171
153
- return true ;
172
+ return KEYSTORE_OK ;
154
173
}
155
- static bool _get_and_decrypt_seed (
174
+
175
+ /**
176
+ * Retrieves the encrypted seed and attempts to decrypt it using the password.
177
+ *
178
+ * `securechip_result_out`, if not NULL, will contain the error code from `securechip_kdf()` if
179
+ * there was a secure chip error, and 0 otherwise.
180
+ */
181
+ static keystore_error_t _get_and_decrypt_seed (
156
182
const char * password ,
157
183
uint8_t * decrypted_seed_out ,
158
184
size_t * decrypted_seed_len_out ,
159
- bool * password_correct_out )
185
+ int * securechip_result_out )
160
186
{
161
187
uint8_t encrypted_seed_and_hmac [96 ];
162
188
UTIL_CLEANUP_32 (encrypted_seed_and_hmac );
163
189
uint8_t encrypted_len ;
164
190
if (!memory_get_encrypted_seed_and_hmac (encrypted_seed_and_hmac , & encrypted_len )) {
165
- return false ;
191
+ return KEYSTORE_ERR_MEMORY ;
166
192
}
167
193
uint8_t secret [32 ];
168
194
UTIL_CLEANUP_32 (secret );
169
- if (!_stretch_password (password , secret )) {
170
- return false;
195
+ keystore_error_t result = _stretch_password (password , secret , securechip_result_out );
196
+ if (result != KEYSTORE_OK ) {
197
+ return result ;
171
198
}
172
199
if (encrypted_len < 49 ) {
173
200
Abort ("_get_and_decrypt_seed: underflow / zero size" );
174
201
}
175
202
size_t decrypted_len = encrypted_len - 48 ;
176
203
uint8_t decrypted [decrypted_len ];
177
- * password_correct_out = cipher_aes_hmac_decrypt (
204
+ bool password_correct = cipher_aes_hmac_decrypt (
178
205
encrypted_seed_and_hmac , encrypted_len , decrypted , & decrypted_len , secret );
179
- if (* password_correct_out ) {
180
- if (!_validate_seed_length (decrypted_len )) {
181
- util_zero (decrypted , sizeof (decrypted ));
182
- return false;
183
- }
184
- * decrypted_seed_len_out = decrypted_len ;
185
- memcpy (decrypted_seed_out , decrypted , decrypted_len );
206
+ if (!password_correct ) {
207
+ return KEYSTORE_ERR_INCORRECT_PASSWORD ;
186
208
}
187
- util_zero (decrypted , sizeof (decrypted ));
188
- return true;
209
+ if (!_validate_seed_length (decrypted_len )) {
210
+ util_zero (decrypted , sizeof (decrypted ));
211
+ return KEYSTORE_ERR_SEED_SIZE ;
212
+ }
213
+ * decrypted_seed_len_out = decrypted_len ;
214
+ memcpy (decrypted_seed_out , decrypted , decrypted_len );
215
+
216
+ return KEYSTORE_OK ;
189
217
}
190
218
191
219
static bool _verify_seed (
@@ -196,11 +224,7 @@ static bool _verify_seed(
196
224
uint8_t decrypted_seed [KEYSTORE_MAX_SEED_LENGTH ] = {0 };
197
225
size_t seed_len ;
198
226
UTIL_CLEANUP_32 (decrypted_seed );
199
- bool password_correct = false;
200
- if (!_get_and_decrypt_seed (password , decrypted_seed , & seed_len , & password_correct )) {
201
- return false;
202
- }
203
- if (!password_correct ) {
227
+ if (_get_and_decrypt_seed (password , decrypted_seed , & seed_len , NULL ) != KEYSTORE_OK ) {
204
228
return false;
205
229
}
206
230
if (expected_seed_len != seed_len ) {
@@ -232,7 +256,7 @@ bool keystore_encrypt_and_store_seed(
232
256
}
233
257
uint8_t secret [32 ] = {0 };
234
258
UTIL_CLEANUP_32 (secret );
235
- if (! _stretch_password (password , secret ) ) {
259
+ if (_stretch_password (password , secret , NULL ) != KEYSTORE_OK ) {
236
260
return false;
237
261
}
238
262
@@ -299,10 +323,13 @@ static void _free_string(char** str)
299
323
wally_free_string (* str );
300
324
}
301
325
302
- keystore_error_t keystore_unlock (const char * password , uint8_t * remaining_attempts_out )
326
+ keystore_error_t keystore_unlock (
327
+ const char * password ,
328
+ uint8_t * remaining_attempts_out ,
329
+ int * securechip_result_out )
303
330
{
304
331
if (!memory_is_seeded ()) {
305
- return KEYSTORE_ERR_GENERIC ;
332
+ return KEYSTORE_ERR_UNSEEDED ;
306
333
}
307
334
uint8_t failed_attempts = bitbox02_smarteeprom_get_unlock_attempts ();
308
335
if (failed_attempts >= MAX_UNLOCK_ATTEMPTS ) {
@@ -319,11 +346,12 @@ keystore_error_t keystore_unlock(const char* password, uint8_t* remaining_attemp
319
346
uint8_t seed [KEYSTORE_MAX_SEED_LENGTH ] = {0 };
320
347
UTIL_CLEANUP_32 (seed );
321
348
size_t seed_len ;
322
- bool password_correct = false;
323
- if (!_get_and_decrypt_seed (password , seed , & seed_len , & password_correct )) {
324
- return KEYSTORE_ERR_GENERIC ;
349
+ keystore_error_t result =
350
+ _get_and_decrypt_seed (password , seed , & seed_len , securechip_result_out );
351
+ if (result != KEYSTORE_OK && result != KEYSTORE_ERR_INCORRECT_PASSWORD ) {
352
+ return result ;
325
353
}
326
- if (password_correct ) {
354
+ if (result == KEYSTORE_OK ) {
327
355
if (_is_unlocked_device ) {
328
356
// Already unlocked. Fail if the seed changed under our feet (should never happen).
329
357
if (seed_len != _seed_length || !MEMEQ (_retained_seed , seed , _seed_length )) {
@@ -346,7 +374,7 @@ keystore_error_t keystore_unlock(const char* password, uint8_t* remaining_attemp
346
374
}
347
375
348
376
* remaining_attempts_out = MAX_UNLOCK_ATTEMPTS - failed_attempts ;
349
- return password_correct ? KEYSTORE_OK : KEYSTORE_ERR_INCORRECT_PASSWORD ;
377
+ return result ;
350
378
}
351
379
352
380
bool keystore_unlock_bip39 (const char * mnemonic_passphrase )
0 commit comments