fuzzer.c 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616
  1. /**
  2. * Copyright (c) 2020-2022 Christian Reitter
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included
  12. * in all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
  18. * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. */
  22. #include <math.h>
  23. #include <stdint.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. // includes for potential target functions
  28. // based on test_check.c
  29. #include "address.h"
  30. #include "aes/aes.h"
  31. #include "base32.h"
  32. #include "base58.h"
  33. #include "bignum.h"
  34. #include "bip32.h"
  35. #include "bip39.h"
  36. #include "blake256.h"
  37. #include "blake2b.h"
  38. #include "blake2s.h"
  39. #include "chacha_drbg.h"
  40. #include "curves.h"
  41. #include "ecdsa.h"
  42. #include "ed25519-donna/ed25519-donna.h"
  43. #include "ed25519-donna/ed25519-keccak.h"
  44. #include "ed25519-donna/ed25519.h"
  45. #include "hasher.h"
  46. #include "hmac_drbg.h"
  47. #include "memzero.h"
  48. #include "monero/monero.h"
  49. #include "nem.h"
  50. #include "nist256p1.h"
  51. #include "pbkdf2.h"
  52. #include "rand.h"
  53. #include "rc4.h"
  54. #include "rfc6979.h"
  55. #include "script.h"
  56. #include "secp256k1.h"
  57. #include "segwit_addr.h"
  58. #include "sha2.h"
  59. #include "sha3.h"
  60. #include "shamir.h"
  61. #include "slip39.h"
  62. #include "slip39_wordlist.h"
  63. #include "zkp_bip340.h"
  64. #include "zkp_context.h"
  65. #include "zkp_ecdsa.h"
  66. #if defined(__has_feature)
  67. #if __has_feature(memory_sanitizer)
  68. #include <sanitizer/msan_interface.h>
  69. #endif
  70. #endif
  71. /* code design notes
  72. *
  73. * TODO note down design tradeoffs for this fuzzer style
  74. */
  75. /* code performance notes
  76. *
  77. * use #define over runtime checks for performance reasons
  78. * avoid VLA arrays for performance reasons
  79. * potential performance drawbacks of heap usage are accepted for better out of
  80. * bounds error detection some expensive functions are hidden with compile-time
  81. * switches fuzzer harnesses are meant to exit early if the preconditions are
  82. * not met
  83. */
  84. /* fuzzer input data handling */
  85. const uint8_t *fuzzer_ptr;
  86. size_t fuzzer_length;
  87. const uint8_t *fuzzer_input(size_t len) {
  88. if (fuzzer_length < len) {
  89. fuzzer_length = 0;
  90. return NULL;
  91. }
  92. const uint8_t *result = fuzzer_ptr;
  93. fuzzer_length -= len;
  94. fuzzer_ptr += len;
  95. return result;
  96. }
  97. /* fuzzer state handling */
  98. void fuzzer_reset_state(void) {
  99. // reset the PRNGs to make individual fuzzer runs deterministic
  100. srand(0);
  101. random_reseed(0);
  102. // clear internal caches
  103. // note: this is not strictly required for all fuzzer targets
  104. #if USE_BIP32_CACHE
  105. bip32_cache_clear();
  106. #endif
  107. #if USE_BIP39_CACHE
  108. bip39_cache_clear();
  109. #endif
  110. }
  111. void crash(void) {
  112. // intentionally exit the program
  113. // the fuzzer framework treats this as a crash
  114. exit(1);
  115. }
  116. // IDEA are there advantages to turning this into a macro?
  117. //
  118. // check the memory area for memory information leaks if MSAN is available,
  119. // crash if problems are detected
  120. void check_msan(void *pointer, size_t length) {
  121. #if defined(__has_feature)
  122. #if __has_feature(memory_sanitizer)
  123. // check `address` for memory info leakage
  124. __msan_check_mem_is_initialized(pointer, length);
  125. #else
  126. // ignore if MSan is not enabled
  127. (void)pointer;
  128. (void)length;
  129. #endif
  130. #else
  131. // ignore if the compiler does not know __has_feature()
  132. (void)pointer;
  133. (void)length;
  134. #endif
  135. }
  136. // simplify the pointer check after a var_pointer = malloc()
  137. // return -1 to mark fuzz input as uninteresting for the fuzz engine
  138. // warning: use only if no manual memory cleanup is needed
  139. #define RETURN_IF_NULL(var_pointer) \
  140. if (var_pointer == NULL) { \
  141. return -1; \
  142. }
  143. void zkp_initialize_context_or_crash(void) {
  144. // The current context usage has persistent side effects
  145. // TODO switch to frequent re-initialization where necessary
  146. if (!zkp_context_is_initialized()) {
  147. if (zkp_context_init() != 0) {
  148. crash();
  149. }
  150. }
  151. }
  152. /* individual fuzzer harness functions */
  153. int fuzz_bn_format(void) {
  154. bignum256 target_bignum;
  155. // we need some amount of initial data
  156. if (fuzzer_length < sizeof(target_bignum) + 1 + 1) {
  157. return -1;
  158. }
  159. #define FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE 512
  160. char buf[FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE] = {0};
  161. int ret = 0;
  162. // mutate the struct contents
  163. memcpy(&target_bignum, fuzzer_input(sizeof(target_bignum)),
  164. sizeof(target_bignum));
  165. uint8_t prefixlen = 0;
  166. uint8_t suffixlen = 0;
  167. uint32_t decimals = 0;
  168. int32_t exponent = 0;
  169. bool trailing = false;
  170. // range 1 to 128
  171. prefixlen = (fuzzer_input(1)[0] & 127) + 1;
  172. suffixlen = (fuzzer_input(1)[0] & 127) + 1;
  173. // check for the second half of the data
  174. if (fuzzer_length < (size_t)(prefixlen + suffixlen + 4 + 4 + 1 - 2)) {
  175. return -1;
  176. }
  177. memcpy(&decimals, fuzzer_input(4), 4);
  178. memcpy(&exponent, fuzzer_input(4), 4);
  179. trailing = (fuzzer_input(1)[0] & 1);
  180. // IDEA allow prefix == NULL
  181. char *prefix = malloc(prefixlen);
  182. RETURN_IF_NULL(prefix);
  183. // IDEA allow suffix == NULL
  184. char *suffix = malloc(suffixlen);
  185. if (suffix == NULL) {
  186. free(prefix);
  187. return -1;
  188. }
  189. memset(prefix, 0, prefixlen);
  190. memset(suffix, 0, suffixlen);
  191. // only fetch up to (length - 1) to ensure null termination together with the
  192. // memset
  193. memcpy(prefix, fuzzer_input(prefixlen - 1), prefixlen - 1);
  194. memcpy(suffix, fuzzer_input(suffixlen - 1), suffixlen - 1);
  195. ret = bn_format(&target_bignum, prefix, suffix, decimals, exponent, trailing,
  196. 0, buf, FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE);
  197. // basic sanity checks for the return values
  198. if (ret > FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE) {
  199. crash();
  200. }
  201. check_msan(&buf, FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE);
  202. free(prefix);
  203. free(suffix);
  204. return 0;
  205. }
  206. // arbitrarily chosen maximum size
  207. #define BASE32_DECODE_MAX_INPUT_LEN 512
  208. int fuzz_base32_decode(void) {
  209. if (fuzzer_length < 2 || fuzzer_length > BASE32_DECODE_MAX_INPUT_LEN) {
  210. return -1;
  211. }
  212. char *in_buffer = malloc(fuzzer_length);
  213. RETURN_IF_NULL(in_buffer);
  214. // basic heuristic: the decoded output will always fit in less or equal space
  215. uint8_t *out_buffer = malloc(fuzzer_length);
  216. if (out_buffer == NULL) {
  217. free(in_buffer);
  218. return -1;
  219. }
  220. size_t outlen = fuzzer_length;
  221. size_t raw_inlen = fuzzer_length;
  222. memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
  223. // null-terminate input buffer to prevent issues with strlen()
  224. in_buffer[raw_inlen - 1] = 0;
  225. uint8_t *ret = base32_decode(in_buffer, raw_inlen, out_buffer, outlen,
  226. BASE32_ALPHABET_RFC4648);
  227. if (ret != NULL) {
  228. check_msan(out_buffer, outlen);
  229. }
  230. free(in_buffer);
  231. free(out_buffer);
  232. return 0;
  233. }
  234. // arbitrarily chosen maximum size
  235. #define BASE32_ENCODE_MAX_INPUT_LEN 512
  236. int fuzz_base32_encode(void) {
  237. if (fuzzer_length > BASE32_ENCODE_MAX_INPUT_LEN) {
  238. return -1;
  239. }
  240. uint8_t *in_buffer = malloc(fuzzer_length);
  241. RETURN_IF_NULL(in_buffer);
  242. // TODO: find a better heuristic for output buffer size
  243. size_t outlen = 2 * fuzzer_length;
  244. char *out_buffer = malloc(outlen);
  245. if (out_buffer == NULL) {
  246. free(in_buffer);
  247. return -1;
  248. }
  249. // mutate in_buffer
  250. size_t raw_inlen = fuzzer_length;
  251. memcpy(in_buffer, fuzzer_ptr, raw_inlen);
  252. fuzzer_input(raw_inlen);
  253. char *ret = base32_encode(in_buffer, raw_inlen, out_buffer, outlen,
  254. BASE32_ALPHABET_RFC4648);
  255. if (ret != NULL) {
  256. // the return value is a pointer to the end of the written buffer,
  257. // use it to calculate the used buffer area
  258. check_msan(out_buffer, ret - out_buffer);
  259. }
  260. free(in_buffer);
  261. free(out_buffer);
  262. return 0;
  263. }
  264. // internal limit is 128, try some extra bytes
  265. #define BASE58_ENCODE_MAX_INPUT_LEN 140
  266. int fuzz_base58_encode_check(void) {
  267. if (fuzzer_length > BASE58_ENCODE_MAX_INPUT_LEN) {
  268. return -1;
  269. }
  270. uint8_t *in_buffer = malloc(fuzzer_length);
  271. RETURN_IF_NULL(in_buffer);
  272. // TODO: find a better heuristic for output buffer size
  273. size_t outlen = 2 * fuzzer_length;
  274. char *out_buffer = malloc(outlen);
  275. if (out_buffer == NULL) {
  276. free(in_buffer);
  277. return -1;
  278. }
  279. // mutate in_buffer
  280. size_t raw_inlen = fuzzer_length;
  281. memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
  282. int ret = 0;
  283. // run multiple hasher variants for the same input
  284. base58_encode_check(in_buffer, raw_inlen, HASHER_SHA2D, out_buffer, outlen);
  285. base58_encode_check(in_buffer, raw_inlen, HASHER_BLAKED, out_buffer, outlen);
  286. base58_encode_check(in_buffer, raw_inlen, HASHER_GROESTLD_TRUNC, out_buffer,
  287. outlen);
  288. ret = base58_encode_check(in_buffer, raw_inlen, HASHER_SHA3K, out_buffer,
  289. outlen);
  290. // check one of the encode results
  291. if (ret != 0) {
  292. // the return value describes how many characters are written
  293. check_msan(out_buffer, ret);
  294. }
  295. free(in_buffer);
  296. free(out_buffer);
  297. return 0;
  298. }
  299. // internal limit is 128, try some extra bytes
  300. #define BASE58_DECODE_MAX_INPUT_LEN 140
  301. int fuzz_base58_decode_check(void) {
  302. if (fuzzer_length > BASE58_DECODE_MAX_INPUT_LEN) {
  303. return -1;
  304. }
  305. uint8_t *in_buffer = malloc(fuzzer_length + 1);
  306. RETURN_IF_NULL(in_buffer);
  307. size_t raw_inlen = fuzzer_length;
  308. memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
  309. uint8_t out_buffer[MAX_ADDR_RAW_SIZE] = {0};
  310. // force null-termination
  311. in_buffer[raw_inlen] = 0;
  312. const char *in_char = (const char *)in_buffer;
  313. // run multiple hasher variants for the same input
  314. base58_decode_check(in_char, HASHER_SHA2D, out_buffer, MAX_ADDR_RAW_SIZE);
  315. base58_decode_check(in_char, HASHER_BLAKED, out_buffer, MAX_ADDR_RAW_SIZE);
  316. base58_decode_check(in_char, HASHER_GROESTLD_TRUNC, out_buffer,
  317. MAX_ADDR_RAW_SIZE);
  318. base58_decode_check(in_char, HASHER_SHA3K, out_buffer, MAX_ADDR_RAW_SIZE);
  319. check_msan(out_buffer, MAX_ADDR_RAW_SIZE);
  320. free(in_buffer);
  321. return 0;
  322. }
  323. // arbitrarily chosen maximum size meant to limit input complexity
  324. // there is no input size limit for the target function
  325. #define XMR_BASE58_ADDR_DECODE_MAX_INPUT_LEN 512
  326. int fuzz_xmr_base58_addr_decode_check(void) {
  327. if (fuzzer_length > XMR_BASE58_ADDR_DECODE_MAX_INPUT_LEN) {
  328. return -1;
  329. }
  330. // TODO no null termination used !?
  331. // TODO use better size heuristic
  332. size_t outlen = fuzzer_length;
  333. char *in_buffer = malloc(fuzzer_length);
  334. RETURN_IF_NULL(in_buffer);
  335. uint8_t *out_buffer = malloc(outlen);
  336. if (out_buffer == NULL) {
  337. free(in_buffer);
  338. return -1;
  339. }
  340. // tag is only written to
  341. uint64_t tag = 0;
  342. size_t raw_inlen = fuzzer_length;
  343. // mutate in_buffer
  344. memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
  345. int ret = xmr_base58_addr_decode_check(in_buffer, raw_inlen, &tag, out_buffer,
  346. outlen);
  347. // IDEA check tag for expected values?
  348. // IDEA re-encode valid decoding results to check function consistency?
  349. if (ret != 0) {
  350. check_msan(out_buffer, outlen);
  351. }
  352. free(in_buffer);
  353. free(out_buffer);
  354. return 0;
  355. }
  356. // arbitrarily chosen maximum size
  357. #define XMR_BASE58_DECODE_MAX_INPUT_LEN 512
  358. // a more focused variant of the xmr_base58_addr_decode_check() harness
  359. int fuzz_xmr_base58_decode(void) {
  360. if (fuzzer_length > XMR_BASE58_DECODE_MAX_INPUT_LEN) {
  361. return -1;
  362. }
  363. // TODO better size heuristic
  364. size_t outlen = fuzzer_length;
  365. char *in_buffer = malloc(fuzzer_length);
  366. RETURN_IF_NULL(in_buffer);
  367. uint8_t *out_buffer = malloc(outlen);
  368. if (out_buffer == NULL) {
  369. free(in_buffer);
  370. return -1;
  371. }
  372. memset(out_buffer, 0, outlen);
  373. // mutate in_buffer
  374. size_t raw_inlen = fuzzer_length;
  375. memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
  376. xmr_base58_decode(in_buffer, raw_inlen, out_buffer, &outlen);
  377. free(in_buffer);
  378. free(out_buffer);
  379. return 0;
  380. }
  381. // arbitrarily chosen maximum size
  382. #define XMR_BASE58_ADDR_ENCODE_MAX_INPUT_LEN 140
  383. int fuzz_xmr_base58_addr_encode_check(void) {
  384. // tag_in is internally limited
  385. uint8_t tag_in;
  386. int ret1 = 0;
  387. size_t tag_size = sizeof(tag_in);
  388. if (fuzzer_length < tag_size + 1 ||
  389. fuzzer_length > XMR_BASE58_ADDR_ENCODE_MAX_INPUT_LEN) {
  390. return -1;
  391. }
  392. // mutate tag_in
  393. memcpy(&tag_in, fuzzer_input(tag_size), tag_size);
  394. // TODO better size heuristic
  395. size_t outlen = fuzzer_length * 2;
  396. uint8_t *in_buffer = malloc(fuzzer_length);
  397. RETURN_IF_NULL(in_buffer);
  398. char *out_buffer = malloc(outlen);
  399. if (out_buffer == NULL) {
  400. free(in_buffer);
  401. return -1;
  402. }
  403. memset(out_buffer, 0, outlen);
  404. // mutate in_buffer
  405. size_t raw_inlen = fuzzer_length;
  406. memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
  407. ret1 = xmr_base58_addr_encode_check(tag_in, in_buffer, raw_inlen, out_buffer,
  408. outlen);
  409. if (ret1 != 0) {
  410. // encoding successful
  411. uint64_t second_tag = 0;
  412. // TODO improve length
  413. uint8_t dummy_buffer[XMR_BASE58_ADDR_ENCODE_MAX_INPUT_LEN] = {0};
  414. int ret2 = 0;
  415. // ret1 represents the actual length of the encoded string
  416. // this is important for the decode function to succeed
  417. ret2 = xmr_base58_addr_decode_check(out_buffer, ret1, &second_tag,
  418. dummy_buffer, sizeof(dummy_buffer));
  419. // the tag comparison is between unequal types, but this is acceptable here
  420. if (ret2 == 0 || tag_in != second_tag) {
  421. crash();
  422. }
  423. }
  424. free(in_buffer);
  425. free(out_buffer);
  426. return 0;
  427. }
  428. // arbitrarily chosen maximum size
  429. #define XMR_BASE58_ENCODE_MAX_INPUT_LEN 512
  430. // a more focused variant of the xmr_base58_addr_encode_check() harness
  431. int fuzz_xmr_base58_encode(void) {
  432. if (fuzzer_length > XMR_BASE58_ENCODE_MAX_INPUT_LEN) {
  433. return -1;
  434. }
  435. // TODO better size heuristic
  436. size_t outlen = fuzzer_length * 2;
  437. uint8_t *in_buffer = malloc(fuzzer_length);
  438. RETURN_IF_NULL(in_buffer);
  439. char *out_buffer = malloc(outlen);
  440. if (out_buffer == NULL) {
  441. free(in_buffer);
  442. return -1;
  443. }
  444. memset(out_buffer, 0, outlen);
  445. // mutate in_buffer
  446. size_t raw_inlen = fuzzer_length;
  447. memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
  448. xmr_base58_encode(out_buffer, &outlen, in_buffer, raw_inlen);
  449. free(in_buffer);
  450. free(out_buffer);
  451. return 0;
  452. }
  453. int fuzz_xmr_serialize_varint(void) {
  454. // arbitrarily chosen maximum size
  455. #define XMR_SERIALIZE_VARINT_MAX_INPUT_LEN 128
  456. uint64_t varint_in;
  457. size_t varint_in_size = sizeof(varint_in);
  458. if (fuzzer_length <= varint_in_size ||
  459. fuzzer_length > XMR_SERIALIZE_VARINT_MAX_INPUT_LEN) {
  460. return -1;
  461. }
  462. uint8_t out_buffer[XMR_SERIALIZE_VARINT_MAX_INPUT_LEN] = {0};
  463. size_t outlen = sizeof(out_buffer);
  464. uint64_t varint_out = 0;
  465. // mutate varint_in
  466. memcpy(&varint_in, fuzzer_input(varint_in_size), varint_in_size);
  467. // mutate in_buffer
  468. size_t raw_inlen = fuzzer_length;
  469. uint8_t *in_buffer = malloc(raw_inlen);
  470. RETURN_IF_NULL(in_buffer);
  471. memcpy(in_buffer, fuzzer_input(raw_inlen), raw_inlen);
  472. // use the varint
  473. xmr_size_varint(varint_in);
  474. xmr_write_varint(out_buffer, outlen, varint_in);
  475. // use the input buffer
  476. xmr_read_varint(in_buffer, raw_inlen, &varint_out);
  477. // IDEA cross-check write/read results
  478. free(in_buffer);
  479. return 0;
  480. }
  481. // arbitrarily chosen maximum size
  482. #define NEM_VALIDATE_ADDRESS_MAX_INPUT_LEN 128
  483. int fuzz_nem_validate_address(void) {
  484. if (fuzzer_length < 1 || fuzzer_length > NEM_VALIDATE_ADDRESS_MAX_INPUT_LEN) {
  485. return -1;
  486. }
  487. uint8_t network = fuzzer_input(1)[0];
  488. size_t raw_inlen = fuzzer_length + 1;
  489. char *in_buffer = malloc(raw_inlen);
  490. RETURN_IF_NULL(in_buffer);
  491. // mutate the buffer
  492. memcpy(in_buffer, fuzzer_input(raw_inlen - 1), raw_inlen - 1);
  493. // force null-termination
  494. in_buffer[raw_inlen - 1] = 0;
  495. nem_validate_address(in_buffer, network);
  496. free(in_buffer);
  497. return 0;
  498. }
  499. int fuzz_nem_get_address(void) {
  500. unsigned char ed25519_public_key_fuzz[32] = {0};
  501. uint8_t version = 0;
  502. // TODO switch to < comparison?
  503. if (fuzzer_length != (sizeof(ed25519_public_key_fuzz) + sizeof(version))) {
  504. return -1;
  505. }
  506. char address[NEM_ADDRESS_SIZE + 1] = {0};
  507. memcpy(ed25519_public_key_fuzz, fuzzer_input(sizeof(ed25519_public_key_fuzz)),
  508. sizeof(ed25519_public_key_fuzz));
  509. memcpy(&version, fuzzer_input(sizeof(version)), sizeof(version));
  510. nem_get_address(ed25519_public_key_fuzz, version, address);
  511. check_msan(&address, sizeof(address));
  512. return 0;
  513. }
  514. int fuzz_xmr_get_subaddress_secret_key(void) {
  515. bignum256modm m = {0};
  516. uint32_t major = 0;
  517. uint32_t minor = 0;
  518. if (fuzzer_length != (sizeof(bignum256modm) + 2 * sizeof(uint32_t))) {
  519. return -1;
  520. }
  521. bignum256modm output = {0};
  522. memcpy(m, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm));
  523. memcpy(&major, fuzzer_input(sizeof(uint32_t)), sizeof(uint32_t));
  524. memcpy(&minor, fuzzer_input(sizeof(uint32_t)), sizeof(uint32_t));
  525. xmr_get_subaddress_secret_key(output, major, minor, m);
  526. check_msan(&output, sizeof(output));
  527. return 0;
  528. }
  529. int fuzz_xmr_derive_private_key(void) {
  530. bignum256modm base = {0};
  531. ge25519 deriv = {0};
  532. uint32_t idx = 0;
  533. if (fuzzer_length !=
  534. (sizeof(bignum256modm) + sizeof(ge25519) + sizeof(uint32_t))) {
  535. return -1;
  536. }
  537. memcpy(base, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm));
  538. memcpy(&deriv, fuzzer_input(sizeof(ge25519)), sizeof(ge25519));
  539. memcpy(&idx, fuzzer_input(sizeof(uint32_t)), sizeof(uint32_t));
  540. bignum256modm output = {0};
  541. xmr_derive_private_key(output, &deriv, idx, base);
  542. check_msan(&output, sizeof(output));
  543. return 0;
  544. }
  545. int fuzz_xmr_derive_public_key(void) {
  546. ge25519 base = {0};
  547. ge25519 deriv = {0};
  548. uint32_t idx = 0;
  549. if (fuzzer_length != (2 * sizeof(ge25519) + sizeof(uint32_t))) {
  550. return -1;
  551. }
  552. memcpy(&base, fuzzer_input(sizeof(ge25519)), sizeof(ge25519));
  553. memcpy(&deriv, fuzzer_input(sizeof(ge25519)), sizeof(ge25519));
  554. memcpy(&idx, fuzzer_input(sizeof(uint32_t)), sizeof(uint32_t));
  555. ge25519 output = {0};
  556. xmr_derive_public_key(&output, &deriv, idx, &base);
  557. check_msan(&output, sizeof(output));
  558. return 0;
  559. }
  560. #define SHAMIR_MAX_SHARE_COUNT 16
  561. #define SHAMIR_MAX_DATA_LEN (SHAMIR_MAX_SHARE_COUNT * SHAMIR_MAX_LEN)
  562. int fuzz_shamir_interpolate(void) {
  563. if (fuzzer_length != (2 * sizeof(uint8_t) + SHAMIR_MAX_SHARE_COUNT +
  564. SHAMIR_MAX_DATA_LEN + sizeof(size_t))) {
  565. return -1;
  566. }
  567. uint8_t result[SHAMIR_MAX_LEN] = {0};
  568. uint8_t result_index = 0;
  569. uint8_t share_indices[SHAMIR_MAX_SHARE_COUNT] = {0};
  570. uint8_t share_values_content[SHAMIR_MAX_SHARE_COUNT][SHAMIR_MAX_LEN] = {0};
  571. const uint8_t *share_values[SHAMIR_MAX_SHARE_COUNT] = {0};
  572. uint8_t share_count = 0;
  573. size_t len = 0;
  574. for (size_t i = 0; i < SHAMIR_MAX_SHARE_COUNT; i++) {
  575. share_values[i] = share_values_content[i];
  576. }
  577. memcpy(&result_index, fuzzer_input(sizeof(uint8_t)), sizeof(uint8_t));
  578. memcpy(&share_indices, fuzzer_input(SHAMIR_MAX_SHARE_COUNT),
  579. SHAMIR_MAX_SHARE_COUNT);
  580. memcpy(&share_values_content, fuzzer_input(SHAMIR_MAX_DATA_LEN),
  581. SHAMIR_MAX_DATA_LEN);
  582. memcpy(&share_count, fuzzer_input(sizeof(uint8_t)), sizeof(uint8_t));
  583. // note: this is platform specific via byte length of size_t
  584. memcpy(&len, fuzzer_input(sizeof(size_t)), sizeof(size_t));
  585. // mirror a check that the real code does
  586. if (share_count < 1 || share_count > SHAMIR_MAX_SHARE_COUNT) {
  587. return 0;
  588. }
  589. // (len > SHAMIR_MAX_LEN) is handled in the target function
  590. shamir_interpolate(result, result_index, share_indices, share_values,
  591. share_count, len);
  592. check_msan(&result, sizeof(result));
  593. return 0;
  594. }
  595. int fuzz_ecdsa_sign_digest_functions(void) {
  596. // bug result reference: https://github.com/trezor/trezor-firmware/pull/1697
  597. uint8_t curve_decider = 0;
  598. uint8_t priv_key[32] = {0};
  599. uint8_t digest[32] = {0};
  600. uint8_t sig1[64] = {0};
  601. uint8_t sig2[64] = {0};
  602. uint8_t pby1, pby2 = 0;
  603. if (fuzzer_length < 1 + sizeof(priv_key) + sizeof(digest)) {
  604. return -1;
  605. }
  606. const ecdsa_curve *curve;
  607. memcpy(&curve_decider, fuzzer_input(1), 1);
  608. memcpy(&priv_key, fuzzer_input(sizeof(priv_key)), sizeof(priv_key));
  609. memcpy(&digest, fuzzer_input(sizeof(digest)), sizeof(digest));
  610. // pick one of the standard curves
  611. if ((curve_decider & 0x1) == 1) {
  612. curve = &secp256k1;
  613. } else {
  614. curve = &nist256p1;
  615. }
  616. int res = 0;
  617. // IDEA optionally set a function for is_canonical() callback
  618. int res1 = ecdsa_sign_digest(curve, priv_key, digest, sig1, &pby1, NULL);
  619. // the zkp function variant is only defined for a specific curve
  620. if (curve == &secp256k1) {
  621. int res2 =
  622. zkp_ecdsa_sign_digest(curve, priv_key, digest, sig2, &pby2, NULL);
  623. if ((res1 == 0 && res2 != 0) || (res1 != 0 && res2 == 0)) {
  624. // one variant succeeded where the other did not
  625. crash();
  626. }
  627. if (res1 == 0 && res2 == 0) {
  628. if ((pby1 != pby2) || memcmp(&sig1, &sig2, sizeof(sig1)) != 0) {
  629. // result values are different
  630. crash();
  631. }
  632. }
  633. }
  634. // successful signing
  635. if (res1 == 0) {
  636. uint8_t pub_key[33] = {0};
  637. res = ecdsa_get_public_key33(curve, priv_key, pub_key);
  638. if (res != 0) {
  639. // pubkey derivation did not succeed
  640. crash();
  641. }
  642. res = ecdsa_verify_digest(curve, pub_key, sig1, digest);
  643. if (res != 0) {
  644. // verification did not succeed
  645. crash();
  646. }
  647. }
  648. return 0;
  649. }
  650. int fuzz_ecdsa_verify_digest_functions(void) {
  651. uint8_t curve_decider = 0;
  652. uint8_t hash[32] = {0};
  653. uint8_t sig[64] = {0};
  654. uint8_t pub_key[65] = {0};
  655. if (fuzzer_length < 1 + sizeof(hash) + sizeof(sig) + sizeof(pub_key)) {
  656. return -1;
  657. }
  658. memcpy(&curve_decider, fuzzer_input(1), 1);
  659. memcpy(&hash, fuzzer_input(sizeof(hash)), sizeof(hash));
  660. memcpy(&sig, fuzzer_input(sizeof(sig)), sizeof(sig));
  661. memcpy(&pub_key, fuzzer_input(sizeof(pub_key)), sizeof(pub_key));
  662. const ecdsa_curve *curve;
  663. // pick one of the standard curves
  664. if ((curve_decider & 0x1) == 1) {
  665. curve = &secp256k1;
  666. } else {
  667. curve = &nist256p1;
  668. }
  669. int res1 = ecdsa_verify_digest(curve, (const uint8_t *)&pub_key,
  670. (const uint8_t *)&sig, (const uint8_t *)&hash);
  671. if (res1 == 0) {
  672. // See if the fuzzer ever manages to get find a correct verification
  673. // intentionally trigger a crash to make this case observable
  674. // TODO this is not an actual problem, remove in the future
  675. crash();
  676. }
  677. // the zkp_ecdsa* function only accepts the secp256k1 curve
  678. if (curve == &secp256k1) {
  679. int res2 =
  680. zkp_ecdsa_verify_digest(curve, (const uint8_t *)&pub_key,
  681. (const uint8_t *)&sig, (const uint8_t *)&hash);
  682. // the error code behavior is different between both functions, compare only
  683. // verification state
  684. if ((res1 == 0 && res2 != 0) || (res1 != 0 && res2 == 0)) {
  685. // results differ, this is a problem
  686. crash();
  687. }
  688. }
  689. return 0;
  690. }
  691. int fuzz_word_index(void) {
  692. #define MAX_WORD_LENGTH 12
  693. if (fuzzer_length < MAX_WORD_LENGTH) {
  694. return -1;
  695. }
  696. char word[MAX_WORD_LENGTH + 1] = {0};
  697. memcpy(&word, fuzzer_ptr, MAX_WORD_LENGTH);
  698. size_t word_length = strlen(word);
  699. uint16_t index = 0;
  700. word_index(&index, (const char *)&word, word_length);
  701. return 0;
  702. }
  703. int fuzz_slip39_word_completion_mask(void) {
  704. if (fuzzer_length != 2) {
  705. return -1;
  706. }
  707. uint16_t sequence = (fuzzer_ptr[0] << 8) + fuzzer_ptr[1];
  708. fuzzer_input(2);
  709. slip39_word_completion_mask(sequence);
  710. return 0;
  711. }
  712. // regular MAX_MNEMONIC_LEN is 240, try some extra bytes
  713. #define MAX_MNEMONIC_FUZZ_LENGTH 256
  714. int fuzz_mnemonic_check(void) {
  715. if (fuzzer_length < MAX_MNEMONIC_FUZZ_LENGTH) {
  716. return -1;
  717. }
  718. char mnemonic[MAX_MNEMONIC_FUZZ_LENGTH + 1] = {0};
  719. memcpy(&mnemonic, fuzzer_ptr, MAX_MNEMONIC_FUZZ_LENGTH);
  720. // at the time of creation of this fuzzer harness, mnemonic_check()
  721. // internally calls mnemonic_to_bits() while checking the result
  722. int ret = mnemonic_check(mnemonic);
  723. (void)ret;
  724. /*
  725. if(ret == 1) {
  726. // correct result
  727. }
  728. */
  729. return 0;
  730. }
  731. int fuzz_mnemonic_from_data(void) {
  732. if (fuzzer_length < 16 || fuzzer_length > 32) {
  733. return -1;
  734. }
  735. const char *mnemo_result = mnemonic_from_data(fuzzer_ptr, fuzzer_length);
  736. if (mnemo_result != NULL) {
  737. int res = mnemonic_check(mnemo_result);
  738. if (res == 0) {
  739. // TODO the mnemonic_check() function is currently incorrectly rejecting
  740. // valid 15 and 21 word seeds
  741. // remove this workaround limitation later
  742. if (fuzzer_length != 20 && fuzzer_length != 28) {
  743. // the generated mnemonic has an invalid format
  744. crash();
  745. }
  746. }
  747. }
  748. // scrub the internal buffer to rule out persistent side effects
  749. mnemonic_clear();
  750. return 0;
  751. }
  752. // passphrase normally has a 64 or 256 byte length maximum
  753. #define MAX_PASSPHRASE_FUZZ_LENGTH 257
  754. int fuzz_mnemonic_to_seed(void) {
  755. if (fuzzer_length < MAX_MNEMONIC_FUZZ_LENGTH + MAX_PASSPHRASE_FUZZ_LENGTH) {
  756. return -1;
  757. }
  758. char mnemonic[MAX_PASSPHRASE_FUZZ_LENGTH + 1] = {0};
  759. char passphrase[MAX_MNEMONIC_FUZZ_LENGTH + 1] = {0};
  760. uint8_t seed[512 / 8] = {0};
  761. memcpy(&mnemonic, fuzzer_input(MAX_MNEMONIC_FUZZ_LENGTH),
  762. MAX_MNEMONIC_FUZZ_LENGTH);
  763. memcpy(&passphrase, fuzzer_input(MAX_PASSPHRASE_FUZZ_LENGTH),
  764. MAX_PASSPHRASE_FUZZ_LENGTH);
  765. mnemonic_to_seed(mnemonic, passphrase, seed, NULL);
  766. return 0;
  767. }
  768. int fuzz_ethereum_address_checksum(void) {
  769. uint8_t addr[20] = {0};
  770. char address[43] = {0};
  771. uint64_t chain_id = 0;
  772. bool rskip60 = false;
  773. if (fuzzer_length < sizeof(addr) + sizeof(address) + sizeof(chain_id) + 1) {
  774. return -1;
  775. }
  776. memcpy(addr, fuzzer_input(sizeof(addr)), sizeof(addr));
  777. memcpy(address, fuzzer_input(sizeof(address)), sizeof(address));
  778. memcpy(&chain_id, fuzzer_input(sizeof(chain_id)), sizeof(chain_id));
  779. // usually dependent on chain_id, but determined separately here
  780. rskip60 = (*fuzzer_input(1)) & 0x1;
  781. ethereum_address_checksum(addr, address, rskip60, chain_id);
  782. return 0;
  783. }
  784. int fuzz_aes(void) {
  785. if (fuzzer_length < 1 + 16 + 16 + 32) {
  786. return -1;
  787. }
  788. aes_encrypt_ctx ctxe;
  789. aes_decrypt_ctx ctxd;
  790. uint8_t ibuf[16] = {0};
  791. uint8_t obuf[16] = {0};
  792. uint8_t iv[16] = {0};
  793. uint8_t cbuf[16] = {0};
  794. const uint8_t *keylength_decider = fuzzer_input(1);
  795. // note: the unit test uses the fixed 32 byte key
  796. // 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
  797. uint8_t keybuf[32] = {0};
  798. memcpy(&keybuf, fuzzer_input(32), 32);
  799. #ifdef AES_VAR
  800. // try 128, 192, 256 bit key lengths
  801. size_t keylength = 32;
  802. switch (keylength_decider[0] & 0x3) {
  803. case 0:
  804. // invalid length
  805. keylength = 1;
  806. break;
  807. case 1:
  808. keylength = 16;
  809. break;
  810. case 2:
  811. keylength = 24;
  812. break;
  813. case 3:
  814. keylength = 32;
  815. break;
  816. }
  817. if (aes_encrypt_key((const unsigned char *)&keybuf, keylength, &ctxe) ||
  818. aes_decrypt_key((const unsigned char *)&keybuf, keylength, &ctxd)) {
  819. // initialization problems, stop processing
  820. // we expect this to happen with the invalid key length
  821. return 0;
  822. }
  823. #else
  824. // use a 256 bit key length
  825. (void)keylength_decider;
  826. aes_encrypt_key256((const unsigned char *)&keybuf, &ctxe);
  827. aes_decrypt_key256((const unsigned char *)&keybuf, &ctxd);
  828. #endif
  829. memcpy(ibuf, fuzzer_input(16), 16);
  830. memcpy(iv, fuzzer_input(16), 16);
  831. aes_ecb_encrypt(ibuf, obuf, 16, &ctxe);
  832. aes_ecb_decrypt(ibuf, obuf, 16, &ctxd);
  833. aes_cbc_encrypt(ibuf, obuf, 16, iv, &ctxe);
  834. aes_cbc_decrypt(ibuf, obuf, 16, iv, &ctxd);
  835. aes_cfb_encrypt(ibuf, obuf, 16, iv, &ctxe);
  836. aes_cfb_decrypt(ibuf, obuf, 16, iv, &ctxe);
  837. aes_ofb_encrypt(ibuf, obuf, 16, iv, &ctxe);
  838. aes_ofb_decrypt(ibuf, obuf, 16, iv, &ctxe);
  839. aes_ctr_encrypt(ibuf, obuf, 16, cbuf, aes_ctr_cbuf_inc, &ctxe);
  840. aes_ctr_decrypt(ibuf, obuf, 16, cbuf, aes_ctr_cbuf_inc, &ctxe);
  841. return 0;
  842. }
  843. int fuzz_chacha_drbg(void) {
  844. #define CHACHA_DRBG_ENTROPY_LENGTH 32
  845. #define CHACHA_DRBG_RESEED_LENGTH 32
  846. #define CHACHA_DRBG_NONCE_LENGTH 16
  847. #define CHACHA_DRBG_RESULT_LENGTH 16
  848. if (fuzzer_length < CHACHA_DRBG_ENTROPY_LENGTH + CHACHA_DRBG_RESEED_LENGTH +
  849. CHACHA_DRBG_NONCE_LENGTH) {
  850. return -1;
  851. }
  852. uint8_t entropy[CHACHA_DRBG_ENTROPY_LENGTH] = {0};
  853. uint8_t reseed[CHACHA_DRBG_RESEED_LENGTH] = {0};
  854. uint8_t nonce_bytes[CHACHA_DRBG_NONCE_LENGTH] = {0};
  855. uint8_t result[CHACHA_DRBG_RESULT_LENGTH] = {0};
  856. CHACHA_DRBG_CTX ctx;
  857. // IDEA switch to variable input sizes
  858. memcpy(&entropy, fuzzer_input(CHACHA_DRBG_ENTROPY_LENGTH),
  859. CHACHA_DRBG_ENTROPY_LENGTH);
  860. memcpy(&reseed, fuzzer_input(CHACHA_DRBG_RESEED_LENGTH),
  861. CHACHA_DRBG_RESEED_LENGTH);
  862. memcpy(&nonce_bytes, fuzzer_input(CHACHA_DRBG_NONCE_LENGTH),
  863. CHACHA_DRBG_NONCE_LENGTH);
  864. chacha_drbg_init(&ctx, entropy, sizeof(entropy), nonce_bytes,
  865. sizeof(nonce_bytes));
  866. chacha_drbg_reseed(&ctx, reseed, sizeof(reseed), NULL, 0);
  867. chacha_drbg_generate(&ctx, result, sizeof(result));
  868. return 0;
  869. }
  870. int fuzz_ed25519_sign_verify(void) {
  871. ed25519_secret_key secret_key;
  872. ed25519_signature signature;
  873. ed25519_public_key public_key;
  874. // length chosen arbitrarily
  875. uint8_t message[32] = {0};
  876. int ret = 0;
  877. if (fuzzer_length <
  878. sizeof(secret_key) + sizeof(signature) + sizeof(message)) {
  879. return -1;
  880. }
  881. memcpy(&secret_key, fuzzer_input(sizeof(secret_key)), sizeof(secret_key));
  882. memcpy(&signature, fuzzer_input(sizeof(signature)), sizeof(signature));
  883. memcpy(&message, fuzzer_input(sizeof(message)), sizeof(message));
  884. ed25519_publickey(secret_key, public_key);
  885. // sign message, this should always succeed
  886. ed25519_sign(message, sizeof(message), secret_key, signature);
  887. // verify message, we expect this to work
  888. ret = ed25519_sign_open(message, sizeof(message), public_key, signature);
  889. if (ret != 0) {
  890. // verification did not succeed
  891. crash();
  892. }
  893. return 0;
  894. }
  895. int fuzz_zkp_bip340_sign_digest(void) {
  896. uint8_t priv_key[32] = {0};
  897. uint8_t aux_input[32] = {0};
  898. uint8_t digest[32] = {0};
  899. uint8_t pub_key[32] = {0};
  900. uint8_t sig[64] = {0};
  901. if (fuzzer_length <
  902. sizeof(priv_key) + sizeof(aux_input) + sizeof(digest) + sizeof(sig)) {
  903. return -1;
  904. }
  905. memcpy(priv_key, fuzzer_input(sizeof(priv_key)), sizeof(priv_key));
  906. memcpy(digest, fuzzer_input(sizeof(digest)), sizeof(digest));
  907. // TODO leave initialized to 0x0?
  908. memcpy(aux_input, fuzzer_input(sizeof(aux_input)), sizeof(aux_input));
  909. // TODO leave initialized to 0x0?
  910. memcpy(sig, fuzzer_input(sizeof(sig)), sizeof(sig));
  911. zkp_bip340_get_public_key(priv_key, pub_key);
  912. check_msan(&pub_key, sizeof(pub_key));
  913. zkp_bip340_sign_digest(priv_key, digest, sig, aux_input);
  914. check_msan(&sig, sizeof(sig));
  915. check_msan(&aux_input, sizeof(aux_input));
  916. // IDEA test sign result?
  917. return 0;
  918. }
  919. int fuzz_zkp_bip340_verify_digest(void) {
  920. int res = 0;
  921. uint8_t pub_key[32] = {0};
  922. uint8_t digest[32] = {0};
  923. uint8_t sig[64] = {0};
  924. if (fuzzer_length < sizeof(digest) + sizeof(pub_key) + sizeof(sig)) {
  925. return -1;
  926. }
  927. memcpy(pub_key, fuzzer_input(sizeof(pub_key)), sizeof(pub_key));
  928. memcpy(digest, fuzzer_input(sizeof(digest)), sizeof(digest));
  929. memcpy(sig, fuzzer_input(sizeof(sig)), sizeof(sig));
  930. res = zkp_bip340_verify_digest(pub_key, sig, digest);
  931. // res == 0 is valid, but crash to make successful passes visible
  932. // TODO remove this later
  933. if (res == 0) {
  934. crash();
  935. }
  936. return 0;
  937. }
  938. int fuzz_zkp_bip340_tweak_keys(void) {
  939. uint8_t internal_priv[32] = {0};
  940. uint8_t root_hash[32] = {0};
  941. uint8_t internal_pub[32] = {0};
  942. uint8_t result[32] = {0};
  943. if (fuzzer_length <
  944. sizeof(internal_priv) + sizeof(root_hash) + sizeof(internal_pub)) {
  945. return -1;
  946. }
  947. memcpy(internal_priv, fuzzer_input(sizeof(internal_priv)),
  948. sizeof(internal_priv));
  949. memcpy(root_hash, fuzzer_input(sizeof(root_hash)), sizeof(root_hash));
  950. memcpy(internal_pub, fuzzer_input(sizeof(internal_pub)),
  951. sizeof(internal_pub));
  952. // IDEA act on return values
  953. zkp_bip340_tweak_private_key(internal_priv, root_hash, result);
  954. zkp_bip340_tweak_public_key(internal_pub, root_hash, result);
  955. return 0;
  956. }
  957. int fuzz_ecdsa_get_public_key_functions(void) {
  958. uint8_t privkey[32] = {0};
  959. uint8_t pubkey33_1[33] = {0};
  960. uint8_t pubkey33_2[33] = {0};
  961. uint8_t pubkey65_1[65] = {0};
  962. uint8_t pubkey65_2[65] = {0};
  963. // note: the zkp_ecdsa_* variants require this specific curve
  964. const ecdsa_curve *curve = &secp256k1;
  965. if (fuzzer_length < sizeof(privkey)) {
  966. return -1;
  967. }
  968. memcpy(privkey, fuzzer_input(sizeof(privkey)), sizeof(privkey));
  969. int res_33_1 = ecdsa_get_public_key33(curve, privkey, pubkey33_1);
  970. int res_33_2 = zkp_ecdsa_get_public_key33(curve, privkey, pubkey33_2);
  971. int res_65_1 = ecdsa_get_public_key65(curve, privkey, pubkey65_1);
  972. int res_65_2 = zkp_ecdsa_get_public_key65(curve, privkey, pubkey65_2);
  973. // the function pairs have different return error codes for the same input
  974. // so only fail if the one succeeds where the other does not
  975. if ((res_33_1 == 0 && res_33_2 != 0) || (res_33_1 != 0 && res_33_2 == 0)) {
  976. // function result mismatch
  977. crash();
  978. }
  979. if ((res_65_1 == 0 && res_65_2 != 0) || (res_65_1 != 0 && res_65_2 == 0)) {
  980. // function result mismatch
  981. crash();
  982. }
  983. if (res_33_1 == 0 && res_33_2 == 0 &&
  984. memcmp(&pubkey33_1, &pubkey33_2, sizeof(pubkey33_1)) != 0) {
  985. // function result data mismatch
  986. crash();
  987. }
  988. if (res_65_1 == 0 && res_65_2 == 0 &&
  989. memcmp(&pubkey65_1, &pubkey65_2, sizeof(pubkey65_1)) != 0) {
  990. // function result data mismatch
  991. crash();
  992. }
  993. return 0;
  994. }
  995. int fuzz_ecdsa_recover_pub_from_sig_functions(void) {
  996. uint8_t digest[32] = {0};
  997. uint8_t sig[64] = {0};
  998. const ecdsa_curve *curve = &secp256k1;
  999. uint8_t recid = 0;
  1000. uint8_t pubkey1[65] = {0};
  1001. uint8_t pubkey2[65] = {0};
  1002. if (fuzzer_length < sizeof(digest) + sizeof(sig) + sizeof(recid)) {
  1003. return -1;
  1004. }
  1005. memcpy(digest, fuzzer_input(sizeof(digest)), sizeof(digest));
  1006. memcpy(sig, fuzzer_input(sizeof(sig)), sizeof(sig));
  1007. memcpy(&recid, fuzzer_input(sizeof(recid)), sizeof(recid));
  1008. // conform to parameter requirements
  1009. recid = recid & 0x03;
  1010. int res1 = zkp_ecdsa_recover_pub_from_sig(curve, pubkey1, sig, digest, recid);
  1011. int res2 = ecdsa_recover_pub_from_sig(curve, pubkey2, sig, digest, recid);
  1012. if ((res1 == 0 && res2 != 0) || (res1 != 0 && res2 == 0)) {
  1013. // result mismatch
  1014. // bug result reference: https://github.com/trezor/trezor-firmware/pull/2050
  1015. crash();
  1016. }
  1017. if (res1 == 0 && res2 == 0 &&
  1018. memcmp(&pubkey1, &pubkey2, sizeof(pubkey1)) != 0) {
  1019. // pubkey result mismatch
  1020. crash();
  1021. }
  1022. return 0;
  1023. }
  1024. int fuzz_ecdsa_sig_from_der(void) {
  1025. // bug result reference: https://github.com/trezor/trezor-firmware/pull/2058
  1026. uint8_t der[72] = {0};
  1027. uint8_t out[72] = {0};
  1028. if (fuzzer_length < sizeof(der)) {
  1029. return -1;
  1030. }
  1031. memcpy(der, fuzzer_input(sizeof(der)), sizeof(der));
  1032. // null-terminate
  1033. der[sizeof(der) - 1] = 0;
  1034. size_t der_len = strlen((const char *)der);
  1035. // IDEA use different fuzzer-controlled der_len such as 1 to 73
  1036. int ret = ecdsa_sig_from_der(der, der_len, out);
  1037. (void)ret;
  1038. // IDEA check if back conversion works
  1039. return 0;
  1040. }
  1041. int fuzz_ecdsa_sig_to_der(void) {
  1042. uint8_t sig[64] = {0};
  1043. uint8_t der[72] = {0};
  1044. if (fuzzer_length < sizeof(sig)) {
  1045. return -1;
  1046. }
  1047. memcpy(sig, fuzzer_input(sizeof(sig)), sizeof(sig));
  1048. int ret = ecdsa_sig_to_der((const uint8_t *)&sig, der);
  1049. (void)ret;
  1050. // IDEA check if back conversion works
  1051. return 0;
  1052. }
  1053. int fuzz_button_sequence_to_word(void) {
  1054. uint16_t input = 0;
  1055. if (fuzzer_length < sizeof(input)) {
  1056. return -1;
  1057. }
  1058. memcpy(&input, fuzzer_input(sizeof(input)), sizeof(input));
  1059. button_sequence_to_word(input);
  1060. return 0;
  1061. }
  1062. int fuzz_xmr_add_keys(void) {
  1063. bignum256modm a, b;
  1064. ge25519 A, B;
  1065. if (fuzzer_length < sizeof(bignum256modm) * 2 + sizeof(ge25519) * 2) {
  1066. return -1;
  1067. }
  1068. memcpy(&a, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm));
  1069. memcpy(&b, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm));
  1070. memcpy(&A, fuzzer_input(sizeof(ge25519)), sizeof(ge25519));
  1071. memcpy(&B, fuzzer_input(sizeof(ge25519)), sizeof(ge25519));
  1072. ge25519 r;
  1073. xmr_add_keys2(&r, a, b, &B);
  1074. check_msan(&r, sizeof(r));
  1075. xmr_add_keys2_vartime(&r, a, b, &B);
  1076. check_msan(&r, sizeof(r));
  1077. xmr_add_keys3(&r, a, &A, b, &B);
  1078. check_msan(&r, sizeof(r));
  1079. xmr_add_keys3_vartime(&r, a, &A, b, &B);
  1080. check_msan(&r, sizeof(r));
  1081. return 0;
  1082. }
  1083. int fuzz_ecdh_multiply(void) {
  1084. uint8_t priv_key[32];
  1085. // 33 or 65 bytes content
  1086. uint8_t pub_key[65];
  1087. uint8_t decider;
  1088. if (fuzzer_length < sizeof(priv_key) + sizeof(pub_key) + sizeof(decider)) {
  1089. return -1;
  1090. }
  1091. memcpy(&priv_key, fuzzer_input(sizeof(priv_key)), sizeof(priv_key));
  1092. memcpy(&pub_key, fuzzer_input(sizeof(pub_key)), sizeof(pub_key));
  1093. memcpy(&decider, fuzzer_input(sizeof(decider)), sizeof(decider));
  1094. uint8_t session_key[65] = {0};
  1095. int res1 = 0;
  1096. // TODO evaluate crash with &curve == NULL, documentation / convention issue?
  1097. const ecdsa_curve *curve2;
  1098. // ecdh_multiply() is only called with secp256k1 and nist256p1 curve from
  1099. // modtrezorcrypto code theoretically other curve parameters are also possible
  1100. if ((decider & 1) == 0) {
  1101. curve2 = &nist256p1;
  1102. } else {
  1103. curve2 = &secp256k1;
  1104. }
  1105. res1 = ecdh_multiply(curve2, (uint8_t *)&priv_key, (uint8_t *)&pub_key,
  1106. (uint8_t *)&session_key);
  1107. check_msan(&session_key, sizeof(session_key));
  1108. if (res1 != 0) {
  1109. // failure case
  1110. }
  1111. return 0;
  1112. }
  1113. int fuzz_segwit_addr_encode(void) {
  1114. // the current firmware code only uses witver = 0 and witver = 1
  1115. // we give more flexibility, but do not allow the full int range
  1116. uint8_t chosen_witver = 0;
  1117. // restrict fuzzer variations to lengths of 0 to 255
  1118. uint8_t chosen_witprog_len = 0;
  1119. // in typical use, hrp is a bech32 prefix of 2 to 4 chars
  1120. // TODO make this dynamic, investigate lowercase requirements
  1121. // see also https://github.com/sipa/bech32/issues/38
  1122. char *hrp = "bc";
  1123. if (fuzzer_length < sizeof(chosen_witver) + sizeof(chosen_witprog_len)) {
  1124. return -1;
  1125. }
  1126. memcpy(&chosen_witver, fuzzer_input(sizeof(chosen_witver)),
  1127. sizeof(chosen_witver));
  1128. memcpy(&chosen_witprog_len, fuzzer_input(sizeof(chosen_witprog_len)),
  1129. sizeof(chosen_witprog_len));
  1130. if (chosen_witprog_len > fuzzer_length) {
  1131. return -1;
  1132. }
  1133. char output_address[MAX_ADDR_SIZE] = {0};
  1134. uint8_t *witprog = malloc(chosen_witprog_len);
  1135. RETURN_IF_NULL(witprog);
  1136. memcpy(witprog, fuzzer_input(chosen_witprog_len), chosen_witprog_len);
  1137. int ret = segwit_addr_encode(output_address, hrp, chosen_witver, witprog,
  1138. chosen_witprog_len);
  1139. // IDEA act depending on ret
  1140. (void)ret;
  1141. free(witprog);
  1142. return 0;
  1143. }
  1144. // int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len,
  1145. // const char* hrp, const char* addr) {
  1146. int fuzz_segwit_addr_decode(void) {
  1147. int decoded_witver = 0;
  1148. size_t decoded_witprog_len = 0;
  1149. // TODO
  1150. uint8_t addr_raw[MAX_ADDR_RAW_SIZE] = {0};
  1151. uint8_t chosen_addr_len = 0;
  1152. if (fuzzer_length < sizeof(chosen_addr_len)) {
  1153. return -1;
  1154. }
  1155. memcpy(&chosen_addr_len, fuzzer_input(sizeof(chosen_addr_len)),
  1156. sizeof(chosen_addr_len));
  1157. if (chosen_addr_len > fuzzer_length) {
  1158. return -1;
  1159. }
  1160. char *addr = malloc(chosen_addr_len + 1);
  1161. RETURN_IF_NULL(addr);
  1162. memcpy(addr, fuzzer_input(chosen_addr_len), chosen_addr_len);
  1163. // null termination
  1164. addr[chosen_addr_len] = 0;
  1165. // TODO see comments in fuzz_segwit_addr_encode()
  1166. char *hrp = "bc";
  1167. int ret = segwit_addr_decode(&decoded_witver, addr_raw, &decoded_witprog_len,
  1168. hrp, addr);
  1169. // IDEA act depending on ret
  1170. (void)ret;
  1171. free(addr);
  1172. return 0;
  1173. }
  1174. /* fuzzer main function */
  1175. #define META_HEADER_SIZE 3
  1176. int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  1177. // reject input that is too short
  1178. if (size < META_HEADER_SIZE) {
  1179. return -1;
  1180. }
  1181. fuzzer_reset_state();
  1182. // this controls up to 256 different test cases
  1183. uint8_t target_decision = data[0];
  1184. // data[1] is reserved for explicit sub decisions
  1185. // uint8_t target_sub_decision = data[1];
  1186. // data[2] is reserved for future use
  1187. // assign the fuzzer payload data for the target functions
  1188. fuzzer_ptr = data + META_HEADER_SIZE;
  1189. fuzzer_length = size - META_HEADER_SIZE;
  1190. // if active: reject all other inputs that are not the selected target
  1191. // this is helpful for directing the fuzzing focus on a specific case
  1192. #ifdef FUZZER_EXCLUSIVE_TARGET
  1193. if (target_decision != FUZZER_EXCLUSIVE_TARGET) {
  1194. return -1;
  1195. }
  1196. #endif
  1197. // recent libFuzzer implementations support marking inputs as non-interesting
  1198. // via return -1; instead of the regular return 0;
  1199. // see
  1200. // https://github.com/llvm/llvm-project/commit/92fb310151d2b1e349695fc0f1c5d5d50afb3b52
  1201. int target_result = 0;
  1202. // TODO reorder and regroup target functions
  1203. switch (target_decision) {
  1204. case 0:
  1205. target_result = fuzz_bn_format();
  1206. break;
  1207. case 1:
  1208. target_result = fuzz_base32_decode();
  1209. break;
  1210. case 2:
  1211. target_result = fuzz_base32_encode();
  1212. break;
  1213. case 3:
  1214. target_result = fuzz_base58_encode_check();
  1215. break;
  1216. case 4:
  1217. target_result = fuzz_base58_decode_check();
  1218. break;
  1219. case 5:
  1220. target_result = fuzz_xmr_base58_addr_decode_check();
  1221. break;
  1222. case 6:
  1223. target_result = fuzz_xmr_base58_addr_encode_check();
  1224. break;
  1225. case 7:
  1226. target_result = fuzz_xmr_serialize_varint();
  1227. break;
  1228. case 8:
  1229. target_result = fuzz_nem_validate_address();
  1230. break;
  1231. case 9:
  1232. target_result = fuzz_nem_get_address();
  1233. break;
  1234. case 10:
  1235. target_result = fuzz_xmr_get_subaddress_secret_key();
  1236. break;
  1237. case 11:
  1238. target_result = fuzz_xmr_derive_private_key();
  1239. break;
  1240. case 12:
  1241. target_result = fuzz_xmr_derive_public_key();
  1242. break;
  1243. case 13:
  1244. target_result = fuzz_shamir_interpolate();
  1245. break;
  1246. case 14:
  1247. #ifdef FUZZ_ALLOW_SLOW
  1248. zkp_initialize_context_or_crash();
  1249. // slow through expensive bignum operations
  1250. target_result = fuzz_ecdsa_verify_digest_functions();
  1251. #endif
  1252. break;
  1253. case 15:
  1254. target_result = fuzz_word_index();
  1255. break;
  1256. case 16:
  1257. target_result = fuzz_slip39_word_completion_mask();
  1258. break;
  1259. case 17:
  1260. target_result = fuzz_mnemonic_check();
  1261. break;
  1262. case 18:
  1263. #ifdef FUZZ_ALLOW_SLOW
  1264. target_result = fuzz_aes();
  1265. #endif
  1266. break;
  1267. case 22:
  1268. target_result = fuzz_chacha_drbg();
  1269. break;
  1270. case 23:
  1271. #ifdef FUZZ_ALLOW_SLOW
  1272. zkp_initialize_context_or_crash();
  1273. // slow through expensive bignum operations
  1274. target_result = fuzz_ecdsa_sign_digest_functions();
  1275. #endif
  1276. break;
  1277. case 24:
  1278. target_result = fuzz_ed25519_sign_verify();
  1279. break;
  1280. case 25:
  1281. target_result = fuzz_mnemonic_from_data();
  1282. break;
  1283. case 26:
  1284. target_result = fuzz_mnemonic_to_seed();
  1285. break;
  1286. case 27:
  1287. target_result = fuzz_button_sequence_to_word();
  1288. break;
  1289. case 28:
  1290. target_result = fuzz_segwit_addr_encode();
  1291. break;
  1292. case 29:
  1293. target_result = fuzz_segwit_addr_decode();
  1294. break;
  1295. case 30:
  1296. target_result = fuzz_ethereum_address_checksum();
  1297. break;
  1298. case 41:
  1299. zkp_initialize_context_or_crash();
  1300. target_result = fuzz_zkp_bip340_sign_digest();
  1301. break;
  1302. case 42:
  1303. zkp_initialize_context_or_crash();
  1304. target_result = fuzz_zkp_bip340_verify_digest();
  1305. break;
  1306. case 43:
  1307. zkp_initialize_context_or_crash();
  1308. target_result = fuzz_zkp_bip340_tweak_keys();
  1309. break;
  1310. case 50:
  1311. zkp_initialize_context_or_crash();
  1312. target_result = fuzz_ecdsa_get_public_key_functions();
  1313. break;
  1314. case 51:
  1315. zkp_initialize_context_or_crash();
  1316. target_result = fuzz_ecdsa_recover_pub_from_sig_functions();
  1317. break;
  1318. case 52:
  1319. target_result = fuzz_ecdsa_sig_from_der();
  1320. break;
  1321. case 53:
  1322. target_result = fuzz_ecdsa_sig_to_der();
  1323. break;
  1324. case 60:
  1325. target_result = fuzz_xmr_base58_encode();
  1326. break;
  1327. case 61:
  1328. target_result = fuzz_xmr_base58_decode();
  1329. break;
  1330. case 63:
  1331. target_result = fuzz_xmr_add_keys();
  1332. break;
  1333. case 64:
  1334. target_result = fuzz_ecdh_multiply();
  1335. break;
  1336. default:
  1337. // mark as uninteresting input
  1338. return -1;
  1339. break;
  1340. }
  1341. return target_result;
  1342. }