ext_xmss.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. /* ext_xmss.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. #include <wolfssl/wolfcrypt/sha256.h>
  28. #ifdef WOLFSSL_HAVE_XMSS
  29. #include <wolfssl/wolfcrypt/ext_xmss.h>
  30. #ifdef NO_INLINE
  31. #include <wolfssl/wolfcrypt/misc.h>
  32. #else
  33. #define WOLFSSL_MISC_INCLUDED
  34. #include <wolfcrypt/src/misc.c>
  35. #endif
  36. #include <xmss_callbacks.h>
  37. #ifndef WOLFSSL_XMSS_VERIFY_ONLY
  38. static THREAD_LS_T WC_RNG * xmssRng = NULL;
  39. /* RNG callback used by xmss.
  40. * */
  41. static int rng_cb(void * output, size_t length)
  42. {
  43. int ret = 0;
  44. if (output == NULL || xmssRng == NULL) {
  45. return -1;
  46. }
  47. if (length == 0) {
  48. return 0;
  49. }
  50. ret = wc_RNG_GenerateBlock(xmssRng, (byte *)output, (word32)length);
  51. if (ret) {
  52. WOLFSSL_MSG("error: XMSS rng_cb failed");
  53. return -1;
  54. }
  55. return 0;
  56. }
  57. #endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */
  58. /* SHA256 callback used by XMSS.
  59. * */
  60. static int sha256_cb(const unsigned char *in, unsigned long long inlen,
  61. unsigned char *out)
  62. {
  63. wc_Sha256 sha;
  64. if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) {
  65. WOLFSSL_MSG("SHA256 Init failed");
  66. return -1;
  67. }
  68. if (wc_Sha256Update(&sha, in, (word32) inlen) != 0) {
  69. WOLFSSL_MSG("SHA256 Update failed");
  70. return -1;
  71. }
  72. if (wc_Sha256Final(&sha, out) != 0) {
  73. WOLFSSL_MSG("SHA256 Final failed");
  74. wc_Sha256Free(&sha);
  75. return -1;
  76. }
  77. wc_Sha256Free(&sha);
  78. return 0;
  79. }
  80. /* Init an XMSS key.
  81. *
  82. * Call this before setting the params of an XMSS key.
  83. *
  84. * key [in] The XMSS key to init.
  85. * heap [in] Unused.
  86. * devId [in] Unused.
  87. *
  88. * returns 0 on success.
  89. * returns BAD_FUNC_ARG when a parameter is NULL.
  90. * */
  91. int wc_XmssKey_Init(XmssKey * key, void * heap, int devId)
  92. {
  93. if (key == NULL) {
  94. return BAD_FUNC_ARG;
  95. }
  96. (void) heap;
  97. (void) devId;
  98. ForceZero(key, sizeof(XmssKey));
  99. #ifndef WOLFSSL_XMSS_VERIFY_ONLY
  100. key->sk = NULL;
  101. key->sk_len = 0;
  102. key->write_private_key = NULL;
  103. key->read_private_key = NULL;
  104. key->context = NULL;
  105. #endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */
  106. key->state = WC_XMSS_STATE_INITED;
  107. return 0;
  108. }
  109. /* Sets the XMSS key parameters, given an OID.
  110. *
  111. * Note: XMSS and XMSS^MT parameter sets do have overlapping
  112. * OIDs, therefore is_xmssmt is necessary to toggle.
  113. *
  114. * key [in] The XMSS key to set.
  115. * OID [in] The XMSS parameter set OID.
  116. * is_xmssmt [in] 1 The OID is assumed to be XMSS^MT.
  117. * 0 The OID is assumed to be XMSS.
  118. *
  119. * returns 0 on success.
  120. * returns BAD_FUNC_ARG when a parameter is NULL.
  121. * returns -1 on parse failure.
  122. * */
  123. static int wc_XmssKey_SetOid(XmssKey * key, uint32_t oid, int is_xmssmt)
  124. {
  125. int ret = 0;
  126. if (key == NULL || oid == 0) {
  127. return BAD_FUNC_ARG;
  128. }
  129. /* Parse the OID and load the XMSS params structure. */
  130. if (is_xmssmt) {
  131. ret = xmssmt_parse_oid(&key->params, oid);
  132. }
  133. else {
  134. ret = xmss_parse_oid(&key->params, oid);
  135. }
  136. if (ret != 0) {
  137. WOLFSSL_MSG("error: XMSS parse oid failed");
  138. return -1;
  139. }
  140. /* Finally, sanity check that this is a supported parameter set.
  141. *
  142. * We are only supporting XMSS/XMSS^MT with SHA256 parameter sets
  143. * that NIST SP 800-208 has standardized. See patched xmss-reference
  144. * params.h for the defines. */
  145. if (key->params.func != XMSS_SHA2 ||
  146. key->params.n != XMSS_SHA256_N ||
  147. key->params.padding_len != XMSS_SHA256_PADDING_LEN ||
  148. key->params.wots_w != 16 ||
  149. key->params.wots_len != XMSS_SHA256_WOTS_LEN) {
  150. WOLFSSL_MSG("error: unsupported XMSS/XMSS^MT parameter set");
  151. return -1;
  152. }
  153. ret = xmss_set_sha_cb(sha256_cb);
  154. if (ret != 0) {
  155. WOLFSSL_MSG("error: xmss_set_sha_cb failed");
  156. return -1;
  157. }
  158. #ifndef WOLFSSL_XMSS_VERIFY_ONLY
  159. ret = xmss_set_rng_cb(rng_cb);
  160. if (ret != 0) {
  161. WOLFSSL_MSG("error: xmss_set_rng_cb failed");
  162. return -1;
  163. }
  164. #endif
  165. key->oid = oid;
  166. key->is_xmssmt = is_xmssmt;
  167. key->state = WC_XMSS_STATE_PARMSET;
  168. return 0;
  169. }
  170. /* Set the XMSS key parameter string.
  171. *
  172. * The input string must be one of the supported param set names in
  173. * the "Name" section from the table in wolfssl/wolfcrypt/xmss.h,
  174. * e.g. "XMSS-SHA2_10_256" or "XMSSMT-SHA2_20/4_256".
  175. *
  176. * key [in] The XMSS key to set.
  177. * str [in] The XMSS/XMSS^MT parameter string.
  178. *
  179. * returns 0 on success.
  180. * returns BAD_FUNC_ARG when a parameter is NULL.
  181. * returns -1 on failure.
  182. * */
  183. int wc_XmssKey_SetParamStr(XmssKey * key, const char * str)
  184. {
  185. int ret = 0;
  186. uint32_t oid = 0;
  187. int is_xmssmt = 0;
  188. if (key == NULL || str == NULL) {
  189. return BAD_FUNC_ARG;
  190. }
  191. if (key->state != WC_XMSS_STATE_INITED) {
  192. WOLFSSL_MSG("error: XMSS key needs init");
  193. return BAD_FUNC_ARG;
  194. }
  195. switch(XSTRLEN(str)) {
  196. case XMSS_NAME_LEN:
  197. is_xmssmt = 0;
  198. break;
  199. case XMSSMT_NAME_MIN_LEN:
  200. case XMSSMT_NAME_MAX_LEN:
  201. is_xmssmt = 1;
  202. break;
  203. default:
  204. WOLFSSL_MSG("error: XMSS param str invalid length");
  205. return BAD_FUNC_ARG;
  206. }
  207. /* Convert XMSS param string to OID. */
  208. if (is_xmssmt) {
  209. ret = xmssmt_str_to_oid(&oid, str);
  210. }
  211. else {
  212. ret = xmss_str_to_oid(&oid, str);
  213. }
  214. if (ret != 0) {
  215. WOLFSSL_MSG("error: xmssmt_str_to_oid failed");
  216. return -1;
  217. }
  218. return wc_XmssKey_SetOid(key, oid, is_xmssmt);
  219. }
  220. /* Force zeros and frees the XMSS key from memory.
  221. *
  222. * This does not touch the private key saved to non-volatile storage.
  223. *
  224. * This is the only function that frees the key->sk array.
  225. *
  226. * key [in] The XMSS key.
  227. *
  228. * returns void
  229. * */
  230. void wc_XmssKey_Free(XmssKey* key)
  231. {
  232. if (key == NULL) {
  233. return;
  234. }
  235. #ifndef WOLFSSL_XMSS_VERIFY_ONLY
  236. if (key->sk != NULL) {
  237. ForceZero(key->sk, key->sk_len);
  238. XFREE(key->sk, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  239. key->sk = NULL;
  240. key->sk_len = 0;
  241. }
  242. #endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */
  243. ForceZero(key, sizeof(XmssKey));
  244. key->state = WC_XMSS_STATE_FREED;
  245. return;
  246. }
  247. #ifndef WOLFSSL_XMSS_VERIFY_ONLY
  248. /* Sets the XMSS write private key callback.
  249. *
  250. * The callback must be able to write/update the private key to
  251. * non-volatile storage.
  252. *
  253. * key [in] The XMSS key.
  254. * write_cb [in] The write private key callback.
  255. *
  256. * returns 0 on success.
  257. * returns BAD_FUNC_ARG when a parameter is NULL.
  258. * returns -1 on failure.
  259. * */
  260. int wc_XmssKey_SetWriteCb(XmssKey * key, write_private_key_cb write_cb)
  261. {
  262. if (key == NULL || write_cb == NULL) {
  263. return BAD_FUNC_ARG;
  264. }
  265. /* Changing the write callback of an already working key is forbidden. */
  266. if (key->state == WC_XMSS_STATE_OK) {
  267. WOLFSSL_MSG("error: wc_XmssKey_SetWriteCb: key in use");
  268. return -1;
  269. }
  270. key->write_private_key = write_cb;
  271. return 0;
  272. }
  273. /* Sets the XMSS read private key callback.
  274. *
  275. * The callback must be able to read the private key from
  276. * non-volatile storage.
  277. *
  278. * key [in] The XMSS key.
  279. * read_cb [in] The read private key callback.
  280. *
  281. * returns 0 on success.
  282. * returns BAD_FUNC_ARG when a parameter is NULL.
  283. * returns -1 on failure.
  284. * */
  285. int wc_XmssKey_SetReadCb(XmssKey * key, read_private_key_cb read_cb)
  286. {
  287. if (key == NULL || read_cb == NULL) {
  288. return BAD_FUNC_ARG;
  289. }
  290. /* Changing the read callback of an already working key is forbidden. */
  291. if (key->state == WC_XMSS_STATE_OK) {
  292. WOLFSSL_MSG("error: wc_XmssKey_SetReadCb: key in use");
  293. return -1;
  294. }
  295. key->read_private_key = read_cb;
  296. return 0;
  297. }
  298. /* Sets the XMSS context to be used by write and read callbacks.
  299. *
  300. * E.g. this could be a filename if the callbacks write/read to file.
  301. *
  302. * key [in] The XMSS key.
  303. * context [in] The context pointer.
  304. *
  305. * returns 0 on success.
  306. * returns BAD_FUNC_ARG when a parameter is NULL.
  307. * returns -1 on failure.
  308. * */
  309. int wc_XmssKey_SetContext(XmssKey * key, void * context)
  310. {
  311. if (key == NULL || context == NULL) {
  312. return BAD_FUNC_ARG;
  313. }
  314. /* Setting context of an already working key is forbidden. */
  315. if (key->state == WC_XMSS_STATE_OK) {
  316. WOLFSSL_MSG("error: wc_XmssKey_SetContext: key in use");
  317. return -1;
  318. }
  319. key->context = context;
  320. return 0;
  321. }
  322. /* Allocates the XMSS secret key (sk) array.
  323. *
  324. * The XMSS/XMSS^MT secret key length is a function of the
  325. * parameters, and can't be allocated until the param string
  326. * has been set with SetParamStr.
  327. *
  328. * This is only called by MakeKey() and Reload().
  329. *
  330. * Note: the XMSS sk array is force zeroed after every use.
  331. *
  332. * key [in] The XMSS key.
  333. *
  334. * returns 0 on success.
  335. * returns BAD_FUNC_ARG when a parameter is NULL.
  336. * returns -1 on failure.
  337. * */
  338. static int wc_XmssKey_AllocSk(XmssKey* key)
  339. {
  340. int ret = 0;
  341. if (key == NULL) {
  342. return BAD_FUNC_ARG;
  343. }
  344. if (key->sk != NULL) {
  345. WOLFSSL_MSG("error: XMSS secret key already exists");
  346. return -1;
  347. }
  348. /* The XMSS/XMSS^MT secret key length is a function of the
  349. * parameters. Therefore can't allocate this until param
  350. * string has been set. */
  351. ret = wc_XmssKey_GetPrivLen(key, &key->sk_len);
  352. if (ret != 0 || key->sk_len <= 0) {
  353. WOLFSSL_MSG("error: wc_XmssKey_GetPrivLen failed");
  354. return -1;
  355. }
  356. key->sk = (unsigned char *)XMALLOC(key->sk_len, NULL,
  357. DYNAMIC_TYPE_TMP_BUFFER);
  358. if (key->sk == NULL) {
  359. WOLFSSL_MSG("error: malloc XMSS key->sk failed");
  360. return -1;
  361. }
  362. ForceZero(key->sk, key->sk_len);
  363. return 0;
  364. }
  365. /* Make the XMSS/XMSS^MT private/public key pair. The key must have its parameters
  366. * set before calling this.
  367. *
  368. * Write/read callbacks, and context data, must be set prior.
  369. * Key must have parameters set.
  370. *
  371. * This function and Reload() are the only functions that allocate
  372. * key->sk array. wc_XmssKey_FreeKey is the only function that
  373. * deallocates key->sk.
  374. *
  375. * key [in] The XMSS key to make.
  376. * rng [in] Initialized WC_RNG pointer.
  377. *
  378. * returns 0 on success.
  379. * returns BAD_FUNC_ARG when a parameter is NULL.
  380. * returns -1 on verify fail.
  381. * */
  382. int wc_XmssKey_MakeKey(XmssKey* key, WC_RNG * rng)
  383. {
  384. int ret = 0;
  385. enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE;
  386. if (key == NULL || rng == NULL) {
  387. return BAD_FUNC_ARG;
  388. }
  389. if (key->state != WC_XMSS_STATE_PARMSET) {
  390. WOLFSSL_MSG("error: XmssKey not ready for generation");
  391. return -1;
  392. }
  393. if (key->write_private_key == NULL || key->read_private_key == NULL) {
  394. WOLFSSL_MSG("error: XmssKey write/read callbacks are not set");
  395. return -1;
  396. }
  397. if (key->context == NULL) {
  398. WOLFSSL_MSG("error: XmssKey context is not set");
  399. return -1;
  400. }
  401. /* Allocate sk array. */
  402. ret = wc_XmssKey_AllocSk(key);
  403. if (ret != 0) {
  404. return ret;
  405. }
  406. xmssRng = rng;
  407. /* Finally make the secret public key pair. Immediately write it to NV
  408. * storage and then clear from memory. */
  409. if (key->is_xmssmt) {
  410. ret = xmssmt_keypair(key->pk, key->sk, key->oid);
  411. }
  412. else {
  413. ret = xmss_keypair(key->pk, key->sk, key->oid);
  414. }
  415. if (ret == 0) {
  416. cb_rc = key->write_private_key(key->sk, key->sk_len, key->context);
  417. }
  418. ForceZero(key->sk, key->sk_len);
  419. if (ret != 0) {
  420. WOLFSSL_MSG("error: XMSS keypair failed");
  421. key->state = WC_XMSS_STATE_BAD;
  422. return -1;
  423. }
  424. if (cb_rc != WC_XMSS_RC_SAVED_TO_NV_MEMORY) {
  425. WOLFSSL_MSG("error: XMSS write to NV storage failed");
  426. key->state = WC_XMSS_STATE_BAD;
  427. return -1;
  428. }
  429. key->state = WC_XMSS_STATE_OK;
  430. return 0;
  431. }
  432. /* This function allocates the secret key buffer, and does a
  433. * quick sanity check to verify the secret key is readable
  434. * from NV storage, and then force zeros the key from memory.
  435. *
  436. * On success it sets the key state to OK.
  437. *
  438. * Use this function to resume signing with an already existing
  439. * XMSS key pair.
  440. *
  441. * Write/read callbacks, and context data, must be set prior.
  442. * Key must have parameters set.
  443. *
  444. * Returns 0 on success.
  445. *
  446. * This function and MakeKey are the only functions that allocate
  447. * key->sk array. wc_XmssKey_FreeKey is the only function that
  448. * deallocates key->sk.
  449. *
  450. * key [in] XMSS key to load.
  451. *
  452. * returns 0 on success.
  453. * returns BAD_FUNC_ARG when a parameter is NULL.
  454. * returns -1 on load fail.
  455. * */
  456. int wc_XmssKey_Reload(XmssKey * key)
  457. {
  458. int ret = 0;
  459. enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE;
  460. if (key == NULL) {
  461. return BAD_FUNC_ARG;
  462. }
  463. if (key->state != WC_XMSS_STATE_PARMSET) {
  464. WOLFSSL_MSG("error: XmssKey not ready for reload");
  465. return -1;
  466. }
  467. if (key->write_private_key == NULL || key->read_private_key == NULL) {
  468. WOLFSSL_MSG("error: XmssKey write/read callbacks are not set");
  469. return -1;
  470. }
  471. if (key->context == NULL) {
  472. WOLFSSL_MSG("error: XmssKey context is not set");
  473. return -1;
  474. }
  475. /* Allocate sk array. */
  476. ret = wc_XmssKey_AllocSk(key);
  477. if (ret != 0) {
  478. return ret;
  479. }
  480. /* Read the current secret key from NV storage. Force clear it
  481. * immediately. This is just to sanity check the secret key
  482. * is readable from permanent storage. */
  483. cb_rc = key->read_private_key(key->sk, key->sk_len, key->context);
  484. ForceZero(key->sk, key->sk_len);
  485. if (cb_rc != WC_XMSS_RC_READ_TO_MEMORY) {
  486. WOLFSSL_MSG("error: XMSS read from NV storage failed");
  487. key->state = WC_XMSS_STATE_BAD;
  488. return -1;
  489. }
  490. key->state = WC_XMSS_STATE_OK;
  491. return 0;
  492. }
  493. /* Gets the XMSS/XMSS^MT private key length.
  494. *
  495. * Parameters must be set before calling this, as the key size (sk_bytes)
  496. * is a function of the parameters.
  497. *
  498. * Note: the XMSS/XMSS^MT private key format is implementation specific,
  499. * and not standardized. Interoperability of XMSS private keys should
  500. * not be expected.
  501. *
  502. * key [in] The XMSS key.
  503. * len [out] The length of the private key in bytes.
  504. *
  505. * returns 0 on success.
  506. * returns BAD_FUNC_ARG when a parameter is NULL.
  507. * returns -1 on sign fail.
  508. * */
  509. int wc_XmssKey_GetPrivLen(const XmssKey * key, word32 * len)
  510. {
  511. if (key == NULL || len == NULL) {
  512. return BAD_FUNC_ARG;
  513. }
  514. if (key->state != WC_XMSS_STATE_OK && key->state != WC_XMSS_STATE_PARMSET) {
  515. /* params.sk_bytes not set yet. */
  516. return -1;
  517. }
  518. *len = XMSS_OID_LEN + (word32) key->params.sk_bytes;
  519. return 0;
  520. }
  521. /* Signs the message using the XMSS secret key, and
  522. * updates the secret key on NV storage.
  523. *
  524. * Both operations must succeed to be considered
  525. * successful.
  526. *
  527. * On success: sets key state to WC_XMSS_STATE_OK.
  528. * On failure: sets key state to WC_XMSS_STATE_BAD
  529. *
  530. * If no signatures are left, sets state to WC_XMSS_STATE_NOSIGS.
  531. */
  532. static void wc_XmssKey_SignUpdate(XmssKey* key, byte * sig, word32 * sigLen,
  533. const byte * msg, int msgLen)
  534. {
  535. int ret = -1;
  536. unsigned long long len = *sigLen;
  537. enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE;
  538. /* Set the key state to bad by default. State is presumed bad
  539. * unless a correct sign and update operation happen together. */
  540. key->state = WC_XMSS_STATE_BAD;
  541. *sigLen = 0;
  542. /* Read the current secret key from NV storage.*/
  543. cb_rc = key->read_private_key(key->sk, key->sk_len, key->context);
  544. if (cb_rc == WC_XMSS_RC_READ_TO_MEMORY) {
  545. /* Read was good. Now sign and update the secret key in memory. */
  546. if (key->is_xmssmt) {
  547. ret = xmssmt_sign(key->sk, sig, &len, msg, msgLen);
  548. }
  549. else {
  550. ret = xmss_sign(key->sk, sig, &len, msg, msgLen);
  551. }
  552. if (ret == 0 && len == key->params.sig_bytes) {
  553. /* The signature succeeded. key->sk is now updated and must be
  554. * committed to NV storage. */
  555. cb_rc = key->write_private_key(key->sk, key->sk_len, key->context);
  556. if (cb_rc == WC_XMSS_RC_SAVED_TO_NV_MEMORY) {
  557. /* key->sk was successfully committed to NV storage. Set the
  558. * key state to OK, and set the sigLen. */
  559. key->state = WC_XMSS_STATE_OK;
  560. *sigLen = (word32) len;
  561. }
  562. else {
  563. /* Write to NV storage failed. Erase the signature from
  564. * memory. */
  565. ForceZero(sig, key->params.sig_bytes);
  566. WOLFSSL_MSG("error: XMSS write_private_key failed");
  567. }
  568. }
  569. else if (ret == -2) {
  570. /* Signature space exhausted. */
  571. key->state = WC_XMSS_STATE_NOSIGS;
  572. WOLFSSL_MSG("error: no XMSS signatures remaining");
  573. }
  574. else {
  575. /* Something failed or inconsistent in signature. Erase the
  576. * signature just to be safe. */
  577. ForceZero(sig, key->params.sig_bytes);
  578. WOLFSSL_MSG("error: XMSS sign failed");
  579. }
  580. }
  581. else {
  582. /* Read from NV storage failed. */
  583. WOLFSSL_MSG("error: XMSS read_private_key failed");
  584. }
  585. /* Force zero the secret key from memory always. */
  586. ForceZero(key->sk, key->sk_len);
  587. return;
  588. }
  589. /* Sign the message using the XMSS secret key.
  590. *
  591. * key [in] XMSS key to use to sign.
  592. * sig [in] Buffer to write signature into.
  593. * sigLen [in/out] On in, size of buffer.
  594. * On out, the length of the signature in bytes.
  595. * msg [in] Message to sign.
  596. * msgLen [in] Length of the message in bytes.
  597. *
  598. * returns 0 on success.
  599. * returns -1 on sign fail.
  600. * returns BAD_FUNC_ARG when a parameter is NULL.
  601. * returns BUFFER_E when sigLen is too small.
  602. */
  603. int wc_XmssKey_Sign(XmssKey* key, byte * sig, word32 * sigLen, const byte * msg,
  604. int msgLen)
  605. {
  606. if (key == NULL || sig == NULL || sigLen == NULL || msg == NULL) {
  607. return BAD_FUNC_ARG;
  608. }
  609. if (msgLen <= 0) {
  610. return BAD_FUNC_ARG;
  611. }
  612. if (*sigLen < key->params.sig_bytes) {
  613. /* Signature buffer too small. */
  614. WOLFSSL_MSG("error: XMSS sig buffer too small");
  615. return BUFFER_E;
  616. }
  617. if (key->state == WC_XMSS_STATE_NOSIGS) {
  618. WOLFSSL_MSG("error: XMSS signatures exhausted");
  619. return -1;
  620. }
  621. else if (key->state != WC_XMSS_STATE_OK) {
  622. /* The key had an error the last time it was used, and we
  623. * can't guarantee its state. */
  624. WOLFSSL_MSG("error: can't sign, XMSS key not in good state");
  625. return -1;
  626. }
  627. if (key->write_private_key == NULL || key->read_private_key == NULL) {
  628. WOLFSSL_MSG("error: XmssKey write/read callbacks are not set");
  629. return -1;
  630. }
  631. if (key->context == NULL) {
  632. WOLFSSL_MSG("error: XmssKey context is not set");
  633. return -1;
  634. }
  635. /* Finally, sign and update the secret key. */
  636. wc_XmssKey_SignUpdate(key, sig, sigLen, msg, msgLen);
  637. return (key->state == WC_XMSS_STATE_OK) ? 0 : -1;
  638. }
  639. #endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY*/
  640. /* Get the XMSS/XMSS^MT public key length. The public key
  641. * is static in size and does not depend on parameters,
  642. * other than the choice of SHA256 as hashing function.
  643. *
  644. * key [in] The XMSS key.
  645. * len [out] The length of the public key.
  646. *
  647. * returns 0 on success.
  648. * returns BAD_FUNC_ARG when a parameter is NULL.
  649. */
  650. int wc_XmssKey_GetPubLen(const XmssKey * key, word32 * len)
  651. {
  652. if (key == NULL || len == NULL) {
  653. return BAD_FUNC_ARG;
  654. }
  655. *len = XMSS_SHA256_PUBLEN;
  656. return 0;
  657. }
  658. /* Export a generated public key and parameter set from one XmssKey
  659. * to another. Use this to prepare a signature verification XmssKey
  660. * that is pub only.
  661. *
  662. * keyDst [out] Destination key for copy.
  663. * keySrc [in] Source key for copy.
  664. *
  665. * returns 0 on success.
  666. * returns BAD_FUNC_ARG when a parameter is NULL.
  667. * */
  668. int wc_XmssKey_ExportPub(XmssKey * keyDst, const XmssKey * keySrc)
  669. {
  670. if (keyDst == NULL || keySrc == NULL) {
  671. return BAD_FUNC_ARG;
  672. }
  673. ForceZero(keyDst, sizeof(XmssKey));
  674. XMEMCPY(keyDst->pk, keySrc->pk, sizeof(keySrc->pk));
  675. keyDst->oid = keySrc->oid;
  676. keyDst->is_xmssmt = keySrc->is_xmssmt;
  677. /* Mark keyDst as verify only, to prevent misuse. */
  678. keyDst->state = WC_XMSS_STATE_VERIFYONLY;
  679. return 0;
  680. }
  681. /* Exports the raw XMSS public key buffer from key to out buffer.
  682. * The out buffer should be large enough to hold the public key, and
  683. * outLen should indicate the size of the buffer.
  684. *
  685. * key [in] XMSS key.
  686. * out [out] Array holding public key.
  687. * outLen [in/out] On in, size of buffer.
  688. * On out, the length of the public key.
  689. *
  690. * returns 0 on success.
  691. * returns -1 on failure.
  692. * returns BAD_FUNC_ARG when a parameter is NULL.
  693. * returns BUFFER_E if array is too small.
  694. * */
  695. int wc_XmssKey_ExportPubRaw(const XmssKey * key, byte * out, word32 * outLen)
  696. {
  697. int ret = 0;
  698. word32 pubLen = 0;
  699. if (key == NULL || out == NULL || outLen == NULL) {
  700. return BAD_FUNC_ARG;
  701. }
  702. ret = wc_XmssKey_GetPubLen(key, &pubLen);
  703. if (ret != 0) {
  704. WOLFSSL_MSG("error: wc_XmssKey_GetPubLen failed");
  705. return -1;
  706. }
  707. if (*outLen < pubLen) {
  708. return BUFFER_E;
  709. }
  710. XMEMCPY(out, key->pk, pubLen);
  711. *outLen = pubLen;
  712. return 0;
  713. }
  714. /* Imports a raw public key buffer from in array to XmssKey key.
  715. *
  716. * The XMSS parameters must be set first with wc_XmssKey_SetParamStr,
  717. * and inLen must match the length returned by wc_XmssKey_GetPubLen.
  718. *
  719. * key [in] XMSS key.
  720. * in [in] Array holding public key.
  721. * inLen [in] Length of array in bytes.
  722. *
  723. * returns 0 on success.
  724. * returns BAD_FUNC_ARG when a parameter is NULL.
  725. * returns BUFFER_E if array is incorrect size.
  726. * returns -1 on failure.
  727. * */
  728. int wc_XmssKey_ImportPubRaw(XmssKey * key, const byte * in, word32 inLen)
  729. {
  730. int ret = 0;
  731. word32 pubLen = 0;
  732. if (key == NULL || in == NULL) {
  733. return BAD_FUNC_ARG;
  734. }
  735. if (key->state != WC_XMSS_STATE_PARMSET) {
  736. /* XMSS key not ready for import. Param str must be set first. */
  737. WOLFSSL_MSG("error: XMSS key not ready for import");
  738. return -1;
  739. }
  740. ret = wc_XmssKey_GetPubLen(key, &pubLen);
  741. if (ret != 0) {
  742. WOLFSSL_MSG("error: wc_XmssKey_GetPubLen failed");
  743. return -1;
  744. }
  745. if (inLen != pubLen) {
  746. /* Something inconsistent. Parameters weren't set, or input
  747. * pub key is wrong.*/
  748. return BUFFER_E;
  749. }
  750. XMEMCPY(key->pk, in, pubLen);
  751. key->state = WC_XMSS_STATE_VERIFYONLY;
  752. return 0;
  753. }
  754. /* Gets the XMSS/XMSS^MT signature length.
  755. *
  756. * Parameters must be set before calling this, as the signature size
  757. * is a function of the parameters.
  758. *
  759. * Note: call this before wc_XmssKey_Sign or Verify so you know the
  760. * length of the required signature buffer.
  761. *
  762. * key [in] XMSS key to use to sign.
  763. * len [out] The length of the signature in bytes.
  764. *
  765. * returns 0 on success.
  766. * returns BAD_FUNC_ARG when a parameter is NULL.
  767. * returns -1 on sign fail.
  768. * */
  769. int wc_XmssKey_GetSigLen(const XmssKey * key, word32 * len)
  770. {
  771. if (key == NULL || len == NULL) {
  772. return BAD_FUNC_ARG;
  773. }
  774. if (key->state != WC_XMSS_STATE_OK && key->state != WC_XMSS_STATE_PARMSET) {
  775. return -1;
  776. }
  777. *len = key->params.sig_bytes;
  778. return 0;
  779. }
  780. /* Verify the signature using the XMSS public key.
  781. *
  782. * Requires that XMSS parameters have been set with
  783. * wc_XmssKey_SetParamStr, and that a public key is available
  784. * from importing or MakeKey().
  785. *
  786. * Call wc_XmssKey_GetSigLen() before this function to determine
  787. * length of the signature buffer.
  788. *
  789. * key [in] XMSS key to use to verify.
  790. * sig [in] Signature to verify.
  791. * sigLen [in] Size of signature in bytes.
  792. * msg [in] Message to verify.
  793. * msgLen [in] Length of the message in bytes.
  794. *
  795. * returns 0 on success.
  796. * returns -1 on verify fail.
  797. * returns BAD_FUNC_ARG when a parameter is NULL.
  798. * returns BUFFER_E when sigLen is too small.
  799. */
  800. int wc_XmssKey_Verify(XmssKey * key, const byte * sig, word32 sigLen,
  801. const byte * msg, int msgLen)
  802. {
  803. int ret = 0;
  804. unsigned long long msg_len = 0;
  805. msg_len = msgLen;
  806. if (key == NULL || sig == NULL || msg == NULL) {
  807. return BAD_FUNC_ARG;
  808. }
  809. if (sigLen < key->params.sig_bytes) {
  810. /* Signature buffer too small. */
  811. return BUFFER_E;
  812. }
  813. if (key->state != WC_XMSS_STATE_OK &&
  814. key->state != WC_XMSS_STATE_VERIFYONLY) {
  815. /* XMSS key not ready for verification. Param str must be
  816. * set first, and Reload() called. */
  817. WOLFSSL_MSG("error: XMSS key not ready for verification");
  818. return -1;
  819. }
  820. if (key->is_xmssmt) {
  821. ret = xmssmt_sign_open(msg, &msg_len, sig, sigLen, key->pk);
  822. }
  823. else {
  824. ret = xmss_sign_open(msg, &msg_len, sig, sigLen, key->pk);
  825. }
  826. if (ret != 0 || (int) msg_len != msgLen) {
  827. WOLFSSL_MSG("error: XMSS verify failed");
  828. return -1;
  829. }
  830. return ret;
  831. }
  832. #endif /* WOLFSSL_HAVE_XMSS */