ext_lms.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. /* ext_lms.c
  2. *
  3. * Copyright (C) 2006-2023 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <wolfssl/wolfcrypt/settings.h>
  25. #include <wolfssl/wolfcrypt/error-crypt.h>
  26. #include <wolfssl/wolfcrypt/logging.h>
  27. #ifdef WOLFSSL_HAVE_LMS
  28. #include <wolfssl/wolfcrypt/ext_lms.h>
  29. #ifdef NO_INLINE
  30. #include <wolfssl/wolfcrypt/misc.h>
  31. #else
  32. #define WOLFSSL_MISC_INCLUDED
  33. #include <wolfcrypt/src/misc.c>
  34. #endif
  35. #ifndef WOLFSSL_LMS_VERIFY_ONLY
  36. /* If built against hss_lib_thread.a, the hash-sigs lib will spawn
  37. * worker threads to parallelize cpu intensive tasks. This will mainly
  38. * speedup key generation and signing, and to a lesser extent
  39. * verifying for larger levels values.
  40. *
  41. * Their default max is 16 worker threads, but can be capped with
  42. * hss_extra_info_set_threads(). To be safe we are capping at 4 here.
  43. * */
  44. #define EXT_LMS_MAX_THREADS (4)
  45. /* The hash-sigs hss_generate_private_key API requires a generate_random
  46. * callback that only has output and length args. The RNG struct must be global
  47. * to the function. Maybe there should be a wc_LmsKey_SetRngCb. */
  48. static THREAD_LS_T WC_RNG * LmsRng = NULL;
  49. static bool LmsGenerateRand(void * output, size_t length)
  50. {
  51. int ret = 0;
  52. if (output == NULL || LmsRng == NULL) {
  53. return false;
  54. }
  55. if (length == 0) {
  56. return true;
  57. }
  58. ret = wc_RNG_GenerateBlock(LmsRng, output, (word32) length);
  59. if (ret) {
  60. WOLFSSL_MSG("error: LmsGenerateRand failed");
  61. return false;
  62. }
  63. return true;
  64. }
  65. /* Write callback passed into hash-sigs hss lib.
  66. *
  67. * Returns true on success. */
  68. static bool LmsWritePrivKey(unsigned char *private_key,
  69. size_t len_private_key, void *lmsKey)
  70. {
  71. LmsKey * key = (LmsKey *) lmsKey;
  72. enum wc_LmsRc ret = WC_LMS_RC_NONE;
  73. if (private_key == NULL || key == NULL || len_private_key <= 0) {
  74. WOLFSSL_MSG("error: LmsWritePrivKey: invalid args");
  75. return false;
  76. }
  77. if (key->state != WC_LMS_STATE_PARMSET && key->state != WC_LMS_STATE_OK) {
  78. /* The LmsKey is not ready for writing. */
  79. WOLFSSL_MSG("error: LmsWritePrivKey: LMS key not in writeable state");
  80. return false;
  81. }
  82. if (key->write_private_key == NULL) {
  83. WOLFSSL_MSG("error: LmsWritePrivKey: LMS key write callback not set");
  84. key->state = WC_LMS_STATE_BAD;
  85. return false;
  86. }
  87. /* Use write callback that saves private key to non-volatile storage. */
  88. ret = key->write_private_key(private_key, (word32)len_private_key,
  89. key->context);
  90. if (ret != WC_LMS_RC_SAVED_TO_NV_MEMORY) {
  91. WOLFSSL_MSG("error: LmsKey write_private_key failed");
  92. WOLFSSL_MSG(wc_LmsKey_RcToStr(ret));
  93. key->state = WC_LMS_STATE_BAD;
  94. return false;
  95. }
  96. return true;
  97. }
  98. /* Read callback passed into hash-sigs hss lib.
  99. *
  100. * Returns true on success. */
  101. static bool LmsReadPrivKey(unsigned char *private_key,
  102. size_t len_private_key, void *lmsKey)
  103. {
  104. LmsKey * key = (LmsKey *) lmsKey;
  105. enum wc_LmsRc ret = WC_LMS_RC_NONE;
  106. if (private_key == NULL || key == NULL || len_private_key <= 0) {
  107. WOLFSSL_MSG("error: LmsReadPrivKey: invalid args");
  108. return false;
  109. }
  110. if (key->state != WC_LMS_STATE_PARMSET && key->state != WC_LMS_STATE_OK) {
  111. /* The LmsKey is not ready for reading. */
  112. WOLFSSL_MSG("error: LmsReadPrivKey: LMS key not in readable state");
  113. return false;
  114. }
  115. if (key->read_private_key == NULL) {
  116. WOLFSSL_MSG("error: LmsReadPrivKey: LMS key read callback not set");
  117. key->state = WC_LMS_STATE_BAD;
  118. return false;
  119. }
  120. /* Use read callback that reads private key from non-volatile storage. */
  121. ret = key->read_private_key(private_key, (word32)len_private_key,
  122. key->context);
  123. if (ret != WC_LMS_RC_READ_TO_MEMORY) {
  124. WOLFSSL_MSG("error: LmsKey read_private_key failed");
  125. WOLFSSL_MSG(wc_LmsKey_RcToStr(ret));
  126. key->state = WC_LMS_STATE_BAD;
  127. return false;
  128. }
  129. return true;
  130. }
  131. #endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */
  132. const char * wc_LmsKey_ParmToStr(enum wc_LmsParm lmsParm)
  133. {
  134. switch (lmsParm) {
  135. case WC_LMS_PARM_NONE:
  136. return "LMS_NONE";
  137. case WC_LMS_PARM_L1_H15_W2:
  138. return "LMS/HSS L1_H15_W2";
  139. case WC_LMS_PARM_L1_H15_W4:
  140. return "LMS/HSS L1_H15_W4";
  141. case WC_LMS_PARM_L2_H10_W2:
  142. return "LMS/HSS L2_H10_W2";
  143. case WC_LMS_PARM_L2_H10_W4:
  144. return "LMS/HSS L2_H10_W4";
  145. case WC_LMS_PARM_L2_H10_W8:
  146. return "LMS/HSS L2_H10_W8";
  147. case WC_LMS_PARM_L3_H5_W2:
  148. return "LMS/HSS L3_H5_W2";
  149. case WC_LMS_PARM_L3_H5_W4:
  150. return "LMS/HSS L3_H5_W4";
  151. case WC_LMS_PARM_L3_H5_W8:
  152. return "LMS/HSS L3_H5_W8";
  153. case WC_LMS_PARM_L3_H10_W4:
  154. return "LMS/HSS L3_H10_W4";
  155. case WC_LMS_PARM_L4_H5_W8:
  156. return "LMS/HSS L4_H5_W8";
  157. default:
  158. WOLFSSL_MSG("error: invalid LMS parameter");
  159. break;
  160. }
  161. return "LMS_INVALID";
  162. }
  163. const char * wc_LmsKey_RcToStr(enum wc_LmsRc lmsEc)
  164. {
  165. switch (lmsEc) {
  166. case WC_LMS_RC_NONE:
  167. return "LMS_RC_NONE";
  168. case WC_LMS_RC_BAD_ARG:
  169. return "LMS_RC_BAD_ARG";
  170. case WC_LMS_RC_WRITE_FAIL:
  171. return "LMS_RC_WRITE_FAIL";
  172. case WC_LMS_RC_READ_FAIL:
  173. return "LMS_RC_READ_FAIL";
  174. case WC_LMS_RC_SAVED_TO_NV_MEMORY:
  175. return "LMS_RC_SAVED_TO_NV_MEMORY";
  176. case WC_LMS_RC_READ_TO_MEMORY:
  177. return "LMS_RC_READ_TO_MEMORY";
  178. default:
  179. WOLFSSL_MSG("error: invalid LMS error code");
  180. break;
  181. }
  182. return "LMS_RC_INVALID";
  183. }
  184. /* Init an LMS key.
  185. *
  186. * Call this before setting the params of an LMS key.
  187. *
  188. * Returns 0 on success.
  189. * */
  190. int wc_LmsKey_Init(LmsKey * key, void * heap, int devId)
  191. {
  192. if (key == NULL) {
  193. return BAD_FUNC_ARG;
  194. }
  195. (void) heap;
  196. (void) devId;
  197. ForceZero(key, sizeof(LmsKey));
  198. #ifndef WOLFSSL_LMS_VERIFY_ONLY
  199. hss_init_extra_info(&key->info);
  200. /* Set the max number of worker threads that hash-sigs can spawn. */
  201. hss_extra_info_set_threads(&key->info, EXT_LMS_MAX_THREADS);
  202. key->working_key = NULL;
  203. key->write_private_key = NULL;
  204. key->read_private_key = NULL;
  205. key->context = NULL;
  206. #endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */
  207. key->state = WC_LMS_STATE_INITED;
  208. return 0;
  209. }
  210. /* Set the wc_LmsParm of an LMS key.
  211. *
  212. * Use this if you wish to set a key with a predefined parameter set,
  213. * such as WC_LMS_PARM_L2_H10_W8.
  214. *
  215. * Key must be inited before calling this.
  216. *
  217. * Returns 0 on success.
  218. * */
  219. int wc_LmsKey_SetLmsParm(LmsKey * key, enum wc_LmsParm lmsParm)
  220. {
  221. if (key == NULL) {
  222. return BAD_FUNC_ARG;
  223. }
  224. /* If NONE is passed, default to the lowest predefined set. */
  225. switch (lmsParm) {
  226. case WC_LMS_PARM_NONE:
  227. case WC_LMS_PARM_L1_H15_W2:
  228. return wc_LmsKey_SetParameters(key, 1, 15, 2);
  229. case WC_LMS_PARM_L1_H15_W4:
  230. return wc_LmsKey_SetParameters(key, 1, 15, 4);
  231. case WC_LMS_PARM_L2_H10_W2:
  232. return wc_LmsKey_SetParameters(key, 2, 10, 2);
  233. case WC_LMS_PARM_L2_H10_W4:
  234. return wc_LmsKey_SetParameters(key, 2, 10, 4);
  235. case WC_LMS_PARM_L2_H10_W8:
  236. return wc_LmsKey_SetParameters(key, 2, 10, 8);
  237. case WC_LMS_PARM_L3_H5_W2:
  238. return wc_LmsKey_SetParameters(key, 3, 5, 2);
  239. case WC_LMS_PARM_L3_H5_W4:
  240. return wc_LmsKey_SetParameters(key, 3, 5, 4);
  241. case WC_LMS_PARM_L3_H5_W8:
  242. return wc_LmsKey_SetParameters(key, 3, 5, 8);
  243. case WC_LMS_PARM_L3_H10_W4:
  244. return wc_LmsKey_SetParameters(key, 3, 10, 4);
  245. case WC_LMS_PARM_L4_H5_W8:
  246. return wc_LmsKey_SetParameters(key, 4, 5, 8);
  247. default:
  248. WOLFSSL_MSG("error: invalid LMS parameter set");
  249. break;
  250. }
  251. return BAD_FUNC_ARG;
  252. }
  253. /* Set the parameters of an LMS key.
  254. *
  255. * Use this if you wish to set specific parameters not found in the
  256. * wc_LmsParm predefined sets. See comments in lms.h for allowed
  257. * parameters.
  258. *
  259. * Key must be inited before calling this.
  260. *
  261. * Returns 0 on success.
  262. * */
  263. int wc_LmsKey_SetParameters(LmsKey * key, int levels, int height,
  264. int winternitz)
  265. {
  266. int i = 0;
  267. param_set_t lm = LMS_SHA256_N32_H5;
  268. param_set_t ots = LMOTS_SHA256_N32_W1;
  269. if (key == NULL) {
  270. return BAD_FUNC_ARG;
  271. }
  272. if (key->state != WC_LMS_STATE_INITED) {
  273. WOLFSSL_MSG("error: LmsKey needs init");
  274. return -1;
  275. }
  276. /* Verify inputs make sense.
  277. *
  278. * Note: there does not seem to be a define for min or
  279. * max Winternitz integer in hash-sigs lib or RFC8554. */
  280. if (levels < MIN_HSS_LEVELS || levels > MAX_HSS_LEVELS) {
  281. WOLFSSL_MSG("error: invalid level parameter");
  282. return BAD_FUNC_ARG;
  283. }
  284. if (height < MIN_MERKLE_HEIGHT || height > MAX_MERKLE_HEIGHT) {
  285. WOLFSSL_MSG("error: invalid height parameter");
  286. return BAD_FUNC_ARG;
  287. }
  288. switch (height) {
  289. case 5:
  290. lm = LMS_SHA256_N32_H5;
  291. break;
  292. case 10:
  293. lm = LMS_SHA256_N32_H10;
  294. break;
  295. case 15:
  296. lm = LMS_SHA256_N32_H15;
  297. break;
  298. case 20:
  299. lm = LMS_SHA256_N32_H20;
  300. break;
  301. case 25:
  302. lm = LMS_SHA256_N32_H25;
  303. break;
  304. default:
  305. WOLFSSL_MSG("error: invalid height parameter");
  306. return BAD_FUNC_ARG;
  307. }
  308. switch (winternitz) {
  309. case 1:
  310. ots = LMOTS_SHA256_N32_W1;
  311. break;
  312. case 2:
  313. ots = LMOTS_SHA256_N32_W2;
  314. break;
  315. case 4:
  316. ots = LMOTS_SHA256_N32_W4;
  317. break;
  318. case 8:
  319. ots = LMOTS_SHA256_N32_W8;
  320. break;
  321. default:
  322. WOLFSSL_MSG("error: invalid winternitz parameter");
  323. return BAD_FUNC_ARG;
  324. }
  325. key->levels = levels;
  326. for (i = 0; i < levels; ++i) {
  327. key->lm_type[i] = lm;
  328. key->lm_ots_type[i] = ots;
  329. }
  330. /* Move the state to params set.
  331. * Key is ready for MakeKey or Reload. */
  332. key->state = WC_LMS_STATE_PARMSET;
  333. return 0;
  334. }
  335. /* Get the parameters of an LMS key.
  336. *
  337. * Key must be inited and parameters set before calling this.
  338. *
  339. * Returns 0 on success.
  340. * */
  341. int wc_LmsKey_GetParameters(const LmsKey * key, int * levels, int * height,
  342. int * winternitz)
  343. {
  344. if (key == NULL || levels == NULL || height == NULL || winternitz == NULL) {
  345. return BAD_FUNC_ARG;
  346. }
  347. /* This shouldn't happen, but check the LmsKey parameters aren't invalid. */
  348. if (key->levels < MIN_HSS_LEVELS || key->levels > MAX_HSS_LEVELS) {
  349. WOLFSSL_MSG("error: LmsKey invalid level parameter");
  350. return -1;
  351. }
  352. *levels = key->levels;
  353. switch (key->lm_type[0]) {
  354. case LMS_SHA256_N32_H5:
  355. *height = 5;
  356. break;
  357. case LMS_SHA256_N32_H10:
  358. *height = 10;
  359. break;
  360. case LMS_SHA256_N32_H15:
  361. *height = 15;
  362. break;
  363. case LMS_SHA256_N32_H20:
  364. *height = 20;
  365. break;
  366. case LMS_SHA256_N32_H25:
  367. *height = 25;
  368. break;
  369. default:
  370. WOLFSSL_MSG("error: LmsKey invalid height parameter");
  371. return -1;
  372. }
  373. switch (key->lm_ots_type[0]) {
  374. case LMOTS_SHA256_N32_W1:
  375. *winternitz = 1;
  376. break;
  377. case LMOTS_SHA256_N32_W2:
  378. *winternitz = 2;
  379. break;
  380. case LMOTS_SHA256_N32_W4:
  381. *winternitz = 4;
  382. break;
  383. case LMOTS_SHA256_N32_W8:
  384. *winternitz = 8;
  385. break;
  386. default:
  387. WOLFSSL_MSG("error: LmsKey invalid winternitz parameter");
  388. return -1;
  389. }
  390. return 0;
  391. }
  392. /* Frees the LMS key from memory.
  393. *
  394. * This does not affect the private key saved to non-volatile storage.
  395. * */
  396. void wc_LmsKey_Free(LmsKey* key)
  397. {
  398. if (key == NULL) {
  399. return;
  400. }
  401. #ifndef WOLFSSL_LMS_VERIFY_ONLY
  402. if (key->working_key != NULL) {
  403. hss_free_working_key(key->working_key);
  404. key->working_key = NULL;
  405. }
  406. #endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */
  407. ForceZero(key, sizeof(LmsKey));
  408. key->state = WC_LMS_STATE_FREED;
  409. return;
  410. }
  411. #ifndef WOLFSSL_LMS_VERIFY_ONLY
  412. /* Set the write private key callback to the LMS key structure.
  413. *
  414. * The callback must be able to write/update the private key to
  415. * non-volatile storage.
  416. *
  417. * Returns 0 on success.
  418. * */
  419. int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb write_cb)
  420. {
  421. if (key == NULL || write_cb == NULL) {
  422. return BAD_FUNC_ARG;
  423. }
  424. /* Changing the write callback of an already working key is forbidden. */
  425. if (key->state == WC_LMS_STATE_OK) {
  426. WOLFSSL_MSG("error: wc_LmsKey_SetWriteCb: key in use");
  427. return -1;
  428. }
  429. key->write_private_key = write_cb;
  430. return 0;
  431. }
  432. /* Set the read private key callback to the LMS key structure.
  433. *
  434. * The callback must be able to read the private key from
  435. * non-volatile storage.
  436. *
  437. * Returns 0 on success.
  438. * */
  439. int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb read_cb)
  440. {
  441. if (key == NULL || read_cb == NULL) {
  442. return BAD_FUNC_ARG;
  443. }
  444. /* Changing the read callback of an already working key is forbidden. */
  445. if (key->state == WC_LMS_STATE_OK) {
  446. WOLFSSL_MSG("error: wc_LmsKey_SetReadCb: key in use");
  447. return -1;
  448. }
  449. key->read_private_key = read_cb;
  450. return 0;
  451. }
  452. /* Sets the context to be used by write and read callbacks.
  453. *
  454. * E.g. this could be a filename if the callbacks write/read to file.
  455. *
  456. * Returns 0 on success.
  457. * */
  458. int wc_LmsKey_SetContext(LmsKey * key, void * context)
  459. {
  460. if (key == NULL || context == NULL) {
  461. return BAD_FUNC_ARG;
  462. }
  463. /* Setting context of an already working key is forbidden. */
  464. if (key->state == WC_LMS_STATE_OK) {
  465. WOLFSSL_MSG("error: wc_LmsKey_SetContext: key in use");
  466. return -1;
  467. }
  468. key->context = context;
  469. return 0;
  470. }
  471. /* Make the LMS private/public key pair. The key must have its parameters
  472. * set before calling this.
  473. *
  474. * Write/read callbacks, and context data, must be set prior.
  475. * Key must have parameters set.
  476. *
  477. * Returns 0 on success.
  478. * */
  479. int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG * rng)
  480. {
  481. bool result = true;
  482. if (key == NULL || rng == NULL) {
  483. return BAD_FUNC_ARG;
  484. }
  485. if (key->state != WC_LMS_STATE_PARMSET) {
  486. WOLFSSL_MSG("error: LmsKey not ready for generation");
  487. return -1;
  488. }
  489. if (key->write_private_key == NULL || key->read_private_key == NULL) {
  490. WOLFSSL_MSG("error: LmsKey write/read callbacks are not set");
  491. return -1;
  492. }
  493. if (key->context == NULL) {
  494. WOLFSSL_MSG("error: LmsKey context is not set");
  495. return -1;
  496. }
  497. LmsRng = rng;
  498. /* TODO: The hash-sigs lib allows you to save variable length auxiliary
  499. * data, which can be used to speed up key reloading when signing. The
  500. * aux data can be 300B - 1KB in size.
  501. *
  502. * Not implemented at the moment.
  503. *
  504. * key->aux_data_len = hss_get_aux_data_len(AUX_DATA_MAX_LEN, key->levels,
  505. * key->lm_type,
  506. * key->lm_ots_type);
  507. *
  508. * key->aux_data = XMALLOC(key->aux_data_len, NULL,
  509. * DYNAMIC_TYPE_TMP_BUFFER);
  510. */
  511. /* First generate the private key using the parameters and callbacks.
  512. * If successful, private key will be saved to non-volatile storage,
  513. * and the public key will be in memory. */
  514. result = hss_generate_private_key(LmsGenerateRand, key->levels,
  515. key->lm_type, key->lm_ots_type,
  516. LmsWritePrivKey, key,
  517. key->pub, sizeof(key->pub),
  518. NULL, 0, &key->info);
  519. if (!result) {
  520. WOLFSSL_MSG("error: hss_generate_private_key failed");
  521. key->state = WC_LMS_STATE_BAD;
  522. return -1;
  523. }
  524. /* Once generated, now we must load the private key so we have
  525. * an hss working key for signing operations. */
  526. key->working_key = hss_load_private_key(LmsReadPrivKey, key,
  527. 0, NULL, 0, &key->info);
  528. if (key->working_key == NULL) {
  529. WOLFSSL_MSG("error: hss_load_private_key failed");
  530. key->state = WC_LMS_STATE_BAD;
  531. return -1;
  532. }
  533. /* This should not happen, but check just in case. */
  534. if (wc_LmsKey_SigsLeft(key) == 0) {
  535. WOLFSSL_MSG("error: generated LMS key signatures exhausted");
  536. key->state = WC_LMS_STATE_NOSIGS;
  537. return -1;
  538. }
  539. key->state = WC_LMS_STATE_OK;
  540. return 0;
  541. }
  542. /* Reload a key that has been prepared with the appropriate params and
  543. * data. Use this if you wish to resume signing with an existing key.
  544. *
  545. * Write/read callbacks, and context data, must be set prior.
  546. * Key must have parameters set.
  547. *
  548. * Returns 0 on success. */
  549. int wc_LmsKey_Reload(LmsKey * key)
  550. {
  551. bool result = true;
  552. if (key == NULL) {
  553. return BAD_FUNC_ARG;
  554. }
  555. if (key->state != WC_LMS_STATE_PARMSET) {
  556. WOLFSSL_MSG("error: LmsKey not ready for reload");
  557. return -1;
  558. }
  559. if (key->write_private_key == NULL || key->read_private_key == NULL) {
  560. WOLFSSL_MSG("error: LmsKey write/read callbacks are not set");
  561. return -1;
  562. }
  563. if (key->context == NULL) {
  564. WOLFSSL_MSG("error: LmsKey context is not set");
  565. return -1;
  566. }
  567. key->working_key = hss_load_private_key(LmsReadPrivKey, key,
  568. 0, NULL, 0, &key->info);
  569. if (key->working_key == NULL) {
  570. WOLFSSL_MSG("error: hss_load_private_key failed");
  571. key->state = WC_LMS_STATE_BAD;
  572. return -1;
  573. }
  574. result = hss_get_parameter_set(&key->levels, key->lm_type,
  575. key->lm_ots_type, LmsReadPrivKey, key);
  576. if (!result) {
  577. WOLFSSL_MSG("error: hss_get_parameter_set failed");
  578. key->state = WC_LMS_STATE_BAD;
  579. hss_free_working_key(key->working_key);
  580. key->working_key = NULL;
  581. return -1;
  582. }
  583. /* Double check the key actually has signatures left. */
  584. if (wc_LmsKey_SigsLeft(key) == 0) {
  585. WOLFSSL_MSG("error: reloaded LMS key signatures exhausted");
  586. key->state = WC_LMS_STATE_NOSIGS;
  587. return -1;
  588. }
  589. key->state = WC_LMS_STATE_OK;
  590. return 0;
  591. }
  592. /* Given a levels, height, winternitz parameter set, determine
  593. * the private key length */
  594. int wc_LmsKey_GetPrivLen(const LmsKey * key, word32 * len)
  595. {
  596. if (key == NULL || len == NULL) {
  597. return BAD_FUNC_ARG;
  598. }
  599. *len = (word32) hss_get_private_key_len(key->levels, key->lm_type,
  600. key->lm_ots_type);
  601. return 0;
  602. }
  603. int wc_LmsKey_Sign(LmsKey* key, byte * sig, word32 * sigSz, const byte * msg,
  604. int msgSz)
  605. {
  606. bool result = true;
  607. size_t len = 0;
  608. if (key == NULL || sig == NULL || sigSz == NULL || msg == NULL) {
  609. return BAD_FUNC_ARG;
  610. }
  611. if (msgSz <= 0) {
  612. return BAD_FUNC_ARG;
  613. }
  614. if (key->state == WC_LMS_STATE_NOSIGS) {
  615. WOLFSSL_MSG("error: LMS signatures exhausted");
  616. return -1;
  617. }
  618. else if (key->state != WC_LMS_STATE_OK) {
  619. /* The key had an error the last time it was used, and we
  620. * can't guarantee its state. */
  621. WOLFSSL_MSG("error: can't sign, LMS key not in good state");
  622. return -1;
  623. }
  624. len = hss_get_signature_len(key->levels, key->lm_type, key->lm_ots_type);
  625. if (len == 0) {
  626. /* Key parameters are invalid. */
  627. WOLFSSL_MSG("error: hss_get_signature_len failed");
  628. key->state = WC_LMS_STATE_BAD;
  629. return -1;
  630. }
  631. result = hss_generate_signature(key->working_key, LmsWritePrivKey,
  632. key, (const void *) msg, msgSz,
  633. sig, len, &key->info);
  634. if (!result) {
  635. if (wc_LmsKey_SigsLeft(key) == 0) {
  636. WOLFSSL_MSG("error: LMS signatures exhausted");
  637. key->state = WC_LMS_STATE_NOSIGS;
  638. return -1;
  639. }
  640. WOLFSSL_MSG("error: hss_generate_signature failed");
  641. key->state = WC_LMS_STATE_BAD;
  642. return -1;
  643. }
  644. *sigSz = (word32) len;
  645. return 0;
  646. }
  647. /* Returns 1 if there are signatures remaining.
  648. * Returns 0 if available signatures are exhausted.
  649. *
  650. * Note: the number of remaining signatures is hidden behind an opaque
  651. * pointer in the hash-sigs lib. We could add a counter here that is
  652. * decremented on every signature. The number of available signatures
  653. * grows as
  654. * N = 2 ** (levels * height)
  655. * so it would need to be a big integer. */
  656. int wc_LmsKey_SigsLeft(LmsKey * key)
  657. {
  658. if (key == NULL) {
  659. return BAD_FUNC_ARG;
  660. }
  661. if (hss_extra_info_test_last_signature(&key->info)) {
  662. return 0;
  663. }
  664. return 1;
  665. }
  666. #endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY*/
  667. /* Given a levels, height, winternitz parameter set, determine
  668. * the public key length */
  669. int wc_LmsKey_GetPubLen(const LmsKey * key, word32 * len)
  670. {
  671. if (key == NULL || len == NULL) {
  672. return BAD_FUNC_ARG;
  673. }
  674. *len = (word32) hss_get_public_key_len(key->levels, key->lm_type,
  675. key->lm_ots_type);
  676. return 0;
  677. }
  678. /* Export a generated public key and parameter set from one LmsKey
  679. * to another. Use this to prepare a signature verification LmsKey
  680. * that is pub only.
  681. *
  682. * Though the public key is all that is used to verify signatures,
  683. * the parameter set is needed to calculate the signature length
  684. * before hand. */
  685. int wc_LmsKey_ExportPub(LmsKey * keyDst, const LmsKey * keySrc)
  686. {
  687. if (keyDst == NULL || keySrc == NULL) {
  688. return BAD_FUNC_ARG;
  689. }
  690. ForceZero(keyDst, sizeof(LmsKey));
  691. XMEMCPY(keyDst->pub, keySrc->pub, sizeof(keySrc->pub));
  692. XMEMCPY(keyDst->lm_type, keySrc->lm_type, sizeof(keySrc->lm_type));
  693. XMEMCPY(keyDst->lm_ots_type, keySrc->lm_ots_type,
  694. sizeof(keySrc->lm_ots_type));
  695. keyDst->levels = keySrc->levels;
  696. /* Mark this key as verify only, to prevent misuse. */
  697. keyDst->state = WC_LMS_STATE_VERIFYONLY;
  698. return 0;
  699. }
  700. /* Exports the raw LMS public key buffer from key to out buffer.
  701. * The out buffer should be large enough to hold the public key, and
  702. * outLen should indicate the size of the buffer.
  703. *
  704. * - Returns 0 on success, and sets outLen to LMS pubLen.
  705. * - Returns BUFFER_E if outLen < LMS pubLen.
  706. *
  707. * Call wc_LmsKey_GetPubLen beforehand to determine pubLen.
  708. * */
  709. int wc_LmsKey_ExportPubRaw(const LmsKey * key, byte * out, word32 * outLen)
  710. {
  711. int ret = 0;
  712. word32 pubLen = 0;
  713. if (key == NULL || out == NULL || outLen == NULL) {
  714. return BAD_FUNC_ARG;
  715. }
  716. ret = wc_LmsKey_GetPubLen(key, &pubLen);
  717. if (ret != 0) {
  718. WOLFSSL_MSG("error: wc_LmsKey_GetPubLen failed");
  719. return -1;
  720. }
  721. if (*outLen < pubLen) {
  722. return BUFFER_E;
  723. }
  724. XMEMCPY(out, key->pub, pubLen);
  725. *outLen = pubLen;
  726. return 0;
  727. }
  728. /* Imports a raw public key buffer from in array to LmsKey key.
  729. *
  730. * The LMS parameters must be set first with wc_LmsKey_SetLmsParm or
  731. * wc_LmsKey_SetParameters, and inLen must match the length returned
  732. * by wc_LmsKey_GetPubLen.
  733. *
  734. * - Returns 0 on success.
  735. * - Returns BUFFER_E if inlen != LMS pubLen.
  736. *
  737. * Call wc_LmsKey_GetPubLen beforehand to determine pubLen.
  738. * */
  739. int wc_LmsKey_ImportPubRaw(LmsKey * key, const byte * in, word32 inLen)
  740. {
  741. int ret = 0;
  742. word32 pubLen = 0;
  743. if (key == NULL || in == NULL) {
  744. return BAD_FUNC_ARG;
  745. }
  746. ret = wc_LmsKey_GetPubLen(key, &pubLen);
  747. if (ret != 0) {
  748. WOLFSSL_MSG("error: wc_LmsKey_GetPubLen failed");
  749. return -1;
  750. }
  751. if (inLen != pubLen) {
  752. /* Something inconsistent. Parameters weren't set, or input
  753. * pub key is wrong.*/
  754. return BUFFER_E;
  755. }
  756. XMEMCPY(key->pub, in, pubLen);
  757. return 0;
  758. }
  759. /* Given a levels, height, winternitz parameter set, determine
  760. * the signature length.
  761. *
  762. * Call this before wc_LmsKey_Sign so you know the length of
  763. * the required signature buffer. */
  764. int wc_LmsKey_GetSigLen(const LmsKey * key, word32 * len)
  765. {
  766. if (key == NULL || len == NULL) {
  767. return BAD_FUNC_ARG;
  768. }
  769. *len = (word32) hss_get_signature_len(key->levels, key->lm_type,
  770. key->lm_ots_type);
  771. return 0;
  772. }
  773. int wc_LmsKey_Verify(LmsKey * key, const byte * sig, word32 sigSz,
  774. const byte * msg, int msgSz)
  775. {
  776. bool result = true;
  777. if (key == NULL || sig == NULL || msg == NULL) {
  778. return BAD_FUNC_ARG;
  779. }
  780. #ifdef WOLFSSL_LMS_VERIFY_ONLY
  781. result = hss_validate_signature(key->pub, (const void *) msg, msgSz, sig,
  782. sigSz, NULL);
  783. #else
  784. result = hss_validate_signature(key->pub, (const void *) msg, msgSz, sig,
  785. sigSz, &key->info);
  786. #endif
  787. if (!result) {
  788. WOLFSSL_MSG("error: hss_validate_signature failed");
  789. return -1;
  790. }
  791. return 0;
  792. }
  793. #endif /* WOLFSSL_HAVE_LMS */