cryptoengine.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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. extern const uint8_t disk1_mbr[];
  41. #define CHACHA_BLOCK_SIZE 64
  42. #define CHACHA_BUFFER_SIZE (CHACHA_BLOCK_SIZE * 16)
  43. #define LBA_SIZE 512
  44. #define CHACHA_INLINE
  45. #ifndef CHACHA_INLINE
  46. static uint8_t chacha_tmp[CHACHA_BUFFER_SIZE];
  47. static uint32_t chacha_processed;
  48. #endif
  49. int flash_decrypt_read_sector(uint32_t sector, uint8_t *buf)
  50. {
  51. if (cryptoengine_check_vault() < 0)
  52. return -1;
  53. if (fsm_get() < VAULT_MAIN_MENU)
  54. return -1;
  55. if ((sector * SPI_FLASH_SECTOR_SIZE) >= DRIVE_FLASH_SIZE)
  56. return -1;
  57. flash_read(DRIVE_FLASH_OFFSET + sector * SPI_FLASH_SECTOR_SIZE, buf,
  58. SPI_FLASH_SECTOR_SIZE);
  59. wc_Chacha_SetIV(&cha, hdr_cache.host_seed, sector * (SPI_FLASH_SECTOR_SIZE / CHACHA_BLOCK_SIZE));
  60. #ifndef CHACHA_INLINE
  61. chacha_processed = 0;
  62. while (chacha_processed < SPI_FLASH_SECTOR_SIZE) {
  63. wc_Chacha_Process(&cha, chacha_tmp, buf + chacha_processed,
  64. CHACHA_BUFFER_SIZE);
  65. memcpy(buf + chacha_processed, chacha_tmp, CHACHA_BUFFER_SIZE);
  66. chacha_processed += CHACHA_BUFFER_SIZE;
  67. }
  68. #else
  69. wc_Chacha_Process(&cha, buf, buf, SPI_FLASH_SECTOR_SIZE);
  70. #endif
  71. if (sector == 0) {
  72. memcpy(buf, disk1_mbr, LBA_SIZE);
  73. }
  74. return 0;
  75. }
  76. int flash_encrypt_write_sector(uint32_t sector, uint8_t *buf)
  77. {
  78. if (cryptoengine_check_vault() < 0)
  79. return -1;
  80. if (fsm_get() < VAULT_MAIN_MENU)
  81. return -1;
  82. if ((sector * SPI_FLASH_SECTOR_SIZE) >= DRIVE_FLASH_SIZE)
  83. return -1;
  84. if (sector == 0) {
  85. memcpy(buf, disk1_mbr, LBA_SIZE);
  86. }
  87. wc_Chacha_SetIV(&cha, hdr_cache.host_seed, sector * (SPI_FLASH_SECTOR_SIZE / CHACHA_BLOCK_SIZE));
  88. #ifndef CHACHA_INLINE
  89. chacha_processed = 0;
  90. while (chacha_processed < SPI_FLASH_SECTOR_SIZE) {
  91. wc_Chacha_Process(&cha, chacha_tmp, buf + chacha_processed,
  92. CHACHA_BUFFER_SIZE);
  93. memcpy(buf + chacha_processed, chacha_tmp, CHACHA_BUFFER_SIZE);
  94. chacha_processed += CHACHA_BUFFER_SIZE;
  95. }
  96. #else
  97. wc_Chacha_Process(&cha, buf, buf, SPI_FLASH_SECTOR_SIZE);
  98. #endif
  99. flash_write(DRIVE_FLASH_OFFSET + sector * SPI_FLASH_SECTOR_SIZE, buf,
  100. SPI_FLASH_SECTOR_SIZE);
  101. return 0;
  102. }
  103. int flash_decrypt_read_svc(struct vault_service *out, uint32_t addr)
  104. {
  105. if (cryptoengine_check_vault() < 0)
  106. return -1;
  107. flash_read(addr, &svc_cache, SVC_SIZE);
  108. memcpy(out, (uint8_t *)(&svc_cache), SVC_ENC_OFF);
  109. wc_Chacha_SetIV(&cha, hdr_cache.host_seed, addr);
  110. wc_Chacha_Process(&cha, (uint8_t *)out + SVC_ENC_OFF, ((uint8_t *)&svc_cache) + SVC_ENC_OFF, SVC_ENC_SIZE);
  111. return 0;
  112. }
  113. static int flash_encrypt_write_svc(const struct vault_service *svc, uint32_t idx)
  114. {
  115. uint32_t addr = idx * SVC_SIZE + SVC_FLASH_OFFSET;
  116. if (cryptoengine_check_vault() < 0)
  117. return -1;
  118. wc_Chacha_SetIV(&cha, hdr_cache.host_seed, addr);
  119. wc_Chacha_Process(&cha, (uint8_t *)&svc_cache, (uint8_t *)svc, SVC_SIZE);
  120. flash_write_svc(&svc_cache, idx);
  121. }
  122. int cryptoengine_verify_passphrase(const char *passphrase, int *res)
  123. {
  124. int ret = -1;
  125. int i;
  126. uint8_t SecretKey[CRYPTO_KEY_SIZE];
  127. uint8_t DecryptedSignature[PK_SIGNATURE_SIZE];
  128. mp_int r, s;
  129. mp_init(&r);
  130. mp_init(&s);
  131. *res = 0;
  132. if (cryptoengine_check_vault() < 0) {
  133. return -1;
  134. }
  135. ret = wc_PBKDF2(SecretKey, passphrase, strlen(passphrase), hdr_cache.host_salt, SALT_LEN, 1000, 32, SHA512);
  136. if (ret < 0)
  137. return ret;
  138. wc_Chacha_SetKey(&cha, SecretKey, CRYPTO_KEY_SIZE);
  139. wc_Chacha_SetIV(&cha, hdr_cache.host_seed, 0);
  140. wc_Chacha_Process(&cha, DecryptedSignature, hdr_cache.signature, PK_SIGNATURE_SIZE);
  141. wc_ecc_init(&ecc);
  142. if (wc_ecc_import_unsigned(&ecc, hdr_cache.auth_pubkey,
  143. hdr_cache.auth_pubkey + CRYPTO_KEY_SIZE,
  144. NULL, ECC_SECP256R1) < 0) {
  145. mp_free(&r);
  146. mp_free(&s);
  147. wc_ecc_free(&ecc);
  148. return -1;
  149. }
  150. mp_read_unsigned_bin(&r, DecryptedSignature, CRYPTO_KEY_SIZE);
  151. mp_read_unsigned_bin(&s, DecryptedSignature + CRYPTO_KEY_SIZE,
  152. CRYPTO_KEY_SIZE);
  153. ret = wc_ecc_verify_hash_ex(&r, &s, hdr_cache.digest, VAULT_DIGEST_SIZE,
  154. res, &ecc);
  155. mp_free(&r);
  156. mp_free(&s);
  157. if ((ret < 0) || (*res != 1)) {
  158. if (*res == 0)
  159. gpio_put(16, 0);
  160. wc_ecc_free(&ecc);
  161. }
  162. return ret;
  163. }
  164. static void hdr_cache_load(void)
  165. {
  166. flash_read(VAULT_FLASH_OFFSET, &hdr_cache, sizeof(struct vault_header));
  167. }
  168. uint8_t checked_digest[VAULT_DIGEST_SIZE];
  169. int cryptoengine_hdr_sha_check(const struct vault_header *vh)
  170. {
  171. Sha512 sha;
  172. int hash, hash_len;
  173. wc_InitSha512(&sha);
  174. for (hash = 0; hash < SHA_PAYLOAD_SIZE;) {
  175. hash_len = WC_SHA512_BLOCK_SIZE;
  176. if ((SHA_PAYLOAD_SIZE - hash) < hash_len)
  177. hash_len = SHA_PAYLOAD_SIZE - hash;
  178. wc_Sha512Update(&sha, ((uint8_t*)vh) + hash, hash_len);
  179. hash += hash_len;
  180. }
  181. wc_Sha512Final(&sha, checked_digest);
  182. if(memcmp(checked_digest, vh->digest, VAULT_DIGEST_SIZE) != 0) {
  183. return -1;
  184. }
  185. wc_Sha512Free(&sha);
  186. return 0;
  187. }
  188. int cryptoengine_svc_sha_check(const struct vault_service *vs)
  189. {
  190. Sha512 sha;
  191. int hash, hash_len;
  192. const uint32_t svc_sha_payload_size = (sizeof(struct vault_service) - (VAULT_DIGEST_SIZE + PK_SIGNATURE_SIZE));
  193. wc_InitSha512(&sha);
  194. for (hash = 0; hash < svc_sha_payload_size;) {
  195. hash_len = WC_SHA512_BLOCK_SIZE;
  196. if ((svc_sha_payload_size - hash) < hash_len)
  197. hash_len = svc_sha_payload_size - hash;
  198. wc_Sha512Update(&sha, ((uint8_t*)vs) + hash, hash_len);
  199. hash += hash_len;
  200. }
  201. wc_Sha512Final(&sha, checked_digest);
  202. if(memcmp(checked_digest, vs->dig, VAULT_DIGEST_SIZE) != 0) {
  203. return -1;
  204. }
  205. wc_Sha512Free(&sha);
  206. return 0;
  207. }
  208. int cryptoengine_svc_sig_verify(const struct vault_service *vs, int *res)
  209. {
  210. int ret;
  211. mp_int r, s;
  212. mp_init(&r);
  213. mp_init(&s);
  214. mp_read_unsigned_bin(&r, vs->sig, CRYPTO_KEY_SIZE);
  215. mp_read_unsigned_bin(&s, vs->sig + CRYPTO_KEY_SIZE, CRYPTO_KEY_SIZE);
  216. ret = wc_ecc_verify_hash_ex(&r, &s, vs->dig, VAULT_DIGEST_SIZE, res, &ecc);
  217. mp_free(&r);
  218. mp_free(&s);
  219. return ret;
  220. }
  221. int cryptoengine_check_vault(void)
  222. {
  223. hdr_cache_load();
  224. if (hdr_cache.magic != VAULT_MAGIC) {
  225. return -1;
  226. }
  227. /* Checking hdr integrity */
  228. if (cryptoengine_hdr_sha_check(&hdr_cache) < 0)
  229. return -1;
  230. /* Vault seems valid, integrity check OK */
  231. return 0;
  232. }
  233. int cryptoengine_import_service(struct vault_service *vs, uint32_t idx)
  234. {
  235. uint32_t address = SVC_FLASH_OFFSET + SVC_SIZE * idx;
  236. int res;
  237. if (cryptoengine_check_vault() < 0)
  238. return -1;
  239. memcpy(&svc_cache, ((uint8_t *)vs), SVC_ENC_OFF);
  240. wc_Chacha_SetIV(&cha, hdr_cache.host_seed, address);
  241. wc_Chacha_Process(&cha, ((uint8_t *)&svc_cache) + SVC_ENC_OFF,
  242. ((uint8_t *)vs) + SVC_ENC_OFF, SVC_ENC_SIZE);
  243. if (cryptoengine_svc_sha_check(&svc_cache) < 0) {
  244. return -1;
  245. }
  246. if ((cryptoengine_svc_sig_verify(&svc_cache, &res) < 0) || (res != 1))
  247. {
  248. return -2;
  249. }
  250. flash_write_svc(vs, idx);
  251. return 0;
  252. }
  253. int cryptoengine_service_count(uint16_t *n_srv, uint16_t *first_avail)
  254. {
  255. int i = 0;
  256. *first_avail = (uint16_t)-1;
  257. *n_srv = 0;
  258. struct vault_service svc;
  259. if (cryptoengine_check_vault() < 0)
  260. return -1;
  261. while (1) {
  262. flash_read(SVC_FLASH_OFFSET + (i * SVC_SIZE), &svc, SVC_SIZE);
  263. if (svc.flags == SVC_FLAG_ACTIVE)
  264. (*n_srv)++;
  265. else if (svc.flags == SVC_FLAG_ERASED)
  266. *first_avail = i;
  267. else if (svc.flags == SVC_FLAG_UNUSED) {
  268. if (*first_avail == ((uint16_t)-1))
  269. *first_avail = i;
  270. break;
  271. }
  272. i++;
  273. }
  274. return *n_srv;
  275. }
  276. int cryptoengine_fill_vault_status(struct vault_status *vst)
  277. {
  278. if (cryptoengine_check_vault() < 0)
  279. return -1;
  280. memcpy(vst->id, &hdr_cache.id, 2 * sizeof(uint32_t));
  281. memcpy(vst->salt, &hdr_cache.host_salt, SALT_LEN);
  282. memcpy(vst->seed, &hdr_cache.host_seed, SEED_LEN);
  283. }