testcrypt.c 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762
  1. /*
  2. * testcrypt: a standalone test program that provides direct access to
  3. * PuTTY's cryptography and mp_int code.
  4. */
  5. /*
  6. * This program speaks a line-oriented protocol on standard input and
  7. * standard output. It's a half-duplex protocol: it expects to read
  8. * one line of command, and then produce a fixed amount of output
  9. * (namely a line containing a decimal integer, followed by that many
  10. * lines each containing one return value).
  11. *
  12. * The protocol is human-readable enough to make it debuggable, but
  13. * verbose enough that you probably wouldn't want to speak it by hand
  14. * at any great length. The Python program test/testcrypt.py wraps it
  15. * to give a more useful user-facing API, by invoking this binary as a
  16. * subprocess.
  17. *
  18. * (I decided that was a better idea than making this program an
  19. * actual Python module, partly because you can rewrap the same binary
  20. * in another scripting language if you prefer, but mostly because
  21. * it's easy to attach a debugger to testcrypt or to run it under
  22. * sanitisers or valgrind or what have you.)
  23. */
  24. #include <assert.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <errno.h>
  29. #include "defs.h"
  30. #include "ssh.h"
  31. #include "sshkeygen.h"
  32. #include "misc.h"
  33. #include "mpint.h"
  34. #include "crypto/ecc.h"
  35. #include "crypto/ntru.h"
  36. #include "crypto/mlkem.h"
  37. #include "proxy/cproxy.h"
  38. static NORETURN PRINTF_LIKE(1, 2) void fatal_error(const char *p, ...)
  39. {
  40. va_list ap;
  41. fprintf(stderr, "testcrypt: ");
  42. va_start(ap, p);
  43. vfprintf(stderr, p, ap);
  44. va_end(ap);
  45. fputc('\n', stderr);
  46. exit(1);
  47. }
  48. void out_of_memory(void) { fatal_error("out of memory"); }
  49. static bool old_keyfile_warning_given;
  50. void old_keyfile_warning(void) { old_keyfile_warning_given = true; }
  51. static bufchain random_data_queue;
  52. static prng *test_prng;
  53. void random_read(void *buf, size_t size)
  54. {
  55. if (test_prng) {
  56. prng_read(test_prng, buf, size);
  57. } else {
  58. if (!bufchain_try_fetch_consume(&random_data_queue, buf, size))
  59. fatal_error("No random data in queue");
  60. }
  61. }
  62. uint64_t prng_reseed_time_ms(void)
  63. {
  64. static uint64_t previous_time = 0;
  65. return previous_time += 200;
  66. }
  67. #define VALUE_TYPES(X) \
  68. X(string, strbuf *, strbuf_free(v)) \
  69. X(mpint, mp_int *, mp_free(v)) \
  70. X(modsqrt, ModsqrtContext *, modsqrt_free(v)) \
  71. X(monty, MontyContext *, monty_free(v)) \
  72. X(wcurve, WeierstrassCurve *, ecc_weierstrass_curve_free(v)) \
  73. X(wpoint, WeierstrassPoint *, ecc_weierstrass_point_free(v)) \
  74. X(mcurve, MontgomeryCurve *, ecc_montgomery_curve_free(v)) \
  75. X(mpoint, MontgomeryPoint *, ecc_montgomery_point_free(v)) \
  76. X(ecurve, EdwardsCurve *, ecc_edwards_curve_free(v)) \
  77. X(epoint, EdwardsPoint *, ecc_edwards_point_free(v)) \
  78. X(hash, ssh_hash *, ssh_hash_free(v)) \
  79. X(key, ssh_key *, ssh_key_free(v)) \
  80. X(cipher, ssh_cipher *, ssh_cipher_free(v)) \
  81. X(mac, ssh2_mac *, ssh2_mac_free(v)) \
  82. X(dh, dh_ctx *, dh_cleanup(v)) \
  83. X(ecdh, ecdh_key *, ecdh_key_free(v)) \
  84. X(rsakex, RSAKey *, ssh_rsakex_freekey(v)) \
  85. X(rsa, RSAKey *, rsa_free(v)) \
  86. X(prng, prng *, prng_free(v)) \
  87. X(keycomponents, key_components *, key_components_free(v)) \
  88. X(pcs, PrimeCandidateSource *, pcs_free(v)) \
  89. X(pgc, PrimeGenerationContext *, primegen_free_context(v)) \
  90. X(pockle, Pockle *, pockle_free(v)) \
  91. X(millerrabin, MillerRabin *, miller_rabin_free(v)) \
  92. X(ntrukeypair, NTRUKeyPair *, ntru_keypair_free(v)) \
  93. X(ntruencodeschedule, NTRUEncodeSchedule *, ntru_encode_schedule_free(v)) \
  94. X(shakexof, ShakeXOF *, shake_xof_free(v)) \
  95. /* end of list */
  96. typedef struct Value Value;
  97. enum ValueType {
  98. #define VALTYPE_ENUM(n,t,f) VT_##n,
  99. VALUE_TYPES(VALTYPE_ENUM)
  100. #undef VALTYPE_ENUM
  101. };
  102. typedef enum ValueType ValueType;
  103. static const char *const type_names[] = {
  104. #define VALTYPE_NAME(n,t,f) #n,
  105. VALUE_TYPES(VALTYPE_NAME)
  106. #undef VALTYPE_NAME
  107. };
  108. #define VALTYPE_TYPEDEF(n,t,f) \
  109. typedef t TD_val_##n; \
  110. typedef t *TD_out_val_##n;
  111. VALUE_TYPES(VALTYPE_TYPEDEF)
  112. #undef VALTYPE_TYPEDEF
  113. struct Value {
  114. /*
  115. * Protocol identifier assigned to this value when it was created.
  116. * Lives in the same malloced block as this Value object itself.
  117. */
  118. ptrlen id;
  119. /*
  120. * Type of the value.
  121. */
  122. ValueType type;
  123. /*
  124. * Union of all the things it could hold.
  125. */
  126. union {
  127. #define VALTYPE_UNION(n,t,f) t vu_##n;
  128. VALUE_TYPES(VALTYPE_UNION)
  129. #undef VALTYPE_UNION
  130. char *bare_string;
  131. };
  132. };
  133. static int valuecmp(void *av, void *bv)
  134. {
  135. Value *a = (Value *)av, *b = (Value *)bv;
  136. return ptrlen_strcmp(a->id, b->id);
  137. }
  138. static int valuefind(void *av, void *bv)
  139. {
  140. ptrlen *a = (ptrlen *)av;
  141. Value *b = (Value *)bv;
  142. return ptrlen_strcmp(*a, b->id);
  143. }
  144. static tree234 *values;
  145. static Value *value_new(ValueType vt)
  146. {
  147. static uint64_t next_index = 0;
  148. char *name = dupprintf("%s%"PRIu64, type_names[vt], next_index++);
  149. size_t namelen = strlen(name);
  150. Value *val = snew_plus(Value, namelen+1);
  151. memcpy(snew_plus_get_aux(val), name, namelen+1);
  152. val->id.ptr = snew_plus_get_aux(val);
  153. val->id.len = namelen;
  154. val->type = vt;
  155. Value *added = add234(values, val);
  156. assert(added == val);
  157. sfree(name);
  158. return val;
  159. }
  160. #define VALTYPE_RETURNFN(n,t,f) \
  161. void return_val_##n(strbuf *out, t v) { \
  162. Value *val = value_new(VT_##n); \
  163. val->vu_##n = v; \
  164. put_datapl(out, val->id); \
  165. put_byte(out, '\n'); \
  166. }
  167. VALUE_TYPES(VALTYPE_RETURNFN)
  168. #undef VALTYPE_RETURNFN
  169. static ptrlen get_word(BinarySource *in)
  170. {
  171. ptrlen toret;
  172. toret.ptr = get_ptr(in);
  173. toret.len = 0;
  174. while (get_avail(in) && get_byte(in) != ' ')
  175. toret.len++;
  176. return toret;
  177. }
  178. typedef uintmax_t TD_uint;
  179. typedef bool TD_boolean;
  180. typedef ptrlen TD_val_string_ptrlen;
  181. typedef char *TD_val_string_asciz;
  182. typedef BinarySource *TD_val_string_binarysource;
  183. typedef unsigned *TD_out_uint;
  184. typedef BinarySink *TD_out_val_string_binarysink;
  185. typedef const char *TD_opt_val_string_asciz;
  186. typedef char **TD_out_val_string_asciz;
  187. typedef char **TD_out_opt_val_string_asciz;
  188. typedef const char **TD_out_opt_val_string_asciz_const;
  189. typedef const ssh_hashalg *TD_hashalg;
  190. typedef const ssh2_macalg *TD_macalg;
  191. typedef const ssh_keyalg *TD_keyalg;
  192. typedef const ssh_cipheralg *TD_cipheralg;
  193. typedef const ssh_kex *TD_dh_group;
  194. typedef const ssh_kex *TD_ecdh_alg;
  195. typedef RsaSsh1Order TD_rsaorder;
  196. typedef key_components *TD_keycomponents;
  197. typedef const PrimeGenerationPolicy *TD_primegenpolicy;
  198. typedef struct mpint_list TD_mpint_list;
  199. typedef struct int16_list *TD_int16_list;
  200. typedef PockleStatus TD_pocklestatus;
  201. typedef struct mr_result TD_mr_result;
  202. typedef Argon2Flavour TD_argon2flavour;
  203. typedef FingerprintType TD_fptype;
  204. typedef HttpDigestHash TD_httpdigesthash;
  205. typedef const mlkem_params *TD_mlkem_params;
  206. #define BEGIN_ENUM_TYPE(name) \
  207. static bool enum_translate_##name(ptrlen valname, TD_##name *out) { \
  208. static const struct { \
  209. const char *key; \
  210. TD_##name value; \
  211. } mapping[] = {
  212. #define ENUM_VALUE(name, value) {name, value},
  213. #define END_ENUM_TYPE(name) \
  214. }; \
  215. for (size_t i = 0; i < lenof(mapping); i++) \
  216. if (ptrlen_eq_string(valname, mapping[i].key)) { \
  217. if (out) \
  218. *out = mapping[i].value; \
  219. return true; \
  220. } \
  221. return false; \
  222. } \
  223. \
  224. static TD_##name get_##name(BinarySource *in) { \
  225. ptrlen valname = get_word(in); \
  226. TD_##name out; \
  227. if (enum_translate_##name(valname, &out)) \
  228. return out; \
  229. else \
  230. fatal_error("%s '%.*s': not found", \
  231. #name, PTRLEN_PRINTF(valname)); \
  232. }
  233. #include "testcrypt-enum.h"
  234. #undef BEGIN_ENUM_TYPE
  235. #undef ENUM_VALUE
  236. #undef END_ENUM_TYPE
  237. static uintmax_t get_uint(BinarySource *in)
  238. {
  239. ptrlen word = get_word(in);
  240. char *string = mkstr(word);
  241. uintmax_t toret = strtoumax(string, NULL, 0);
  242. sfree(string);
  243. return toret;
  244. }
  245. static bool get_boolean(BinarySource *in)
  246. {
  247. return ptrlen_eq_string(get_word(in), "true");
  248. }
  249. static Value *lookup_value(ptrlen word)
  250. {
  251. Value *val = find234(values, &word, valuefind);
  252. if (!val)
  253. fatal_error("id '%.*s': not found", PTRLEN_PRINTF(word));
  254. return val;
  255. }
  256. static Value *get_value(BinarySource *in)
  257. {
  258. return lookup_value(get_word(in));
  259. }
  260. typedef void (*finaliser_fn_t)(strbuf *out, void *ctx);
  261. struct finaliser {
  262. finaliser_fn_t fn;
  263. void *ctx;
  264. };
  265. static struct finaliser *finalisers;
  266. static size_t nfinalisers, finalisersize;
  267. static void add_finaliser(finaliser_fn_t fn, void *ctx)
  268. {
  269. sgrowarray(finalisers, finalisersize, nfinalisers);
  270. finalisers[nfinalisers].fn = fn;
  271. finalisers[nfinalisers].ctx = ctx;
  272. nfinalisers++;
  273. }
  274. static void run_finalisers(strbuf *out)
  275. {
  276. for (size_t i = 0; i < nfinalisers; i++)
  277. finalisers[i].fn(out, finalisers[i].ctx);
  278. nfinalisers = 0;
  279. }
  280. static void finaliser_return_value(strbuf *out, void *ctx)
  281. {
  282. Value *val = (Value *)ctx;
  283. put_datapl(out, val->id);
  284. put_byte(out, '\n');
  285. }
  286. static void finaliser_sfree(strbuf *out, void *ctx)
  287. {
  288. sfree(ctx);
  289. }
  290. #define VALTYPE_GETFN(n,t,f) \
  291. static Value *unwrap_value_##n(Value *val) { \
  292. ValueType expected = VT_##n; \
  293. if (expected != val->type) \
  294. fatal_error("id '%.*s': expected %s, got %s", \
  295. PTRLEN_PRINTF(val->id), \
  296. type_names[expected], type_names[val->type]); \
  297. return val; \
  298. } \
  299. static Value *get_value_##n(BinarySource *in) { \
  300. return unwrap_value_##n(get_value(in)); \
  301. } \
  302. static t get_val_##n(BinarySource *in) { \
  303. return get_value_##n(in)->vu_##n; \
  304. }
  305. VALUE_TYPES(VALTYPE_GETFN)
  306. #undef VALTYPE_GETFN
  307. static ptrlen get_val_string_ptrlen(BinarySource *in)
  308. {
  309. return ptrlen_from_strbuf(get_val_string(in));
  310. }
  311. static char *get_val_string_asciz(BinarySource *in)
  312. {
  313. return get_val_string(in)->s;
  314. }
  315. static strbuf *get_opt_val_string(BinarySource *in);
  316. static char *get_opt_val_string_asciz(BinarySource *in)
  317. {
  318. strbuf *sb = get_opt_val_string(in);
  319. return sb ? sb->s : NULL;
  320. }
  321. static mp_int **get_out_val_mpint(BinarySource *in)
  322. {
  323. Value *val = value_new(VT_mpint);
  324. add_finaliser(finaliser_return_value, val);
  325. return &val->vu_mpint;
  326. }
  327. struct mpint_list {
  328. size_t n;
  329. mp_int **integers;
  330. };
  331. static struct mpint_list get_mpint_list(BinarySource *in)
  332. {
  333. size_t n = get_uint(in);
  334. struct mpint_list mpl;
  335. mpl.n = n;
  336. mpl.integers = snewn(n, mp_int *);
  337. for (size_t i = 0; i < n; i++)
  338. mpl.integers[i] = get_val_mpint(in);
  339. add_finaliser(finaliser_sfree, mpl.integers);
  340. return mpl;
  341. }
  342. typedef struct int16_list {
  343. size_t n;
  344. uint16_t *integers;
  345. } int16_list;
  346. static void finaliser_int16_list_free(strbuf *out, void *vlist)
  347. {
  348. int16_list *list = (int16_list *)vlist;
  349. sfree(list->integers);
  350. sfree(list);
  351. }
  352. static int16_list *make_int16_list(size_t n)
  353. {
  354. int16_list *list = snew(int16_list);
  355. list->n = n;
  356. list->integers = snewn(n, uint16_t);
  357. add_finaliser(finaliser_int16_list_free, list);
  358. return list;
  359. }
  360. static int16_list *get_int16_list(BinarySource *in)
  361. {
  362. size_t n = get_uint(in);
  363. int16_list *list = make_int16_list(n);
  364. for (size_t i = 0; i < n; i++)
  365. list->integers[i] = get_uint(in);
  366. return list;
  367. }
  368. static void return_int16_list(strbuf *out, int16_list *list)
  369. {
  370. for (size_t i = 0; i < list->n; i++) {
  371. if (i > 0)
  372. put_byte(out, ',');
  373. put_fmt(out, "%d", (int)(int16_t)list->integers[i]);
  374. }
  375. put_byte(out, '\n');
  376. }
  377. static void finaliser_return_uint(strbuf *out, void *ctx)
  378. {
  379. unsigned *uval = (unsigned *)ctx;
  380. put_fmt(out, "%u\n", *uval);
  381. sfree(uval);
  382. }
  383. static unsigned *get_out_uint(BinarySource *in)
  384. {
  385. unsigned *uval = snew(unsigned);
  386. add_finaliser(finaliser_return_uint, uval);
  387. return uval;
  388. }
  389. static strbuf **get_out_val_string(BinarySource *in)
  390. {
  391. Value *val = value_new(VT_string);
  392. val->vu_string = NULL;
  393. add_finaliser(finaliser_return_value, val);
  394. return &val->vu_string;
  395. }
  396. static BinarySink *get_out_val_string_binarysink(BinarySource *in)
  397. {
  398. strbuf *sb = strbuf_new();
  399. *get_out_val_string(in) = sb;
  400. return BinarySink_UPCAST(sb);
  401. }
  402. static void return_val_string_asciz_const(strbuf *out, const char *s);
  403. static void return_val_string_asciz(strbuf *out, char *s);
  404. static void finaliser_return_opt_string_asciz(strbuf *out, void *ctx)
  405. {
  406. char **valp = (char **)ctx;
  407. char *val = *valp;
  408. sfree(valp);
  409. if (!val)
  410. put_fmt(out, "NULL\n");
  411. else
  412. return_val_string_asciz(out, val);
  413. }
  414. static char **get_out_opt_val_string_asciz(BinarySource *in)
  415. {
  416. char **valp = snew(char *);
  417. *valp = NULL;
  418. add_finaliser(finaliser_return_opt_string_asciz, valp);
  419. return valp;
  420. }
  421. static void finaliser_return_opt_string_asciz_const(strbuf *out, void *ctx)
  422. {
  423. const char **valp = (const char **)ctx;
  424. const char *val = *valp;
  425. sfree(valp);
  426. if (!val)
  427. put_fmt(out, "NULL\n");
  428. else
  429. return_val_string_asciz_const(out, val);
  430. }
  431. static const char **get_out_opt_val_string_asciz_const(BinarySource *in)
  432. {
  433. const char **valp = snew(const char *);
  434. *valp = NULL;
  435. add_finaliser(finaliser_return_opt_string_asciz_const, valp);
  436. return valp;
  437. }
  438. static BinarySource *get_val_string_binarysource(BinarySource *in)
  439. {
  440. strbuf *sb = get_val_string(in);
  441. BinarySource *src = snew(BinarySource);
  442. BinarySource_BARE_INIT(src, sb->u, sb->len);
  443. add_finaliser(finaliser_sfree, src);
  444. return src;
  445. }
  446. #define GET_CONSUMED_FN(type) \
  447. typedef TD_val_##type TD_consumed_val_##type; \
  448. static TD_val_##type get_consumed_val_##type(BinarySource *in) \
  449. { \
  450. Value *val = get_value_##type(in); \
  451. TD_val_##type toret = val->vu_##type; \
  452. del234(values, val); \
  453. sfree(val); \
  454. return toret; \
  455. }
  456. GET_CONSUMED_FN(hash)
  457. GET_CONSUMED_FN(pcs)
  458. static void return_int(strbuf *out, intmax_t u)
  459. {
  460. put_fmt(out, "%"PRIdMAX"\n", u);
  461. }
  462. static void return_uint(strbuf *out, uintmax_t u)
  463. {
  464. put_fmt(out, "0x%"PRIXMAX"\n", u);
  465. }
  466. static void return_boolean(strbuf *out, bool b)
  467. {
  468. put_fmt(out, "%s\n", b ? "true" : "false");
  469. }
  470. static void return_pocklestatus(strbuf *out, PockleStatus status)
  471. {
  472. switch (status) {
  473. default:
  474. put_fmt(out, "POCKLE_BAD_STATUS_VALUE\n");
  475. break;
  476. #define STATUS_CASE(id) \
  477. case id: \
  478. put_fmt(out, "%s\n", #id); \
  479. break;
  480. POCKLE_STATUSES(STATUS_CASE);
  481. #undef STATUS_CASE
  482. }
  483. }
  484. static void return_mr_result(strbuf *out, struct mr_result result)
  485. {
  486. if (!result.passed)
  487. put_fmt(out, "failed\n");
  488. else if (!result.potential_primitive_root)
  489. put_fmt(out, "passed\n");
  490. else
  491. put_fmt(out, "passed+ppr\n");
  492. }
  493. static void return_val_string_asciz_const(strbuf *out, const char *s)
  494. {
  495. strbuf *sb = strbuf_new();
  496. put_data(sb, s, strlen(s));
  497. return_val_string(out, sb);
  498. }
  499. static void return_val_string_asciz(strbuf *out, char *s)
  500. {
  501. return_val_string_asciz_const(out, s);
  502. sfree(s);
  503. }
  504. #define NULLABLE_RETURN_WRAPPER(type_name, c_type) \
  505. static void return_opt_##type_name(strbuf *out, c_type ptr) \
  506. { \
  507. if (!ptr) \
  508. put_fmt(out, "NULL\n"); \
  509. else \
  510. return_##type_name(out, ptr); \
  511. }
  512. NULLABLE_RETURN_WRAPPER(val_string, strbuf *)
  513. NULLABLE_RETURN_WRAPPER(val_string_asciz, char *)
  514. NULLABLE_RETURN_WRAPPER(val_string_asciz_const, const char *)
  515. NULLABLE_RETURN_WRAPPER(val_cipher, ssh_cipher *)
  516. NULLABLE_RETURN_WRAPPER(val_mac, ssh2_mac *)
  517. NULLABLE_RETURN_WRAPPER(val_hash, ssh_hash *)
  518. NULLABLE_RETURN_WRAPPER(val_key, ssh_key *)
  519. NULLABLE_RETURN_WRAPPER(val_mpint, mp_int *)
  520. NULLABLE_RETURN_WRAPPER(int16_list, int16_list *)
  521. static void handle_hello(BinarySource *in, strbuf *out)
  522. {
  523. put_fmt(out, "hello, world\n");
  524. }
  525. static void rsa_free(RSAKey *rsa)
  526. {
  527. freersakey(rsa);
  528. sfree(rsa);
  529. }
  530. static void free_value(Value *val)
  531. {
  532. switch (val->type) {
  533. #define VALTYPE_FREE(n,t,f) case VT_##n: { t v = val->vu_##n; (f); break; }
  534. VALUE_TYPES(VALTYPE_FREE)
  535. #undef VALTYPE_FREE
  536. }
  537. sfree(val);
  538. }
  539. static void handle_free(BinarySource *in, strbuf *out)
  540. {
  541. Value *val = get_value(in);
  542. del234(values, val);
  543. free_value(val);
  544. }
  545. static void handle_newstring(BinarySource *in, strbuf *out)
  546. {
  547. strbuf *sb = strbuf_new();
  548. while (get_avail(in)) {
  549. char c = get_byte(in);
  550. if (c == '%') {
  551. char hex[3];
  552. hex[0] = get_byte(in);
  553. if (hex[0] != '%') {
  554. hex[1] = get_byte(in);
  555. hex[2] = '\0';
  556. c = strtoul(hex, NULL, 16);
  557. }
  558. }
  559. put_byte(sb, c);
  560. }
  561. return_val_string(out, sb);
  562. }
  563. static void handle_getstring(BinarySource *in, strbuf *out)
  564. {
  565. strbuf *sb = get_val_string(in);
  566. for (size_t i = 0; i < sb->len; i++) {
  567. char c = sb->s[i];
  568. if (c > ' ' && c < 0x7F && c != '%') {
  569. put_byte(out, c);
  570. } else {
  571. put_fmt(out, "%%%02X", 0xFFU & (unsigned)c);
  572. }
  573. }
  574. put_byte(out, '\n');
  575. }
  576. static void handle_mp_literal(BinarySource *in, strbuf *out)
  577. {
  578. ptrlen pl = get_word(in);
  579. char *str = mkstr(pl);
  580. mp_int *mp = mp__from_string_literal(str);
  581. sfree(str);
  582. return_val_mpint(out, mp);
  583. }
  584. static void handle_mp_dump(BinarySource *in, strbuf *out)
  585. {
  586. mp_int *mp = get_val_mpint(in);
  587. for (size_t i = mp_max_bytes(mp); i-- > 0 ;)
  588. put_fmt(out, "%02X", mp_get_byte(mp, i));
  589. put_byte(out, '\n');
  590. }
  591. static void handle_checkenum(BinarySource *in, strbuf *out)
  592. {
  593. ptrlen type = get_word(in);
  594. ptrlen value = get_word(in);
  595. bool ok = false;
  596. #define BEGIN_ENUM_TYPE(name) \
  597. if (ptrlen_eq_string(type, #name)) \
  598. ok = enum_translate_##name(value, NULL);
  599. #define ENUM_VALUE(name, value)
  600. #define END_ENUM_TYPE(name)
  601. #include "testcrypt-enum.h"
  602. #undef BEGIN_ENUM_TYPE
  603. #undef ENUM_VALUE
  604. #undef END_ENUM_TYPE
  605. put_dataz(out, ok ? "ok\n" : "bad\n");
  606. }
  607. static void random_queue(ptrlen pl)
  608. {
  609. bufchain_add(&random_data_queue, pl.ptr, pl.len);
  610. }
  611. static size_t random_queue_len(void)
  612. {
  613. return bufchain_size(&random_data_queue);
  614. }
  615. static void random_clear(void)
  616. {
  617. if (test_prng) {
  618. prng_free(test_prng);
  619. test_prng = NULL;
  620. }
  621. bufchain_clear(&random_data_queue);
  622. }
  623. static void random_make_prng(const ssh_hashalg *hashalg, ptrlen seed)
  624. {
  625. random_clear();
  626. test_prng = prng_new(hashalg);
  627. prng_seed_begin(test_prng);
  628. put_datapl(test_prng, seed);
  629. prng_seed_finish(test_prng);
  630. }
  631. mp_int *monty_identity_wrapper(MontyContext *mc)
  632. {
  633. return mp_copy(monty_identity(mc));
  634. }
  635. mp_int *monty_modulus_wrapper(MontyContext *mc)
  636. {
  637. return mp_copy(monty_modulus(mc));
  638. }
  639. strbuf *ssh_hash_digest_wrapper(ssh_hash *h)
  640. {
  641. strbuf *sb = strbuf_new();
  642. void *p = strbuf_append(sb, ssh_hash_alg(h)->hlen);
  643. ssh_hash_digest(h, p);
  644. return sb;
  645. }
  646. strbuf *ssh_hash_final_wrapper(ssh_hash *h)
  647. {
  648. strbuf *sb = strbuf_new();
  649. void *p = strbuf_append(sb, ssh_hash_alg(h)->hlen);
  650. ssh_hash_final(h, p);
  651. return sb;
  652. }
  653. strbuf *shake_xof_read_wrapper(ShakeXOF *sx, TD_uint size)
  654. {
  655. strbuf *sb = strbuf_new();
  656. void *p = strbuf_append(sb, size);
  657. shake_xof_read(sx, p, size);
  658. return sb;
  659. }
  660. void ssh_cipher_setiv_wrapper(ssh_cipher *c, ptrlen iv)
  661. {
  662. if (iv.len != ssh_cipher_alg(c)->blksize)
  663. fatal_error("ssh_cipher_setiv: needs exactly %d bytes",
  664. ssh_cipher_alg(c)->blksize);
  665. ssh_cipher_setiv(c, iv.ptr);
  666. }
  667. void ssh_cipher_setkey_wrapper(ssh_cipher *c, ptrlen key)
  668. {
  669. if (key.len != ssh_cipher_alg(c)->padded_keybytes)
  670. fatal_error("ssh_cipher_setkey: needs exactly %d bytes",
  671. ssh_cipher_alg(c)->padded_keybytes);
  672. ssh_cipher_setkey(c, key.ptr);
  673. }
  674. strbuf *ssh_cipher_encrypt_wrapper(ssh_cipher *c, ptrlen input)
  675. {
  676. if (input.len % ssh_cipher_alg(c)->blksize)
  677. fatal_error("ssh_cipher_encrypt: needs a multiple of %d bytes",
  678. ssh_cipher_alg(c)->blksize);
  679. strbuf *sb = strbuf_dup(input);
  680. ssh_cipher_encrypt(c, sb->u, sb->len);
  681. return sb;
  682. }
  683. strbuf *ssh_cipher_decrypt_wrapper(ssh_cipher *c, ptrlen input)
  684. {
  685. if (input.len % ssh_cipher_alg(c)->blksize)
  686. fatal_error("ssh_cipher_decrypt: needs a multiple of %d bytes",
  687. ssh_cipher_alg(c)->blksize);
  688. strbuf *sb = strbuf_dup(input);
  689. ssh_cipher_decrypt(c, sb->u, sb->len);
  690. return sb;
  691. }
  692. strbuf *ssh_cipher_encrypt_length_wrapper(ssh_cipher *c, ptrlen input,
  693. unsigned long seq)
  694. {
  695. if (input.len != 4)
  696. fatal_error("ssh_cipher_encrypt_length: needs exactly 4 bytes");
  697. strbuf *sb = strbuf_dup(input);
  698. ssh_cipher_encrypt_length(c, sb->u, sb->len, seq);
  699. return sb;
  700. }
  701. strbuf *ssh_cipher_decrypt_length_wrapper(ssh_cipher *c, ptrlen input,
  702. unsigned long seq)
  703. {
  704. if (input.len != 4)
  705. fatal_error("ssh_cipher_decrypt_length: needs exactly 4 bytes");
  706. strbuf *sb = strbuf_dup(input);
  707. ssh_cipher_decrypt_length(c, sb->u, sb->len, seq);
  708. return sb;
  709. }
  710. strbuf *ssh2_mac_genresult_wrapper(ssh2_mac *m)
  711. {
  712. strbuf *sb = strbuf_new();
  713. void *u = strbuf_append(sb, ssh2_mac_alg(m)->len);
  714. ssh2_mac_genresult(m, u);
  715. return sb;
  716. }
  717. ssh_key *ssh_key_base_key_wrapper(ssh_key *key)
  718. {
  719. /* To avoid having to explain the borrowed reference to Python,
  720. * just clone the key unconditionally */
  721. return ssh_key_clone(ssh_key_base_key(key));
  722. }
  723. void ssh_key_ca_public_blob_wrapper(ssh_key *key, BinarySink *out)
  724. {
  725. /* Wrap to avoid null-pointer dereference */
  726. if (!key->vt->is_certificate)
  727. fatal_error("ssh_key_ca_public_blob: needs a certificate");
  728. ssh_key_ca_public_blob(key, out);
  729. }
  730. void ssh_key_cert_id_string_wrapper(ssh_key *key, BinarySink *out)
  731. {
  732. /* Wrap to avoid null-pointer dereference */
  733. if (!key->vt->is_certificate)
  734. fatal_error("ssh_key_cert_id_string: needs a certificate");
  735. ssh_key_cert_id_string(key, out);
  736. }
  737. static bool ssh_key_check_cert_wrapper(
  738. ssh_key *key, bool host, ptrlen principal, uint64_t time, ptrlen optstr,
  739. BinarySink *error)
  740. {
  741. /* Wrap to avoid null-pointer dereference */
  742. if (!key->vt->is_certificate)
  743. fatal_error("ssh_key_cert_id_string: needs a certificate");
  744. ca_options opts;
  745. opts.permit_rsa_sha1 = true;
  746. opts.permit_rsa_sha256 = true;
  747. opts.permit_rsa_sha512 = true;
  748. while (optstr.len) {
  749. ptrlen word = ptrlen_get_word(&optstr, ",");
  750. ptrlen key = word, value = PTRLEN_LITERAL("");
  751. const char *comma = memchr(word.ptr, '=', word.len);
  752. if (comma) {
  753. key.len = comma - (const char *)word.ptr;
  754. value.ptr = comma + 1;
  755. value.len = word.len - key.len - 1;
  756. }
  757. if (ptrlen_eq_string(key, "permit_rsa_sha1"))
  758. opts.permit_rsa_sha1 = ptrlen_eq_string(value, "true");
  759. if (ptrlen_eq_string(key, "permit_rsa_sha256"))
  760. opts.permit_rsa_sha256 = ptrlen_eq_string(value, "true");
  761. if (ptrlen_eq_string(key, "permit_rsa_sha512"))
  762. opts.permit_rsa_sha512 = ptrlen_eq_string(value, "true");
  763. }
  764. return ssh_key_check_cert(key, host, principal, time, &opts, error);
  765. }
  766. bool dh_validate_f_wrapper(dh_ctx *dh, mp_int *f)
  767. {
  768. return dh_validate_f(dh, f) == NULL;
  769. }
  770. void ssh_hash_update(ssh_hash *h, ptrlen pl)
  771. {
  772. put_datapl(h, pl);
  773. }
  774. void ssh2_mac_update(ssh2_mac *m, ptrlen pl)
  775. {
  776. put_datapl(m, pl);
  777. }
  778. static RSAKey *rsa_new(void)
  779. {
  780. RSAKey *rsa = snew(RSAKey);
  781. memset(rsa, 0, sizeof(RSAKey));
  782. return rsa;
  783. }
  784. strbuf *ecdh_key_getkey_wrapper(ecdh_key *ek, ptrlen remoteKey)
  785. {
  786. /* Fold the boolean return value in C into the string return value
  787. * for this purpose, by returning NULL on failure */
  788. strbuf *sb = strbuf_new();
  789. if (!ecdh_key_getkey(ek, remoteKey, BinarySink_UPCAST(sb))) {
  790. strbuf_free(sb);
  791. return NULL;
  792. }
  793. return sb;
  794. }
  795. static void int16_list_resize(int16_list *list, unsigned p)
  796. {
  797. list->integers = sresize(list->integers, p, uint16_t);
  798. for (size_t i = list->n; i < p; i++)
  799. list->integers[i] = 0;
  800. }
  801. #if 0
  802. static int16_list ntru_ring_to_list_and_free(uint16_t *out, unsigned p)
  803. {
  804. struct mpint_list mpl;
  805. mpl.n = p;
  806. mpl->integers = snewn(p, mp_int *);
  807. for (unsigned i = 0; i < p; i++)
  808. mpl->integers[i] = mp_from_integer((int16_t)out[i]);
  809. sfree(out);
  810. add_finaliser(finaliser_sfree, mpl->integers);
  811. return mpl;
  812. }
  813. #endif
  814. int16_list *ntru_ring_multiply_wrapper(
  815. int16_list *a, int16_list *b, unsigned p, unsigned q)
  816. {
  817. int16_list_resize(a, p);
  818. int16_list_resize(b, p);
  819. int16_list *out = make_int16_list(p);
  820. ntru_ring_multiply(out->integers, a->integers, b->integers, p, q);
  821. return out;
  822. }
  823. int16_list *ntru_ring_invert_wrapper(int16_list *in, unsigned p, unsigned q)
  824. {
  825. int16_list_resize(in, p);
  826. int16_list *out = make_int16_list(p);
  827. unsigned success = ntru_ring_invert(out->integers, in->integers, p, q);
  828. if (!success)
  829. return NULL;
  830. return out;
  831. }
  832. int16_list *ntru_mod3_wrapper(int16_list *in, unsigned p, unsigned q)
  833. {
  834. int16_list_resize(in, p);
  835. int16_list *out = make_int16_list(p);
  836. ntru_mod3(out->integers, in->integers, p, q);
  837. return out;
  838. }
  839. int16_list *ntru_round3_wrapper(int16_list *in, unsigned p, unsigned q)
  840. {
  841. int16_list_resize(in, p);
  842. int16_list *out = make_int16_list(p);
  843. ntru_round3(out->integers, in->integers, p, q);
  844. return out;
  845. }
  846. int16_list *ntru_bias_wrapper(int16_list *in, unsigned bias,
  847. unsigned p, unsigned q)
  848. {
  849. int16_list_resize(in, p);
  850. int16_list *out = make_int16_list(p);
  851. ntru_bias(out->integers, in->integers, bias, p, q);
  852. return out;
  853. }
  854. int16_list *ntru_scale_wrapper(int16_list *in, unsigned scale,
  855. unsigned p, unsigned q)
  856. {
  857. int16_list_resize(in, p);
  858. int16_list *out = make_int16_list(p);
  859. ntru_scale(out->integers, in->integers, scale, p, q);
  860. return out;
  861. }
  862. NTRUEncodeSchedule *ntru_encode_schedule_wrapper(int16_list *in)
  863. {
  864. return ntru_encode_schedule(in->integers, in->n);
  865. }
  866. void ntru_encode_wrapper(NTRUEncodeSchedule *sched, int16_list *rs,
  867. BinarySink *bs)
  868. {
  869. ntru_encode(sched, rs->integers, bs);
  870. }
  871. int16_list *ntru_decode_wrapper(NTRUEncodeSchedule *sched, ptrlen data)
  872. {
  873. int16_list *out = make_int16_list(ntru_encode_schedule_nvals(sched));
  874. ntru_decode(sched, out->integers, data);
  875. return out;
  876. }
  877. int16_list *ntru_gen_short_wrapper(unsigned p, unsigned w)
  878. {
  879. int16_list *out = make_int16_list(p);
  880. ntru_gen_short(out->integers, p, w);
  881. return out;
  882. }
  883. int16_list *ntru_pubkey_wrapper(NTRUKeyPair *keypair)
  884. {
  885. unsigned p = ntru_keypair_p(keypair);
  886. int16_list *out = make_int16_list(p);
  887. memcpy(out->integers, ntru_pubkey(keypair), p*sizeof(uint16_t));
  888. return out;
  889. }
  890. int16_list *ntru_encrypt_wrapper(int16_list *plaintext, int16_list *pubkey,
  891. unsigned p, unsigned q)
  892. {
  893. int16_list *out = make_int16_list(p);
  894. ntru_encrypt(out->integers, plaintext->integers, pubkey->integers, p, q);
  895. return out;
  896. }
  897. int16_list *ntru_decrypt_wrapper(int16_list *ciphertext, NTRUKeyPair *keypair)
  898. {
  899. unsigned p = ntru_keypair_p(keypair);
  900. int16_list *out = make_int16_list(p);
  901. ntru_decrypt(out->integers, ciphertext->integers, keypair);
  902. return out;
  903. }
  904. void mlkem_keygen_internal_wrapper(
  905. BinarySink *ek, BinarySink *dk, const mlkem_params *params,
  906. ptrlen d, ptrlen z)
  907. {
  908. assert(d.len == 32 && "Invalid d length");
  909. assert(z.len == 32 && "Invalid z length");
  910. mlkem_keygen_internal(ek, dk, params, d.ptr, z.ptr);
  911. }
  912. void mlkem_keygen_rho_sigma_wrapper(
  913. BinarySink *ek, BinarySink *dk, const mlkem_params *params,
  914. ptrlen rho, ptrlen sigma, ptrlen z)
  915. {
  916. assert(rho.len == 32 && "Invalid rho length");
  917. assert(sigma.len == 32 && "Invalid sigma length");
  918. assert(z.len == 32 && "Invalid z length");
  919. mlkem_keygen_rho_sigma(ek, dk, params, rho.ptr, sigma.ptr, z.ptr);
  920. }
  921. bool mlkem_encaps_internal_wrapper(BinarySink *ciphertext, BinarySink *kout,
  922. const mlkem_params *params, ptrlen ek,
  923. ptrlen m)
  924. {
  925. assert(m.len == 32 && "Invalid m length");
  926. return mlkem_encaps_internal(ciphertext, kout, params, ek, m.ptr);
  927. }
  928. strbuf *rsa_ssh1_encrypt_wrapper(ptrlen input, RSAKey *key)
  929. {
  930. /* Fold the boolean return value in C into the string return value
  931. * for this purpose, by returning NULL on failure */
  932. strbuf *sb = strbuf_new();
  933. put_datapl(sb, input);
  934. put_padding(sb, key->bytes - input.len, 0);
  935. if (!rsa_ssh1_encrypt(sb->u, input.len, key)) {
  936. strbuf_free(sb);
  937. return NULL;
  938. }
  939. return sb;
  940. }
  941. strbuf *rsa_ssh1_decrypt_pkcs1_wrapper(mp_int *input, RSAKey *key)
  942. {
  943. /* Again, return "" on failure */
  944. strbuf *sb = strbuf_new();
  945. if (!rsa_ssh1_decrypt_pkcs1(input, key, sb))
  946. strbuf_clear(sb);
  947. return sb;
  948. }
  949. strbuf *des_encrypt_xdmauth_wrapper(ptrlen key, ptrlen data)
  950. {
  951. if (key.len != 7)
  952. fatal_error("des_encrypt_xdmauth: key must be 7 bytes long");
  953. if (data.len % 8 != 0)
  954. fatal_error("des_encrypt_xdmauth: data must be a multiple of 8 bytes");
  955. strbuf *sb = strbuf_dup(data);
  956. des_encrypt_xdmauth(key.ptr, sb->u, sb->len);
  957. return sb;
  958. }
  959. strbuf *des_decrypt_xdmauth_wrapper(ptrlen key, ptrlen data)
  960. {
  961. if (key.len != 7)
  962. fatal_error("des_decrypt_xdmauth: key must be 7 bytes long");
  963. if (data.len % 8 != 0)
  964. fatal_error("des_decrypt_xdmauth: data must be a multiple of 8 bytes");
  965. strbuf *sb = strbuf_dup(data);
  966. des_decrypt_xdmauth(key.ptr, sb->u, sb->len);
  967. return sb;
  968. }
  969. strbuf *des3_encrypt_pubkey_wrapper(ptrlen key, ptrlen data)
  970. {
  971. if (key.len != 16)
  972. fatal_error("des3_encrypt_pubkey: key must be 16 bytes long");
  973. if (data.len % 8 != 0)
  974. fatal_error("des3_encrypt_pubkey: data must be a multiple of 8 bytes");
  975. strbuf *sb = strbuf_dup(data);
  976. des3_encrypt_pubkey(key.ptr, sb->u, sb->len);
  977. return sb;
  978. }
  979. strbuf *des3_decrypt_pubkey_wrapper(ptrlen key, ptrlen data)
  980. {
  981. if (key.len != 16)
  982. fatal_error("des3_decrypt_pubkey: key must be 16 bytes long");
  983. if (data.len % 8 != 0)
  984. fatal_error("des3_decrypt_pubkey: data must be a multiple of 8 bytes");
  985. strbuf *sb = strbuf_dup(data);
  986. des3_decrypt_pubkey(key.ptr, sb->u, sb->len);
  987. return sb;
  988. }
  989. strbuf *des3_encrypt_pubkey_ossh_wrapper(ptrlen key, ptrlen iv, ptrlen data)
  990. {
  991. if (key.len != 24)
  992. fatal_error("des3_encrypt_pubkey_ossh: key must be 24 bytes long");
  993. if (iv.len != 8)
  994. fatal_error("des3_encrypt_pubkey_ossh: iv must be 8 bytes long");
  995. if (data.len % 8 != 0)
  996. fatal_error("des3_encrypt_pubkey_ossh: data must be a multiple of 8 bytes");
  997. strbuf *sb = strbuf_dup(data);
  998. des3_encrypt_pubkey_ossh(key.ptr, iv.ptr, sb->u, sb->len);
  999. return sb;
  1000. }
  1001. strbuf *des3_decrypt_pubkey_ossh_wrapper(ptrlen key, ptrlen iv, ptrlen data)
  1002. {
  1003. if (key.len != 24)
  1004. fatal_error("des3_decrypt_pubkey_ossh: key must be 24 bytes long");
  1005. if (iv.len != 8)
  1006. fatal_error("des3_encrypt_pubkey_ossh: iv must be 8 bytes long");
  1007. if (data.len % 8 != 0)
  1008. fatal_error("des3_decrypt_pubkey_ossh: data must be a multiple of 8 bytes");
  1009. strbuf *sb = strbuf_dup(data);
  1010. des3_decrypt_pubkey_ossh(key.ptr, iv.ptr, sb->u, sb->len);
  1011. return sb;
  1012. }
  1013. strbuf *aes256_encrypt_pubkey_wrapper(ptrlen key, ptrlen iv, ptrlen data)
  1014. {
  1015. if (key.len != 32)
  1016. fatal_error("aes256_encrypt_pubkey: key must be 32 bytes long");
  1017. if (iv.len != 16)
  1018. fatal_error("aes256_encrypt_pubkey: iv must be 16 bytes long");
  1019. if (data.len % 16 != 0)
  1020. fatal_error("aes256_encrypt_pubkey: data must be a multiple of 16 bytes");
  1021. strbuf *sb = strbuf_dup(data);
  1022. aes256_encrypt_pubkey(key.ptr, iv.ptr, sb->u, sb->len);
  1023. return sb;
  1024. }
  1025. strbuf *aes256_decrypt_pubkey_wrapper(ptrlen key, ptrlen iv, ptrlen data)
  1026. {
  1027. if (key.len != 32)
  1028. fatal_error("aes256_decrypt_pubkey: key must be 32 bytes long");
  1029. if (iv.len != 16)
  1030. fatal_error("aes256_encrypt_pubkey: iv must be 16 bytes long");
  1031. if (data.len % 16 != 0)
  1032. fatal_error("aes256_decrypt_pubkey: data must be a multiple of 16 bytes");
  1033. strbuf *sb = strbuf_dup(data);
  1034. aes256_decrypt_pubkey(key.ptr, iv.ptr, sb->u, sb->len);
  1035. return sb;
  1036. }
  1037. strbuf *prng_read_wrapper(prng *pr, size_t size)
  1038. {
  1039. strbuf *sb = strbuf_new();
  1040. prng_read(pr, strbuf_append(sb, size), size);
  1041. return sb;
  1042. }
  1043. void prng_seed_update(prng *pr, ptrlen data)
  1044. {
  1045. put_datapl(pr, data);
  1046. }
  1047. bool crcda_detect(ptrlen packet, ptrlen iv)
  1048. {
  1049. if (iv.len != 0 && iv.len != 8)
  1050. fatal_error("crcda_detect: iv must be empty or 8 bytes long");
  1051. if (packet.len % 8 != 0)
  1052. fatal_error("crcda_detect: packet must be a multiple of 8 bytes");
  1053. struct crcda_ctx *ctx = crcda_make_context();
  1054. bool toret = detect_attack(ctx, packet.ptr, packet.len,
  1055. iv.len ? iv.ptr : NULL);
  1056. crcda_free_context(ctx);
  1057. return toret;
  1058. }
  1059. ssh_key *ppk_load_s_wrapper(BinarySource *src, char **comment,
  1060. const char *passphrase, const char **errorstr)
  1061. {
  1062. ssh2_userkey *uk = ppk_load_s(src, passphrase, errorstr);
  1063. if (uk == SSH2_WRONG_PASSPHRASE) {
  1064. /* Fudge this special return value */
  1065. *errorstr = "SSH2_WRONG_PASSPHRASE";
  1066. return NULL;
  1067. }
  1068. if (uk == NULL)
  1069. return NULL;
  1070. ssh_key *toret = uk->key;
  1071. *comment = uk->comment;
  1072. sfree(uk);
  1073. return toret;
  1074. }
  1075. int rsa1_load_s_wrapper(BinarySource *src, RSAKey *rsa, char **comment,
  1076. const char *passphrase, const char **errorstr)
  1077. {
  1078. int toret = rsa1_load_s(src, rsa, passphrase, errorstr);
  1079. *comment = rsa->comment;
  1080. rsa->comment = NULL;
  1081. return toret;
  1082. }
  1083. strbuf *ppk_save_sb_wrapper(
  1084. ssh_key *key, const char *comment, const char *passphrase,
  1085. unsigned fmt_version, Argon2Flavour flavour,
  1086. uint32_t mem, uint32_t passes, uint32_t parallel)
  1087. {
  1088. /*
  1089. * For repeatable testing purposes, we never want a timing-dependent
  1090. * choice of password hashing parameters, so this is easy.
  1091. */
  1092. ppk_save_parameters save_params;
  1093. memset(&save_params, 0, sizeof(save_params));
  1094. save_params.fmt_version = fmt_version;
  1095. save_params.argon2_flavour = flavour;
  1096. save_params.argon2_mem = mem;
  1097. save_params.argon2_passes_auto = false;
  1098. save_params.argon2_passes = passes;
  1099. save_params.argon2_parallelism = parallel;
  1100. ssh2_userkey uk;
  1101. uk.key = key;
  1102. uk.comment = dupstr(comment);
  1103. strbuf *toret = ppk_save_sb(&uk, passphrase, &save_params);
  1104. sfree(uk.comment);
  1105. return toret;
  1106. }
  1107. strbuf *rsa1_save_sb_wrapper(RSAKey *key, const char *comment,
  1108. const char *passphrase)
  1109. {
  1110. key->comment = dupstr(comment);
  1111. strbuf *toret = rsa1_save_sb(key, passphrase);
  1112. sfree(key->comment);
  1113. key->comment = NULL;
  1114. return toret;
  1115. }
  1116. #define return_void(out, expression) (expression)
  1117. static ProgressReceiver null_progress = { .vt = &null_progress_vt };
  1118. mp_int *primegen_generate_wrapper(
  1119. PrimeGenerationContext *ctx, PrimeCandidateSource *pcs)
  1120. {
  1121. return primegen_generate(ctx, pcs, &null_progress);
  1122. }
  1123. RSAKey *rsa1_generate(int bits, bool strong, PrimeGenerationContext *pgc)
  1124. {
  1125. RSAKey *rsakey = snew(RSAKey);
  1126. rsa_generate(rsakey, bits, strong, pgc, &null_progress);
  1127. rsakey->comment = NULL;
  1128. return rsakey;
  1129. }
  1130. ssh_key *rsa_generate_wrapper(int bits, bool strong,
  1131. PrimeGenerationContext *pgc)
  1132. {
  1133. return &rsa1_generate(bits, strong, pgc)->sshk;
  1134. }
  1135. ssh_key *dsa_generate_wrapper(int bits, PrimeGenerationContext *pgc)
  1136. {
  1137. struct dsa_key *dsakey = snew(struct dsa_key);
  1138. dsa_generate(dsakey, bits, pgc, &null_progress);
  1139. return &dsakey->sshk;
  1140. }
  1141. ssh_key *ecdsa_generate_wrapper(int bits)
  1142. {
  1143. struct ecdsa_key *ek = snew(struct ecdsa_key);
  1144. if (!ecdsa_generate(ek, bits)) {
  1145. sfree(ek);
  1146. return NULL;
  1147. }
  1148. return &ek->sshk;
  1149. }
  1150. ssh_key *eddsa_generate_wrapper(int bits)
  1151. {
  1152. struct eddsa_key *ek = snew(struct eddsa_key);
  1153. if (!eddsa_generate(ek, bits)) {
  1154. sfree(ek);
  1155. return NULL;
  1156. }
  1157. return &ek->sshk;
  1158. }
  1159. size_t key_components_count(key_components *kc) { return kc->ncomponents; }
  1160. const char *key_components_nth_name(key_components *kc, size_t n)
  1161. {
  1162. return (n >= kc->ncomponents ? NULL :
  1163. kc->components[n].name);
  1164. }
  1165. strbuf *key_components_nth_str(key_components *kc, size_t n)
  1166. {
  1167. if (n >= kc->ncomponents)
  1168. return NULL;
  1169. if (kc->components[n].type != KCT_TEXT &&
  1170. kc->components[n].type != KCT_BINARY)
  1171. return NULL;
  1172. return strbuf_dup(ptrlen_from_strbuf(kc->components[n].str));
  1173. }
  1174. mp_int *key_components_nth_mp(key_components *kc, size_t n)
  1175. {
  1176. return (n >= kc->ncomponents ? NULL :
  1177. kc->components[n].type != KCT_MPINT ? NULL :
  1178. mp_copy(kc->components[n].mp));
  1179. }
  1180. PockleStatus pockle_add_prime_wrapper(Pockle *pockle, mp_int *p,
  1181. struct mpint_list mpl, mp_int *witness)
  1182. {
  1183. return pockle_add_prime(pockle, p, mpl.integers, mpl.n, witness);
  1184. }
  1185. strbuf *argon2_wrapper(Argon2Flavour flavour, uint32_t mem, uint32_t passes,
  1186. uint32_t parallel, uint32_t taglen,
  1187. ptrlen P, ptrlen S, ptrlen K, ptrlen X)
  1188. {
  1189. strbuf *out = strbuf_new();
  1190. argon2(flavour, mem, passes, parallel, taglen, P, S, K, X, out);
  1191. return out;
  1192. }
  1193. strbuf *openssh_bcrypt_wrapper(ptrlen passphrase, ptrlen salt,
  1194. unsigned rounds, unsigned outbytes)
  1195. {
  1196. strbuf *out = strbuf_new();
  1197. openssh_bcrypt(passphrase, salt, rounds,
  1198. strbuf_append(out, outbytes), outbytes);
  1199. return out;
  1200. }
  1201. strbuf *get_implementations_commasep(ptrlen alg)
  1202. {
  1203. strbuf *out = strbuf_new();
  1204. put_datapl(out, alg);
  1205. if (ptrlen_startswith(alg, PTRLEN_LITERAL("aesgcm"), NULL)) {
  1206. put_fmt(out, ",%.*s_sw", PTRLEN_PRINTF(alg));
  1207. put_fmt(out, ",%.*s_ref_poly", PTRLEN_PRINTF(alg));
  1208. #if HAVE_CLMUL
  1209. put_fmt(out, ",%.*s_clmul", PTRLEN_PRINTF(alg));
  1210. #endif
  1211. #if HAVE_NEON_PMULL
  1212. put_fmt(out, ",%.*s_neon", PTRLEN_PRINTF(alg));
  1213. #endif
  1214. } else if (ptrlen_startswith(alg, PTRLEN_LITERAL("aes"), NULL)) {
  1215. put_fmt(out, ",%.*s_sw", PTRLEN_PRINTF(alg));
  1216. #if HAVE_AES_NI
  1217. put_fmt(out, ",%.*s_ni", PTRLEN_PRINTF(alg));
  1218. #endif
  1219. #if HAVE_NEON_CRYPTO
  1220. put_fmt(out, ",%.*s_neon", PTRLEN_PRINTF(alg));
  1221. #endif
  1222. } else if (ptrlen_startswith(alg, PTRLEN_LITERAL("sha256"), NULL) ||
  1223. ptrlen_startswith(alg, PTRLEN_LITERAL("sha1"), NULL)) {
  1224. put_fmt(out, ",%.*s_sw", PTRLEN_PRINTF(alg));
  1225. #if HAVE_SHA_NI
  1226. put_fmt(out, ",%.*s_ni", PTRLEN_PRINTF(alg));
  1227. #endif
  1228. #if HAVE_NEON_CRYPTO
  1229. put_fmt(out, ",%.*s_neon", PTRLEN_PRINTF(alg));
  1230. #endif
  1231. } else if (ptrlen_startswith(alg, PTRLEN_LITERAL("sha512"), NULL)) {
  1232. put_fmt(out, ",%.*s_sw", PTRLEN_PRINTF(alg));
  1233. #if HAVE_NEON_SHA512
  1234. put_fmt(out, ",%.*s_neon", PTRLEN_PRINTF(alg));
  1235. #endif
  1236. }
  1237. return out;
  1238. }
  1239. #define OPTIONAL_PTR_FUNC(type) \
  1240. typedef TD_val_##type TD_opt_val_##type; \
  1241. static TD_opt_val_##type get_opt_val_##type(BinarySource *in) { \
  1242. ptrlen word = get_word(in); \
  1243. if (ptrlen_eq_string(word, "NULL")) \
  1244. return NULL; \
  1245. return unwrap_value_##type(lookup_value(word))->vu_##type; \
  1246. }
  1247. OPTIONAL_PTR_FUNC(cipher)
  1248. OPTIONAL_PTR_FUNC(mpint)
  1249. OPTIONAL_PTR_FUNC(string)
  1250. /*
  1251. * HERE BE DRAGONS: the horrible C preprocessor business that reads
  1252. * testcrypt-func.h and generates a marshalling wrapper for each
  1253. * exported function.
  1254. *
  1255. * In an ideal world, we would start from a specification like this in
  1256. * testcrypt-func.h
  1257. *
  1258. * FUNC(val_foo, example, ARG(val_bar, bar), ARG(uint, n))
  1259. *
  1260. * and generate a wrapper function looking like this:
  1261. *
  1262. * static void handle_example(BinarySource *in, strbuf *out) {
  1263. * TD_val_bar bar = get_val_bar(in);
  1264. * TD_uint n = get_uint(in);
  1265. * return_val_foo(out, example(bar, n));
  1266. * }
  1267. *
  1268. * which would read the marshalled form of each function argument in
  1269. * turn from the input BinarySource via the get_<type>() function
  1270. * family defined in this file; assign each argument to a local
  1271. * variable; call the underlying C function with all those arguments;
  1272. * and then call a function of the return_<type>() family to marshal
  1273. * the output value into the output strbuf to be sent to standard
  1274. * output.
  1275. *
  1276. * With a more general macro processor such as m4, or custom code in
  1277. * Perl or Python, or a helper program like llvm-tblgen, we could just
  1278. * do that directly, reading function specifications from
  1279. * testcrypt-func.h and writing out exactly the above. But we don't
  1280. * have a fully general macro processor (since everything in that
  1281. * category introduces an extra build dependency that's awkward on
  1282. * plain Windows, or requires compiling and running a helper program
  1283. * which is awkward in a cross-compile). We only have cpp. And in cpp,
  1284. * a macro can't expand one of its arguments differently in two parts
  1285. * of its own expansion. So we have to be more clever.
  1286. *
  1287. * In place of the above code, I instead generate three successive
  1288. * declarations for each function. In simplified form they would look
  1289. * like this:
  1290. *
  1291. * typedef struct ARGS_example {
  1292. * TD_val_bar bar;
  1293. * TD_uint n;
  1294. * } ARGS_example;
  1295. *
  1296. * static inline ARGS_example get_args_example(BinarySource *in) {
  1297. * ARGS_example args;
  1298. * args.bar = get_val_bar(in);
  1299. * args.n = get_uint(in);
  1300. * return args;
  1301. * }
  1302. *
  1303. * static void handle_example(BinarySource *in, strbuf *out) {
  1304. * ARGS_example args = get_args_example(in);
  1305. * return_val_foo(out, example(args.bar, args.n));
  1306. * }
  1307. *
  1308. * Each of these mentions the arguments and their types just _once_,
  1309. * so each one can be generated by a single expansion of the FUNC(...)
  1310. * specification in testcrypt-func.h, with FUNC and ARG and VOID
  1311. * defined to appropriate values.
  1312. *
  1313. * Or ... *nearly*. In fact, I left out several details there, but
  1314. * it's a good starting point to understand the full version.
  1315. *
  1316. * To begin with, several of the variable names shown above are
  1317. * actually named with an ugly leading underscore, to minimise the
  1318. * chance of them colliding with real parameter names. (You could
  1319. * easily imagine 'out' being the name of a parameter to one of the
  1320. * wrapped functions.) Also, we memset the whole structure to zero at
  1321. * the start of get_args_example() to avoid compiler warnings about
  1322. * uninitialised stuff, and insert a precautionary '(void)args;' in
  1323. * handle_example to avoid a similar warning about _unused_ stuff.
  1324. *
  1325. * The big problem is the commas that have to appear between arguments
  1326. * in the final call to the actual C function. Those can't be
  1327. * generated by expanding the ARG macro itself, or you'd get one too
  1328. * many - either a leading comma or a trailing comma. Trailing commas
  1329. * are legal in a Python function call, but unfortunately C is not yet
  1330. * so enlightened. (C permits a trailing comma in a struct or array
  1331. * initialiser, and is coming round to it in enums, but hasn't yet
  1332. * seen the light about function calls or function prototypes.)
  1333. *
  1334. * So the commas must appear _between_ ARG(...) specifiers. And that
  1335. * means they unavoidably appear in _every_ expansion of FUNC() (or
  1336. * rather, every expansion that uses the variadic argument list at
  1337. * all). Therefore, we need to ensure they're harmless in the other
  1338. * two functions as well.
  1339. *
  1340. * In the get_args_example() function above, there's no real problem.
  1341. * The list of assignments can perfectly well be separated by commas
  1342. * instead of semicolons, so that it becomes a single expression-
  1343. * statement instead of a sequence of them; the comma operator still
  1344. * defines a sequence point, so it's fine.
  1345. *
  1346. * But what about the structure definition of ARGS_example?
  1347. *
  1348. * To get round that, we fill the structure with pointless extra
  1349. * cruft, in the form of an extra 'int' field before and after each
  1350. * actually useful argument field. So the real structure definition
  1351. * ends up looking more like this:
  1352. *
  1353. * typedef struct ARGS_example {
  1354. * int _predummy_bar;
  1355. * TD_val_bar bar;
  1356. * int _postdummy_bar, _predummy_n;
  1357. * TD_uint n;
  1358. * int _postdummy_n;
  1359. * } ARGS_example;
  1360. *
  1361. * Those extra 'int' fields are ignored completely at run time. They
  1362. * might cause a runtime space cost if the struct doesn't get
  1363. * completely optimised away when get_args_example is inlined into
  1364. * handle_example, but even if so, that's OK, this is a test program
  1365. * whose memory usage isn't critical. The real point is that, in
  1366. * between each pair of real arguments, there's a declaration
  1367. * containing *two* int variables, and in between them is the vital
  1368. * comma that we need!
  1369. *
  1370. * So in that pass through testcrypt-func.h, the ARG(type, name) macro
  1371. * has to expand to the weird piece of text
  1372. *
  1373. * _predummy_name; // terminating the previous int declaration
  1374. * TD_type name; // declaring the thing we actually wanted
  1375. * int _postdummy_name // new declaration ready to see a comma
  1376. *
  1377. * so that a comma-separated list of pieces of expansion like that
  1378. * will fall into just the right form to be the core of the above
  1379. * expanded structure definition. Then we just need to put in the
  1380. * 'int' after the open brace, and the ';' before the closing brace,
  1381. * and we've got everything we need to make it all syntactically legal.
  1382. *
  1383. * Finally, what if a wrapped function has _no_ arguments? Two out of
  1384. * three uses of the argument list here need some kind of special case
  1385. * for that. That's why you have to write 'VOID' explicitly in an
  1386. * empty argument list in testcrypt-func.h: we make VOID expand to
  1387. * whatever is needed to avoid a syntax error in that special case.
  1388. */
  1389. /*
  1390. * Workarounds for an awkwardness in Visual Studio's preprocessor,
  1391. * which disagrees with everyone else about what happens if you expand
  1392. * __VA_ARGS__ into the argument list of another macro. gcc and clang
  1393. * will treat the commas expanding from __VA_ARGS__ as argument
  1394. * separators, whereas VS will make them all part of a single argument
  1395. * to the secondary macro. We want the former behaviour, so we use
  1396. * the following workaround to enforce it.
  1397. *
  1398. * Each of these JUXTAPOSE macros simply places its arguments side by
  1399. * side. But the arguments are macro-expanded before JUXTAPOSE is
  1400. * called at all, so we can do this:
  1401. *
  1402. * JUXTAPOSE(macroname, (__VA_ARGS__))
  1403. * -> JUXTAPOSE(macroname, (foo, bar, baz))
  1404. * -> macroname (foo, bar, baz)
  1405. *
  1406. * and this preliminary expansion causes the commas to be treated
  1407. * normally by the time VS gets round to expanding the inner macro.
  1408. *
  1409. * We need two differently named JUXTAPOSE macros, because we have to
  1410. * do this trick twice: once to turn FUNC and FUNC_WRAPPED in
  1411. * testcrypt-funcs.h into the underlying common FUNC_INNER, and again
  1412. * to expand the final function call. And you can't expand a macro
  1413. * inside text expanded from the _same_ macro, so we have to do the
  1414. * outer and inner instances of this trick using macros of different
  1415. * names.
  1416. */
  1417. #define JUXTAPOSE1(first, second) first second
  1418. #define JUXTAPOSE2(first, second) first second
  1419. #define FUNC(outtype, fname, ...) \
  1420. JUXTAPOSE1(FUNC_INNER, (outtype, fname, fname, __VA_ARGS__))
  1421. #define FUNC_WRAPPED(outtype, fname, ...) \
  1422. JUXTAPOSE1(FUNC_INNER, (outtype, fname, fname##_wrapper, __VA_ARGS__))
  1423. #define ARG(type, arg) _predummy_##arg; TD_##type arg; int _postdummy_##arg
  1424. #define VOID _voiddummy
  1425. #define FUNC_INNER(outtype, fname, realname, ...) \
  1426. typedef struct ARGS_##fname { \
  1427. int __VA_ARGS__; \
  1428. } ARGS_##fname;
  1429. #include "testcrypt-func.h"
  1430. #undef FUNC_INNER
  1431. #undef ARG
  1432. #undef VOID
  1433. #define ARG(type, arg) _args.arg = get_##type(_in)
  1434. #define VOID ((void)0)
  1435. #define FUNC_INNER(outtype, fname, realname, ...) \
  1436. static inline ARGS_##fname get_args_##fname(BinarySource *_in) { \
  1437. ARGS_##fname _args; \
  1438. memset(&_args, 0, sizeof(_args)); \
  1439. __VA_ARGS__; \
  1440. return _args; \
  1441. }
  1442. #include "testcrypt-func.h"
  1443. #undef FUNC_INNER
  1444. #undef ARG
  1445. #undef VOID
  1446. #define ARG(type, arg) _args.arg
  1447. #define VOID
  1448. #define FUNC_INNER(outtype, fname, realname, ...) \
  1449. static void handle_##fname(BinarySource *_in, strbuf *_out) { \
  1450. ARGS_##fname _args = get_args_##fname(_in); \
  1451. (void)_args; /* suppress warning if no actual arguments */ \
  1452. return_##outtype(_out, JUXTAPOSE2(realname, (__VA_ARGS__))); \
  1453. }
  1454. #include "testcrypt-func.h"
  1455. #undef FUNC_INNER
  1456. #undef ARG
  1457. static void process_line(BinarySource *in, strbuf *out)
  1458. {
  1459. ptrlen id = get_word(in);
  1460. #define DISPATCH_INTERNAL(cmdname, handler) do { \
  1461. if (ptrlen_eq_string(id, cmdname)) { \
  1462. handler(in, out); \
  1463. return; \
  1464. } \
  1465. } while (0)
  1466. #define DISPATCH_COMMAND(cmd) DISPATCH_INTERNAL(#cmd, handle_##cmd)
  1467. DISPATCH_COMMAND(hello);
  1468. DISPATCH_COMMAND(free);
  1469. DISPATCH_COMMAND(newstring);
  1470. DISPATCH_COMMAND(getstring);
  1471. DISPATCH_COMMAND(mp_literal);
  1472. DISPATCH_COMMAND(mp_dump);
  1473. DISPATCH_COMMAND(checkenum);
  1474. #undef DISPATCH_COMMAND
  1475. #define FUNC_INNER(outtype, fname, realname, ...) \
  1476. DISPATCH_INTERNAL(#fname,handle_##fname);
  1477. #include "testcrypt-func.h"
  1478. #undef FUNC_INNER
  1479. #undef DISPATCH_INTERNAL
  1480. fatal_error("command '%.*s': unrecognised", PTRLEN_PRINTF(id));
  1481. }
  1482. static void free_all_values(void)
  1483. {
  1484. for (Value *val; (val = delpos234(values, 0)) != NULL ;)
  1485. free_value(val);
  1486. freetree234(values);
  1487. }
  1488. void dputs(const char *buf)
  1489. {
  1490. fputs(buf, stderr);
  1491. }
  1492. int main(int argc, char **argv)
  1493. {
  1494. const char *infile = NULL, *outfile = NULL;
  1495. bool doing_opts = true;
  1496. enable_dit(); /* in case this is used as a crypto helper (Hyrum's Law) */
  1497. while (--argc > 0) {
  1498. char *p = *++argv;
  1499. if (p[0] == '-' && doing_opts) {
  1500. if (!strcmp(p, "-o")) {
  1501. if (--argc <= 0) {
  1502. fprintf(stderr, "'-o' expects a filename\n");
  1503. return 1;
  1504. }
  1505. outfile = *++argv;
  1506. } else if (!strcmp(p, "--")) {
  1507. doing_opts = false;
  1508. } else if (!strcmp(p, "--help")) {
  1509. printf("usage: testcrypt [INFILE] [-o OUTFILE]\n");
  1510. printf(" also: testcrypt --help display this text\n");
  1511. return 0;
  1512. } else {
  1513. fprintf(stderr, "unknown command line option '%s'\n", p);
  1514. return 1;
  1515. }
  1516. } else if (!infile) {
  1517. infile = p;
  1518. } else {
  1519. fprintf(stderr, "can only handle one input file name\n");
  1520. return 1;
  1521. }
  1522. }
  1523. FILE *infp = stdin;
  1524. if (infile) {
  1525. infp = fopen(infile, "r");
  1526. if (!infp) {
  1527. fprintf(stderr, "%s: open: %s\n", infile, strerror(errno));
  1528. return 1;
  1529. }
  1530. }
  1531. FILE *outfp = stdout;
  1532. if (outfile) {
  1533. outfp = fopen(outfile, "w");
  1534. if (!outfp) {
  1535. fprintf(stderr, "%s: open: %s\n", outfile, strerror(errno));
  1536. return 1;
  1537. }
  1538. }
  1539. values = newtree234(valuecmp);
  1540. atexit(free_all_values);
  1541. for (char *line; (line = chomp(fgetline(infp))) != NULL ;) {
  1542. BinarySource src[1];
  1543. BinarySource_BARE_INIT(src, line, strlen(line));
  1544. strbuf *sb = strbuf_new();
  1545. process_line(src, sb);
  1546. run_finalisers(sb);
  1547. size_t lines = 0;
  1548. for (size_t i = 0; i < sb->len; i++)
  1549. if (sb->s[i] == '\n')
  1550. lines++;
  1551. fprintf(outfp, "%"SIZEu"\n%s", lines, sb->s);
  1552. fflush(outfp);
  1553. strbuf_free(sb);
  1554. sfree(line);
  1555. }
  1556. if (infp != stdin)
  1557. fclose(infp);
  1558. if (outfp != stdin)
  1559. fclose(outfp);
  1560. return 0;
  1561. }