cryptoengine.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /* Motenpoche
  2. *
  3. * (c) 2023 Daniele Lacamera <root@danielinux.net>
  4. *
  5. *
  6. * Motenpoche is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Motenpoche is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  19. *
  20. */
  21. #include "user_settings.h"
  22. #include <stdint.h>
  23. #include "cryptoengine.h"
  24. #include "fsm.h"
  25. #include "flash.h"
  26. #include "class/cdc/cdc.h"
  27. #include "class/cdc/cdc_device.h"
  28. #include "bsp/board.h"
  29. #include "wolfssl/wolfcrypt/sha512.h"
  30. #include "wolfssl/wolfcrypt/pwdbased.h"
  31. #include "wolfssl/wolfcrypt/chacha.h"
  32. #include "wolfssl/wolfcrypt/ecc.h"
  33. #include "hardware/gpio.h"
  34. static struct vault_header hdr_cache;
  35. uint32_t sector_cache_id = 0xFFFFFFFF;
  36. static ChaCha cha;
  37. static ecc_key ecc;
  38. static struct vault_service svc_cache;
  39. static int svc_cache_id = -1;
  40. int flash_decrypt_read_svc(struct vault_service *out, uint32_t addr)
  41. {
  42. if (cryptoengine_check_vault() < 0)
  43. return -1;
  44. flash_read(addr, &svc_cache, SVC_SIZE);
  45. memcpy(out, (uint8_t *)(&svc_cache), SVC_ENC_OFF);
  46. wc_Chacha_SetIV(&cha, hdr_cache.host_seed, addr);
  47. wc_Chacha_Process(&cha, (uint8_t *)out + SVC_ENC_OFF, ((uint8_t *)&svc_cache) + SVC_ENC_OFF, SVC_ENC_SIZE);
  48. return 0;
  49. }
  50. static int flash_encrypt_write_svc(const struct vault_service *svc, uint32_t idx)
  51. {
  52. uint32_t addr = idx * SVC_SIZE + SVC_FLASH_OFFSET;
  53. if (cryptoengine_check_vault() < 0)
  54. return -1;
  55. wc_Chacha_SetIV(&cha, hdr_cache.host_seed, addr);
  56. wc_Chacha_Process(&cha, (uint8_t *)&svc_cache, (uint8_t *)svc, SVC_SIZE);
  57. flash_write_svc(&svc_cache, idx);
  58. }
  59. int cryptoengine_verify_passphrase(const char *passphrase, int *res)
  60. {
  61. int ret = -1;
  62. int i;
  63. uint8_t SecretKey[CRYPTO_KEY_SIZE];
  64. uint8_t DecryptedSignature[PK_SIGNATURE_SIZE];
  65. mp_int r, s;
  66. mp_init(&r);
  67. mp_init(&s);
  68. *res = 0;
  69. if (cryptoengine_check_vault() < 0) {
  70. return -1;
  71. }
  72. ret = wc_PBKDF2(SecretKey, passphrase, strlen(passphrase), hdr_cache.host_salt, SALT_LEN, 1000, 32, SHA512);
  73. if (ret < 0)
  74. return ret;
  75. wc_Chacha_SetKey(&cha, SecretKey, CRYPTO_KEY_SIZE);
  76. wc_Chacha_SetIV(&cha, hdr_cache.host_seed, 0);
  77. wc_Chacha_Process(&cha, DecryptedSignature, hdr_cache.signature, PK_SIGNATURE_SIZE);
  78. wc_ecc_init(&ecc);
  79. if (wc_ecc_import_unsigned(&ecc, hdr_cache.auth_pubkey,
  80. hdr_cache.auth_pubkey + CRYPTO_KEY_SIZE,
  81. NULL, ECC_SECP256R1) < 0) {
  82. mp_free(&r);
  83. mp_free(&s);
  84. wc_ecc_free(&ecc);
  85. return -1;
  86. }
  87. mp_read_unsigned_bin(&r, DecryptedSignature, CRYPTO_KEY_SIZE);
  88. mp_read_unsigned_bin(&s, DecryptedSignature + CRYPTO_KEY_SIZE,
  89. CRYPTO_KEY_SIZE);
  90. ret = wc_ecc_verify_hash_ex(&r, &s, hdr_cache.digest, VAULT_DIGEST_SIZE,
  91. res, &ecc);
  92. mp_free(&r);
  93. mp_free(&s);
  94. if ((ret < 0) || (*res != 1)) {
  95. if (*res == 0)
  96. gpio_put(16, 0);
  97. wc_ecc_free(&ecc);
  98. }
  99. return ret;
  100. }
  101. static void hdr_cache_load(void)
  102. {
  103. flash_read(VAULT_FLASH_OFFSET, &hdr_cache, sizeof(struct vault_header));
  104. }
  105. uint8_t checked_digest[VAULT_DIGEST_SIZE];
  106. int cryptoengine_hdr_sha_check(const struct vault_header *vh)
  107. {
  108. Sha512 sha;
  109. int hash, hash_len;
  110. wc_InitSha512(&sha);
  111. for (hash = 0; hash < SHA_PAYLOAD_SIZE;) {
  112. hash_len = WC_SHA512_BLOCK_SIZE;
  113. if ((SHA_PAYLOAD_SIZE - hash) < hash_len)
  114. hash_len = SHA_PAYLOAD_SIZE - hash;
  115. wc_Sha512Update(&sha, ((uint8_t*)vh) + hash, hash_len);
  116. hash += hash_len;
  117. }
  118. wc_Sha512Final(&sha, checked_digest);
  119. if(memcmp(checked_digest, vh->digest, VAULT_DIGEST_SIZE) != 0) {
  120. return -1;
  121. }
  122. wc_Sha512Free(&sha);
  123. return 0;
  124. }
  125. int cryptoengine_svc_sha_check(const struct vault_service *vs)
  126. {
  127. Sha512 sha;
  128. int hash, hash_len;
  129. const uint32_t svc_sha_payload_size = (sizeof(struct vault_service) - (VAULT_DIGEST_SIZE + PK_SIGNATURE_SIZE));
  130. wc_InitSha512(&sha);
  131. for (hash = 0; hash < svc_sha_payload_size;) {
  132. hash_len = WC_SHA512_BLOCK_SIZE;
  133. if ((svc_sha_payload_size - hash) < hash_len)
  134. hash_len = svc_sha_payload_size - hash;
  135. wc_Sha512Update(&sha, ((uint8_t*)vs) + hash, hash_len);
  136. hash += hash_len;
  137. }
  138. wc_Sha512Final(&sha, checked_digest);
  139. if(memcmp(checked_digest, vs->dig, VAULT_DIGEST_SIZE) != 0) {
  140. return -1;
  141. }
  142. wc_Sha512Free(&sha);
  143. return 0;
  144. }
  145. int cryptoengine_svc_sig_verify(const struct vault_service *vs, int *res)
  146. {
  147. int ret;
  148. mp_int r, s;
  149. mp_init(&r);
  150. mp_init(&s);
  151. mp_read_unsigned_bin(&r, vs->sig, CRYPTO_KEY_SIZE);
  152. mp_read_unsigned_bin(&s, vs->sig + CRYPTO_KEY_SIZE, CRYPTO_KEY_SIZE);
  153. ret = wc_ecc_verify_hash_ex(&r, &s, vs->dig, VAULT_DIGEST_SIZE, res, &ecc);
  154. mp_free(&r);
  155. mp_free(&s);
  156. return ret;
  157. }
  158. int cryptoengine_check_vault(void)
  159. {
  160. hdr_cache_load();
  161. if (hdr_cache.magic != VAULT_MAGIC) {
  162. return -1;
  163. }
  164. /* Checking hdr integrity */
  165. if (cryptoengine_hdr_sha_check(&hdr_cache) < 0)
  166. return -1;
  167. /* Vault seems valid, integrity check OK */
  168. return 0;
  169. }
  170. int cryptoengine_import_service(struct vault_service *vs, uint32_t idx)
  171. {
  172. uint32_t address = SVC_FLASH_OFFSET + SVC_SIZE * idx;
  173. int res;
  174. if (cryptoengine_check_vault() < 0)
  175. return -1;
  176. memcpy(&svc_cache, ((uint8_t *)vs), SVC_ENC_OFF);
  177. wc_Chacha_SetIV(&cha, hdr_cache.host_seed, address);
  178. wc_Chacha_Process(&cha, ((uint8_t *)&svc_cache) + SVC_ENC_OFF,
  179. ((uint8_t *)vs) + SVC_ENC_OFF, SVC_ENC_SIZE);
  180. if (cryptoengine_svc_sha_check(&svc_cache) < 0) {
  181. return -1;
  182. }
  183. if ((cryptoengine_svc_sig_verify(&svc_cache, &res) < 0) || (res != 1))
  184. {
  185. return -2;
  186. }
  187. flash_write_svc(vs, idx);
  188. return 0;
  189. }
  190. int cryptoengine_service_count(uint16_t *n_srv, uint16_t *first_avail)
  191. {
  192. int i = 0;
  193. *first_avail = (uint16_t)-1;
  194. *n_srv = 0;
  195. struct vault_service svc;
  196. if (cryptoengine_check_vault() < 0)
  197. return -1;
  198. while (1) {
  199. flash_read(SVC_FLASH_OFFSET + (i * SVC_SIZE), &svc, SVC_SIZE);
  200. if (svc.flags == SVC_FLAG_ACTIVE)
  201. (*n_srv)++;
  202. else if (svc.flags == SVC_FLAG_ERASED)
  203. *first_avail = i;
  204. else if (svc.flags == SVC_FLAG_UNUSED) {
  205. if (*first_avail == ((uint16_t)-1))
  206. *first_avail = i;
  207. break;
  208. }
  209. i++;
  210. }
  211. return *n_srv;
  212. }
  213. int cryptoengine_fill_vault_status(struct vault_status *vst)
  214. {
  215. if (cryptoengine_check_vault() < 0)
  216. return -1;
  217. memcpy(vst->id, &hdr_cache.id, 2 * sizeof(uint32_t));
  218. memcpy(vst->salt, &hdr_cache.host_salt, SALT_LEN);
  219. memcpy(vst->seed, &hdr_cache.host_seed, SEED_LEN);
  220. }