mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 04:38:35 -07:00
Update totp
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "polyfills.h"
|
||||
|
||||
#define CRYPTO_IV_LENGTH (16)
|
||||
#define CRYPTO_SALT_LENGTH (16)
|
||||
|
||||
// According to this explanation: https://github.com/flipperdevices/flipperzero-firmware/issues/2885#issuecomment-1646664666
|
||||
// disabling usage of any key which is "the same across all devices"
|
||||
#define ACCEPTABLE_CRYPTO_KEY_SLOT_START (12)
|
||||
#define ACCEPTABLE_CRYPTO_KEY_SLOT_END (100)
|
||||
#define ACCEPTABLE_CRYPTO_KEY_SLOT_START FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_START
|
||||
#define ACCEPTABLE_CRYPTO_KEY_SLOT_END FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_END
|
||||
|
||||
#define DEFAULT_CRYPTO_KEY_SLOT ACCEPTABLE_CRYPTO_KEY_SLOT_START
|
||||
#define CRYPTO_LATEST_VERSION (2)
|
||||
#define CRYPTO_LATEST_VERSION (3)
|
||||
@@ -1,8 +1,14 @@
|
||||
#include "crypto_facade.h"
|
||||
#include "../../config/app/config.h"
|
||||
#include <furi_hal_crypto.h>
|
||||
#include <furi/core/check.h>
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
|
||||
#include "crypto_v1.h"
|
||||
#endif
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
|
||||
#include "crypto_v2.h"
|
||||
#endif
|
||||
#include "crypto_v3.h"
|
||||
#include "constants.h"
|
||||
|
||||
bool totp_crypto_check_key_slot(uint8_t key_slot) {
|
||||
@@ -11,9 +17,9 @@ bool totp_crypto_check_key_slot(uint8_t key_slot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return furi_hal_crypto_verify_key(key_slot) &&
|
||||
furi_hal_crypto_store_load_key(key_slot, empty_iv) &&
|
||||
furi_hal_crypto_store_unload_key(key_slot);
|
||||
return furi_hal_crypto_enclave_ensure_key(key_slot) &&
|
||||
furi_hal_crypto_enclave_load_key(key_slot, empty_iv) &&
|
||||
furi_hal_crypto_enclave_unload_key(key_slot);
|
||||
}
|
||||
|
||||
uint8_t* totp_crypto_encrypt(
|
||||
@@ -21,15 +27,24 @@ uint8_t* totp_crypto_encrypt(
|
||||
const size_t plain_data_length,
|
||||
const CryptoSettings* crypto_settings,
|
||||
size_t* encrypted_data_length) {
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
|
||||
if(crypto_settings->crypto_version == 1) {
|
||||
return totp_crypto_encrypt_v1(
|
||||
plain_data, plain_data_length, crypto_settings, encrypted_data_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
|
||||
if(crypto_settings->crypto_version == 2) {
|
||||
return totp_crypto_encrypt_v2(
|
||||
plain_data, plain_data_length, crypto_settings, encrypted_data_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(crypto_settings->crypto_version == 3) {
|
||||
return totp_crypto_encrypt_v3(
|
||||
plain_data, plain_data_length, crypto_settings, encrypted_data_length);
|
||||
}
|
||||
|
||||
furi_crash("Unsupported crypto version");
|
||||
}
|
||||
@@ -39,40 +54,65 @@ uint8_t* totp_crypto_decrypt(
|
||||
const size_t encrypted_data_length,
|
||||
const CryptoSettings* crypto_settings,
|
||||
size_t* decrypted_data_length) {
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
|
||||
if(crypto_settings->crypto_version == 1) {
|
||||
return totp_crypto_decrypt_v1(
|
||||
encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
|
||||
if(crypto_settings->crypto_version == 2) {
|
||||
return totp_crypto_decrypt_v2(
|
||||
encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(crypto_settings->crypto_version == 3) {
|
||||
return totp_crypto_decrypt_v3(
|
||||
encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length);
|
||||
}
|
||||
|
||||
furi_crash("Unsupported crypto version");
|
||||
}
|
||||
|
||||
CryptoSeedIVResult
|
||||
totp_crypto_seed_iv(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length) {
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
|
||||
if(crypto_settings->crypto_version == 1) {
|
||||
return totp_crypto_seed_iv_v1(crypto_settings, pin, pin_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
|
||||
if(crypto_settings->crypto_version == 2) {
|
||||
return totp_crypto_seed_iv_v2(crypto_settings, pin, pin_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(crypto_settings->crypto_version == 3) {
|
||||
return totp_crypto_seed_iv_v3(crypto_settings, pin, pin_length);
|
||||
}
|
||||
|
||||
furi_crash("Unsupported crypto version");
|
||||
}
|
||||
|
||||
bool totp_crypto_verify_key(const CryptoSettings* crypto_settings) {
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
|
||||
if(crypto_settings->crypto_version == 1) {
|
||||
return totp_crypto_verify_key_v1(crypto_settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
|
||||
if(crypto_settings->crypto_version == 2) {
|
||||
return totp_crypto_verify_key_v2(crypto_settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(crypto_settings->crypto_version == 3) {
|
||||
return totp_crypto_verify_key_v3(crypto_settings);
|
||||
}
|
||||
|
||||
furi_crash("Unsupported crypto version");
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "crypto_v1.h"
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
|
||||
#include <stdlib.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal_crypto.h>
|
||||
@@ -6,6 +7,7 @@
|
||||
#include <furi_hal_version.h>
|
||||
#include "../../types/common.h"
|
||||
#include "memset_s.h"
|
||||
#include "polyfills.h"
|
||||
|
||||
#define CRYPTO_KEY_SLOT (2)
|
||||
#define CRYPTO_VERIFY_KEY_LENGTH (16)
|
||||
@@ -32,9 +34,9 @@ uint8_t* totp_crypto_encrypt_v1(
|
||||
furi_check(encrypted_data != NULL);
|
||||
*encrypted_data_length = plain_data_aligned_length;
|
||||
|
||||
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
|
||||
furi_hal_crypto_enclave_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
|
||||
furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length);
|
||||
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
|
||||
furi_hal_crypto_enclave_unload_key(CRYPTO_KEY_SLOT);
|
||||
|
||||
memset_s(plain_data_aligned, plain_data_aligned_length, 0, plain_data_aligned_length);
|
||||
free(plain_data_aligned);
|
||||
@@ -43,9 +45,9 @@ uint8_t* totp_crypto_encrypt_v1(
|
||||
furi_check(encrypted_data != NULL);
|
||||
*encrypted_data_length = plain_data_length;
|
||||
|
||||
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
|
||||
furi_hal_crypto_enclave_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
|
||||
furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length);
|
||||
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
|
||||
furi_hal_crypto_enclave_unload_key(CRYPTO_KEY_SLOT);
|
||||
}
|
||||
|
||||
return encrypted_data;
|
||||
@@ -59,9 +61,9 @@ uint8_t* totp_crypto_decrypt_v1(
|
||||
*decrypted_data_length = encrypted_data_length;
|
||||
uint8_t* decrypted_data = malloc(*decrypted_data_length);
|
||||
furi_check(decrypted_data != NULL);
|
||||
furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
|
||||
furi_hal_crypto_enclave_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv);
|
||||
furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length);
|
||||
furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
|
||||
furi_hal_crypto_enclave_unload_key(CRYPTO_KEY_SLOT);
|
||||
return decrypted_data;
|
||||
}
|
||||
|
||||
@@ -72,10 +74,10 @@ CryptoSeedIVResult totp_crypto_seed_iv_v1(
|
||||
CryptoSeedIVResult result;
|
||||
if(crypto_settings->crypto_verify_data == NULL) {
|
||||
FURI_LOG_I(LOGGING_TAG, "Generating new IV");
|
||||
furi_hal_random_fill_buf(&crypto_settings->base_iv[0], TOTP_IV_SIZE);
|
||||
furi_hal_random_fill_buf(&crypto_settings->salt[0], CRYPTO_SALT_LENGTH);
|
||||
}
|
||||
|
||||
memcpy(&crypto_settings->iv[0], &crypto_settings->base_iv[0], TOTP_IV_SIZE);
|
||||
memcpy(&crypto_settings->iv[0], &crypto_settings->salt[0], TOTP_IV_SIZE);
|
||||
if(pin != NULL && pin_length > 0) {
|
||||
uint8_t max_i;
|
||||
if(pin_length > TOTP_IV_SIZE) {
|
||||
@@ -139,4 +141,5 @@ bool totp_crypto_verify_key_v1(const CryptoSettings* crypto_settings) {
|
||||
free(decrypted_key);
|
||||
|
||||
return key_valid;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../config/app/config.h"
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V1_COMPATIBILITY_ENABLED
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
@@ -49,4 +51,5 @@ CryptoSeedIVResult
|
||||
* @param crypto_settings crypto settings
|
||||
* @return \c true if cryptographic information is valid; \c false otherwise
|
||||
*/
|
||||
bool totp_crypto_verify_key_v1(const CryptoSettings* crypto_settings);
|
||||
bool totp_crypto_verify_key_v1(const CryptoSettings* crypto_settings);
|
||||
#endif
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#include "crypto_v2.h"
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
|
||||
#include <stdlib.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal_crypto.h>
|
||||
#include <furi_hal_random.h>
|
||||
#include <furi_hal_version.h>
|
||||
#include "../../types/common.h"
|
||||
#include "../hmac/hmac_sha512.h"
|
||||
#include "../../config/wolfssl/config.h"
|
||||
#include <wolfssl/wolfcrypt/hmac.h>
|
||||
#include "memset_s.h"
|
||||
#include "constants.h"
|
||||
#include "polyfills.h"
|
||||
|
||||
#define CRYPTO_ALIGNMENT_FACTOR (16)
|
||||
|
||||
@@ -46,14 +49,14 @@ uint8_t* totp_crypto_encrypt_v2(
|
||||
*encrypted_data_length = plain_data_aligned_length;
|
||||
|
||||
furi_check(
|
||||
furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
|
||||
"Encryption failed: store_load_key");
|
||||
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
|
||||
"Encryption failed: enclave_load_key");
|
||||
furi_check(
|
||||
furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length),
|
||||
"Encryption failed: encrypt");
|
||||
furi_check(
|
||||
furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot),
|
||||
"Encryption failed: store_unload_key");
|
||||
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
|
||||
"Encryption failed: enclave_unload_key");
|
||||
|
||||
memset_s(plain_data_aligned, plain_data_aligned_length, 0, plain_data_aligned_length);
|
||||
free(plain_data_aligned);
|
||||
@@ -63,13 +66,13 @@ uint8_t* totp_crypto_encrypt_v2(
|
||||
*encrypted_data_length = plain_data_length;
|
||||
|
||||
furi_check(
|
||||
furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
|
||||
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
|
||||
"Encryption failed: store_load_key");
|
||||
furi_check(
|
||||
furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length),
|
||||
"Encryption failed: encrypt");
|
||||
furi_check(
|
||||
furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot),
|
||||
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
|
||||
"Encryption failed: store_unload_key");
|
||||
}
|
||||
|
||||
@@ -85,14 +88,14 @@ uint8_t* totp_crypto_decrypt_v2(
|
||||
uint8_t* decrypted_data = malloc(*decrypted_data_length);
|
||||
furi_check(decrypted_data != NULL);
|
||||
furi_check(
|
||||
furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
|
||||
"Decryption failed: store_load_key");
|
||||
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
|
||||
"Decryption failed: enclave_load_key");
|
||||
furi_check(
|
||||
furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length),
|
||||
"Decryption failed: decrypt");
|
||||
furi_check(
|
||||
furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot),
|
||||
"Decryption failed: store_unload_key");
|
||||
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
|
||||
"Decryption failed: enclave_unload_key");
|
||||
return decrypted_data;
|
||||
}
|
||||
|
||||
@@ -102,12 +105,10 @@ CryptoSeedIVResult totp_crypto_seed_iv_v2(
|
||||
uint8_t pin_length) {
|
||||
CryptoSeedIVResult result;
|
||||
if(crypto_settings->crypto_verify_data == NULL) {
|
||||
FURI_LOG_I(LOGGING_TAG, "Generating new IV");
|
||||
furi_hal_random_fill_buf(&crypto_settings->base_iv[0], CRYPTO_IV_LENGTH);
|
||||
FURI_LOG_I(LOGGING_TAG, "Generating new salt");
|
||||
furi_hal_random_fill_buf(&crypto_settings->salt[0], CRYPTO_SALT_LENGTH);
|
||||
}
|
||||
|
||||
memcpy(&crypto_settings->iv[0], &crypto_settings->base_iv[0], CRYPTO_IV_LENGTH);
|
||||
|
||||
const uint8_t* device_uid = get_device_uid();
|
||||
uint8_t device_uid_length = get_device_uid_length();
|
||||
|
||||
@@ -125,16 +126,20 @@ CryptoSeedIVResult totp_crypto_seed_iv_v2(
|
||||
memcpy(hmac_key + device_uid_length, pin, pin_length);
|
||||
}
|
||||
|
||||
uint8_t hmac[HMAC_SHA512_RESULT_SIZE] = {0};
|
||||
int hmac_result_code = hmac_sha512(
|
||||
hmac_key, hmac_key_length, &crypto_settings->base_iv[0], CRYPTO_IV_LENGTH, &hmac[0]);
|
||||
uint8_t hmac[WC_SHA512_DIGEST_SIZE] = {0};
|
||||
|
||||
Hmac hmac_context;
|
||||
wc_HmacSetKey(&hmac_context, WC_SHA512, hmac_key, hmac_key_length);
|
||||
wc_HmacUpdate(&hmac_context, &crypto_settings->salt[0], CRYPTO_SALT_LENGTH);
|
||||
int hmac_result_code = wc_HmacFinal(&hmac_context, &hmac[0]);
|
||||
wc_HmacFree(&hmac_context);
|
||||
|
||||
memset_s(hmac_key, hmac_key_length, 0, hmac_key_length);
|
||||
free(hmac_key);
|
||||
|
||||
if(hmac_result_code == 0) {
|
||||
uint8_t offset =
|
||||
hmac[HMAC_SHA512_RESULT_SIZE - 1] % (HMAC_SHA512_RESULT_SIZE - CRYPTO_IV_LENGTH - 1);
|
||||
hmac[WC_SHA512_DIGEST_SIZE - 1] % (WC_SHA512_DIGEST_SIZE - CRYPTO_IV_LENGTH - 1);
|
||||
memcpy(&crypto_settings->iv[0], &hmac[offset], CRYPTO_IV_LENGTH);
|
||||
|
||||
result = CryptoSeedIVResultFlagSuccess;
|
||||
@@ -181,4 +186,5 @@ bool totp_crypto_verify_key_v2(const CryptoSettings* crypto_settings) {
|
||||
free(decrypted_key);
|
||||
|
||||
return key_valid;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../config/app/config.h"
|
||||
#ifdef TOTP_OBSOLETE_CRYPTO_V2_COMPATIBILITY_ENABLED
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
@@ -49,4 +51,5 @@ CryptoSeedIVResult
|
||||
* @param crypto_settings crypto settings
|
||||
* @return \c true if cryptographic information is valid; \c false otherwise
|
||||
*/
|
||||
bool totp_crypto_verify_key_v2(const CryptoSettings* crypto_settings);
|
||||
bool totp_crypto_verify_key_v2(const CryptoSettings* crypto_settings);
|
||||
#endif
|
||||
|
||||
195
applications/external/totp/services/crypto/crypto_v3.c
vendored
Normal file
195
applications/external/totp/services/crypto/crypto_v3.c
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
#include "crypto_v3.h"
|
||||
#include <stdlib.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal_crypto.h>
|
||||
#include <furi_hal_random.h>
|
||||
#include <furi_hal_version.h>
|
||||
#include "../../types/common.h"
|
||||
#include "../../config/wolfssl/config.h"
|
||||
#include <wolfssl/wolfcrypt/hmac.h>
|
||||
#include <wolfssl/wolfcrypt/pwdbased.h>
|
||||
#include "memset_s.h"
|
||||
#include "constants.h"
|
||||
#include "polyfills.h"
|
||||
|
||||
#define CRYPTO_ALIGNMENT_FACTOR (16)
|
||||
#define PBKDF2_ITERATIONS_COUNT (200)
|
||||
|
||||
static const uint8_t* get_device_uid() {
|
||||
return (const uint8_t*)UID64_BASE; //-V566
|
||||
}
|
||||
|
||||
static uint8_t get_device_uid_length() {
|
||||
return furi_hal_version_uid_size();
|
||||
}
|
||||
|
||||
static const uint8_t* get_crypto_verify_key() {
|
||||
return get_device_uid();
|
||||
}
|
||||
|
||||
static uint8_t get_crypto_verify_key_length() {
|
||||
return get_device_uid_length();
|
||||
}
|
||||
|
||||
uint8_t* totp_crypto_encrypt_v3(
|
||||
const uint8_t* plain_data,
|
||||
const size_t plain_data_length,
|
||||
const CryptoSettings* crypto_settings,
|
||||
size_t* encrypted_data_length) {
|
||||
uint8_t* encrypted_data;
|
||||
size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR;
|
||||
if(remain) {
|
||||
size_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR;
|
||||
uint8_t* plain_data_aligned = malloc(plain_data_aligned_length);
|
||||
furi_check(plain_data_aligned != NULL);
|
||||
memset(plain_data_aligned, 0, plain_data_aligned_length);
|
||||
memcpy(plain_data_aligned, plain_data, plain_data_length);
|
||||
|
||||
encrypted_data = malloc(plain_data_aligned_length);
|
||||
furi_check(encrypted_data != NULL);
|
||||
*encrypted_data_length = plain_data_aligned_length;
|
||||
|
||||
furi_check(
|
||||
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
|
||||
"Encryption failed: enclave_load_key");
|
||||
furi_check(
|
||||
furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length),
|
||||
"Encryption failed: encrypt");
|
||||
furi_check(
|
||||
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
|
||||
"Encryption failed: enclave_unload_key");
|
||||
|
||||
memset_s(plain_data_aligned, plain_data_aligned_length, 0, plain_data_aligned_length);
|
||||
free(plain_data_aligned);
|
||||
} else {
|
||||
encrypted_data = malloc(plain_data_length);
|
||||
furi_check(encrypted_data != NULL);
|
||||
*encrypted_data_length = plain_data_length;
|
||||
|
||||
furi_check(
|
||||
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
|
||||
"Encryption failed: enclave_load_key");
|
||||
furi_check(
|
||||
furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length),
|
||||
"Encryption failed: encrypt");
|
||||
furi_check(
|
||||
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
|
||||
"Encryption failed: enclave_unload_key");
|
||||
}
|
||||
|
||||
return encrypted_data;
|
||||
}
|
||||
|
||||
uint8_t* totp_crypto_decrypt_v3(
|
||||
const uint8_t* encrypted_data,
|
||||
const size_t encrypted_data_length,
|
||||
const CryptoSettings* crypto_settings,
|
||||
size_t* decrypted_data_length) {
|
||||
*decrypted_data_length = encrypted_data_length;
|
||||
uint8_t* decrypted_data = malloc(*decrypted_data_length);
|
||||
furi_check(decrypted_data != NULL);
|
||||
furi_check(
|
||||
furi_hal_crypto_enclave_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv),
|
||||
"Decryption failed: enclave_load_key");
|
||||
furi_check(
|
||||
furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length),
|
||||
"Decryption failed: decrypt");
|
||||
furi_check(
|
||||
furi_hal_crypto_enclave_unload_key(crypto_settings->crypto_key_slot),
|
||||
"Decryption failed: enclave_unload_key");
|
||||
return decrypted_data;
|
||||
}
|
||||
|
||||
CryptoSeedIVResult totp_crypto_seed_iv_v3(
|
||||
CryptoSettings* crypto_settings,
|
||||
const uint8_t* pin,
|
||||
uint8_t pin_length) {
|
||||
CryptoSeedIVResult result;
|
||||
if(crypto_settings->crypto_verify_data == NULL) {
|
||||
FURI_LOG_I(LOGGING_TAG, "Generating new salt");
|
||||
furi_hal_random_fill_buf(&crypto_settings->salt[0], CRYPTO_SALT_LENGTH);
|
||||
}
|
||||
|
||||
const uint8_t* device_uid = get_device_uid();
|
||||
uint8_t device_uid_length = get_device_uid_length();
|
||||
|
||||
uint8_t pbkdf_key_length = device_uid_length;
|
||||
if(pin != NULL && pin_length > 0) {
|
||||
pbkdf_key_length += pin_length;
|
||||
}
|
||||
|
||||
uint8_t* pbkdf_key = malloc(pbkdf_key_length);
|
||||
furi_check(pbkdf_key != NULL);
|
||||
|
||||
memcpy(pbkdf_key, device_uid, device_uid_length);
|
||||
|
||||
if(pin != NULL && pin_length > 0) {
|
||||
memcpy(pbkdf_key + device_uid_length, pin, pin_length);
|
||||
}
|
||||
|
||||
uint8_t pbkdf_output[WC_SHA512_DIGEST_SIZE] = {0};
|
||||
|
||||
int pbkdf_result_code = wc_PBKDF2(
|
||||
&pbkdf_output[0],
|
||||
pbkdf_key,
|
||||
pbkdf_key_length,
|
||||
&crypto_settings->salt[0],
|
||||
CRYPTO_SALT_LENGTH,
|
||||
PBKDF2_ITERATIONS_COUNT,
|
||||
WC_SHA512_DIGEST_SIZE,
|
||||
WC_SHA512);
|
||||
|
||||
memset_s(pbkdf_key, pbkdf_key_length, 0, pbkdf_key_length);
|
||||
free(pbkdf_key);
|
||||
|
||||
if(pbkdf_result_code == 0) {
|
||||
uint8_t offset = pbkdf_output[WC_SHA512_DIGEST_SIZE - 1] %
|
||||
(WC_SHA512_DIGEST_SIZE - CRYPTO_IV_LENGTH - 1);
|
||||
memcpy(&crypto_settings->iv[0], &pbkdf_output[offset], CRYPTO_IV_LENGTH);
|
||||
result = CryptoSeedIVResultFlagSuccess;
|
||||
if(crypto_settings->crypto_verify_data == NULL) {
|
||||
const uint8_t* crypto_vkey = get_crypto_verify_key();
|
||||
uint8_t crypto_vkey_length = get_crypto_verify_key_length();
|
||||
FURI_LOG_I(LOGGING_TAG, "Generating crypto verify data");
|
||||
crypto_settings->crypto_verify_data = malloc(crypto_vkey_length);
|
||||
furi_check(crypto_settings->crypto_verify_data != NULL);
|
||||
crypto_settings->crypto_verify_data_length = crypto_vkey_length;
|
||||
|
||||
crypto_settings->crypto_verify_data = totp_crypto_encrypt_v3(
|
||||
crypto_vkey,
|
||||
crypto_vkey_length,
|
||||
crypto_settings,
|
||||
&crypto_settings->crypto_verify_data_length);
|
||||
|
||||
crypto_settings->pin_required = pin != NULL && pin_length > 0;
|
||||
|
||||
result |= CryptoSeedIVResultFlagNewCryptoVerifyData;
|
||||
}
|
||||
} else {
|
||||
result = CryptoSeedIVResultFailed;
|
||||
}
|
||||
|
||||
memset_s(&pbkdf_output[0], WC_SHA512_DIGEST_SIZE, 0, WC_SHA512_DIGEST_SIZE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool totp_crypto_verify_key_v3(const CryptoSettings* crypto_settings) {
|
||||
size_t decrypted_key_length;
|
||||
uint8_t* decrypted_key = totp_crypto_decrypt_v3(
|
||||
crypto_settings->crypto_verify_data,
|
||||
crypto_settings->crypto_verify_data_length,
|
||||
crypto_settings,
|
||||
&decrypted_key_length);
|
||||
|
||||
const uint8_t* crypto_vkey = get_crypto_verify_key();
|
||||
uint8_t crypto_vkey_length = get_crypto_verify_key_length();
|
||||
bool key_valid = true;
|
||||
for(uint8_t i = 0; i < crypto_vkey_length && key_valid; i++) {
|
||||
if(decrypted_key[i] != crypto_vkey[i]) key_valid = false;
|
||||
}
|
||||
|
||||
free(decrypted_key);
|
||||
|
||||
return key_valid;
|
||||
}
|
||||
52
applications/external/totp/services/crypto/crypto_v3.h
vendored
Normal file
52
applications/external/totp/services/crypto/crypto_v3.h
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "../../types/crypto_settings.h"
|
||||
#include "common_types.h"
|
||||
|
||||
/**
|
||||
* @brief Encrypts plain data using built-in certificate and given initialization vector (IV)
|
||||
* @param plain_data plain data to be encrypted
|
||||
* @param plain_data_length plain data length
|
||||
* @param crypto_settings crypto settings
|
||||
* @param[out] encrypted_data_length encrypted data length
|
||||
* @return Encrypted data
|
||||
*/
|
||||
uint8_t* totp_crypto_encrypt_v3(
|
||||
const uint8_t* plain_data,
|
||||
const size_t plain_data_length,
|
||||
const CryptoSettings* crypto_settings,
|
||||
size_t* encrypted_data_length);
|
||||
|
||||
/**
|
||||
* @brief Decrypts encrypted data using built-in certificate and given initialization vector (IV)
|
||||
* @param encrypted_data encrypted data to be decrypted
|
||||
* @param encrypted_data_length encrypted data length
|
||||
* @param crypto_settings crypto settings
|
||||
* @param[out] decrypted_data_length decrypted data length
|
||||
* @return Decrypted data
|
||||
*/
|
||||
uint8_t* totp_crypto_decrypt_v3(
|
||||
const uint8_t* encrypted_data,
|
||||
const size_t encrypted_data_length,
|
||||
const CryptoSettings* crypto_settings,
|
||||
size_t* decrypted_data_length);
|
||||
|
||||
/**
|
||||
* @brief Seed initialization vector (IV) using user's PIN
|
||||
* @param crypto_settings crypto settings
|
||||
* @param pin user's PIN
|
||||
* @param pin_length user's PIN length
|
||||
* @return Results of seeding IV
|
||||
*/
|
||||
CryptoSeedIVResult
|
||||
totp_crypto_seed_iv_v3(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length);
|
||||
|
||||
/**
|
||||
* @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption
|
||||
* @param crypto_settings crypto settings
|
||||
* @return \c true if cryptographic information is valid; \c false otherwise
|
||||
*/
|
||||
bool totp_crypto_verify_key_v3(const CryptoSettings* crypto_settings);
|
||||
14
applications/external/totp/services/crypto/polyfills.h
vendored
Normal file
14
applications/external/totp/services/crypto/polyfills.h
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_crypto.h>
|
||||
|
||||
#ifndef FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_START
|
||||
|
||||
// FW Crypto API is outdated, let's polyfill it
|
||||
#define FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_START (12u)
|
||||
#define FURI_HAL_CRYPTO_ENCLAVE_USER_KEY_SLOT_END (100u)
|
||||
#define furi_hal_crypto_enclave_ensure_key furi_hal_crypto_verify_key
|
||||
#define furi_hal_crypto_enclave_load_key furi_hal_crypto_store_load_key
|
||||
#define furi_hal_crypto_enclave_unload_key furi_hal_crypto_store_unload_key
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user