crypto_v2.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "crypto_v2.h"
  2. #include <furi_hal_crypto.h>
  3. #include <furi_hal_random.h>
  4. #include <furi_hal_version.h>
  5. #include "../../types/common.h"
  6. #include "../hmac/hmac_sha512.h"
  7. #include "memset_s.h"
  8. #include "constants.h"
  9. #define CRYPTO_ALIGNMENT_FACTOR (16)
  10. static const uint8_t* get_device_uid() {
  11. return (const uint8_t*)UID64_BASE; //-V566
  12. }
  13. static uint8_t get_device_uid_length() {
  14. return furi_hal_version_uid_size();
  15. }
  16. static const uint8_t* get_crypto_verify_key() {
  17. return get_device_uid();
  18. }
  19. static uint8_t get_crypto_verify_key_length() {
  20. return get_device_uid_length();
  21. }
  22. uint8_t* totp_crypto_encrypt_v2(
  23. const uint8_t* plain_data,
  24. const size_t plain_data_length,
  25. const uint8_t* iv,
  26. uint8_t key_slot,
  27. size_t* encrypted_data_length) {
  28. uint8_t* encrypted_data;
  29. size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR;
  30. if(remain) {
  31. size_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR;
  32. uint8_t* plain_data_aligned = malloc(plain_data_aligned_length);
  33. furi_check(plain_data_aligned != NULL);
  34. memset(plain_data_aligned, 0, plain_data_aligned_length);
  35. memcpy(plain_data_aligned, plain_data, plain_data_length);
  36. encrypted_data = malloc(plain_data_aligned_length);
  37. furi_check(encrypted_data != NULL);
  38. *encrypted_data_length = plain_data_aligned_length;
  39. furi_check(
  40. furi_hal_crypto_store_load_key(key_slot, iv) &&
  41. furi_hal_crypto_encrypt(
  42. plain_data_aligned, encrypted_data, plain_data_aligned_length) &&
  43. furi_hal_crypto_store_unload_key(key_slot),
  44. "Encryption failed");
  45. memset_s(plain_data_aligned, plain_data_aligned_length, 0, plain_data_aligned_length);
  46. free(plain_data_aligned);
  47. } else {
  48. encrypted_data = malloc(plain_data_length);
  49. furi_check(encrypted_data != NULL);
  50. *encrypted_data_length = plain_data_length;
  51. furi_check(
  52. furi_hal_crypto_store_load_key(key_slot, iv) &&
  53. furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length) &&
  54. furi_hal_crypto_store_unload_key(key_slot),
  55. "Encryption failed");
  56. }
  57. return encrypted_data;
  58. }
  59. uint8_t* totp_crypto_decrypt_v2(
  60. const uint8_t* encrypted_data,
  61. const size_t encrypted_data_length,
  62. const uint8_t* iv,
  63. uint8_t key_slot,
  64. size_t* decrypted_data_length) {
  65. *decrypted_data_length = encrypted_data_length;
  66. uint8_t* decrypted_data = malloc(*decrypted_data_length);
  67. furi_check(decrypted_data != NULL);
  68. furi_check(
  69. furi_hal_crypto_store_load_key(key_slot, iv) &&
  70. furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length) &&
  71. furi_hal_crypto_store_unload_key(key_slot),
  72. "Decryption failed");
  73. return decrypted_data;
  74. }
  75. CryptoSeedIVResult
  76. totp_crypto_seed_iv_v2(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) {
  77. CryptoSeedIVResult result;
  78. if(plugin_state->crypto_verify_data == NULL) {
  79. FURI_LOG_I(LOGGING_TAG, "Generating new IV");
  80. furi_hal_random_fill_buf(&plugin_state->base_iv[0], CRYPTO_IV_LENGTH);
  81. }
  82. memcpy(&plugin_state->iv[0], &plugin_state->base_iv[0], CRYPTO_IV_LENGTH);
  83. const uint8_t* device_uid = get_device_uid();
  84. uint8_t device_uid_length = get_device_uid_length();
  85. uint8_t hmac_key_length = device_uid_length;
  86. if(pin != NULL && pin_length > 0) {
  87. hmac_key_length += pin_length;
  88. }
  89. uint8_t* hmac_key = malloc(hmac_key_length);
  90. furi_check(hmac_key != NULL);
  91. memcpy(hmac_key, device_uid, device_uid_length);
  92. if(pin != NULL && pin_length > 0) {
  93. memcpy(hmac_key + device_uid_length, pin, pin_length);
  94. }
  95. uint8_t hmac[HMAC_SHA512_RESULT_SIZE] = {0};
  96. int hmac_result_code = hmac_sha512(
  97. hmac_key, hmac_key_length, &plugin_state->base_iv[0], CRYPTO_IV_LENGTH, &hmac[0]);
  98. memset_s(hmac_key, hmac_key_length, 0, hmac_key_length);
  99. free(hmac_key);
  100. if(hmac_result_code == 0) {
  101. uint8_t offset =
  102. hmac[HMAC_SHA512_RESULT_SIZE - 1] % (HMAC_SHA512_RESULT_SIZE - CRYPTO_IV_LENGTH - 1);
  103. memcpy(&plugin_state->iv[0], &hmac[offset], CRYPTO_IV_LENGTH);
  104. result = CryptoSeedIVResultFlagSuccess;
  105. if(plugin_state->crypto_verify_data == NULL) {
  106. const uint8_t* crypto_vkey = get_crypto_verify_key();
  107. uint8_t crypto_vkey_length = get_crypto_verify_key_length();
  108. FURI_LOG_I(LOGGING_TAG, "Generating crypto verify data");
  109. plugin_state->crypto_verify_data = malloc(crypto_vkey_length);
  110. furi_check(plugin_state->crypto_verify_data != NULL);
  111. plugin_state->crypto_verify_data_length = crypto_vkey_length;
  112. plugin_state->crypto_verify_data = totp_crypto_encrypt_v2(
  113. crypto_vkey,
  114. crypto_vkey_length,
  115. &plugin_state->iv[0],
  116. plugin_state->crypto_key_slot,
  117. &plugin_state->crypto_verify_data_length);
  118. plugin_state->pin_set = pin != NULL && pin_length > 0;
  119. result |= CryptoSeedIVResultFlagNewCryptoVerifyData;
  120. }
  121. } else {
  122. result = CryptoSeedIVResultFailed;
  123. }
  124. return result;
  125. }
  126. bool totp_crypto_verify_key_v2(const PluginState* plugin_state) {
  127. size_t decrypted_key_length;
  128. uint8_t* decrypted_key = totp_crypto_decrypt_v2(
  129. plugin_state->crypto_verify_data,
  130. plugin_state->crypto_verify_data_length,
  131. &plugin_state->iv[0],
  132. plugin_state->crypto_key_slot,
  133. &decrypted_key_length);
  134. const uint8_t* crypto_vkey = get_crypto_verify_key();
  135. uint8_t crypto_vkey_length = get_crypto_verify_key_length();
  136. bool key_valid = true;
  137. for(uint8_t i = 0; i < crypto_vkey_length && key_valid; i++) {
  138. if(decrypted_key[i] != crypto_vkey[i]) key_valid = false;
  139. }
  140. free(decrypted_key);
  141. return key_valid;
  142. }