dilithium.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. /* dilithium.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. /* Based on ed448.c and Reworked for Dilithium by Anthony Hu. */
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. /* in case user set HAVE_PQC there */
  26. #include <wolfssl/wolfcrypt/settings.h>
  27. #include <wolfssl/wolfcrypt/asn.h>
  28. #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
  29. #ifdef HAVE_LIBOQS
  30. #include <oqs/oqs.h>
  31. #endif
  32. #include <wolfssl/wolfcrypt/dilithium.h>
  33. #include <wolfssl/wolfcrypt/error-crypt.h>
  34. #ifdef NO_INLINE
  35. #include <wolfssl/wolfcrypt/misc.h>
  36. #else
  37. #define WOLFSSL_MISC_INCLUDED
  38. #include <wolfcrypt/src/misc.c>
  39. #endif
  40. /* Sign the message using the dilithium private key.
  41. *
  42. * in [in] Message to sign.
  43. * inLen [in] Length of the message in bytes.
  44. * out [in] Buffer to write signature into.
  45. * outLen [in/out] On in, size of buffer.
  46. * On out, the length of the signature in bytes.
  47. * key [in] Dilithium key to use when signing
  48. * returns BAD_FUNC_ARG when a parameter is NULL or public key not set,
  49. * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_SIG_SIZE,
  50. * 0 otherwise.
  51. */
  52. int wc_dilithium_sign_msg(const byte* in, word32 inLen,
  53. byte* out, word32 *outLen,
  54. dilithium_key* key)
  55. {
  56. int ret = 0;
  57. #ifdef HAVE_LIBOQS
  58. OQS_SIG *oqssig = NULL;
  59. size_t localOutLen = 0;
  60. /* sanity check on arguments */
  61. if ((in == NULL) || (out == NULL) || (outLen == NULL) || (key == NULL)) {
  62. ret = BAD_FUNC_ARG;
  63. }
  64. if ((ret == 0) && (!key->prvKeySet)) {
  65. ret = BAD_FUNC_ARG;
  66. }
  67. if (ret == 0) {
  68. if (key->level == 2) {
  69. oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_2);
  70. }
  71. else if (key->level == 3) {
  72. oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_3);
  73. }
  74. else if (key->level == 5) {
  75. oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_5);
  76. }
  77. else {
  78. ret = SIG_TYPE_E;
  79. }
  80. }
  81. /* check and set up out length */
  82. if (ret == 0) {
  83. if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_SIG_SIZE)) {
  84. *outLen = DILITHIUM_LEVEL2_SIG_SIZE;
  85. ret = BUFFER_E;
  86. }
  87. else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_SIG_SIZE)) {
  88. *outLen = DILITHIUM_LEVEL3_SIG_SIZE;
  89. ret = BUFFER_E;
  90. }
  91. else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_SIG_SIZE)) {
  92. *outLen = DILITHIUM_LEVEL5_SIG_SIZE;
  93. ret = BUFFER_E;
  94. }
  95. localOutLen = *outLen;
  96. }
  97. if ((ret == 0) &&
  98. (OQS_SIG_sign(oqssig, out, &localOutLen, in, inLen, key->k)
  99. == OQS_ERROR)) {
  100. ret = BAD_FUNC_ARG;
  101. }
  102. if (ret == 0) {
  103. *outLen = (word32)localOutLen;
  104. }
  105. if (oqssig != NULL) {
  106. OQS_SIG_free(oqssig);
  107. }
  108. #else
  109. ret = NOT_COMPILED_IN;
  110. #endif
  111. return ret;
  112. }
  113. /* Verify the message using the dilithium public key.
  114. *
  115. * sig [in] Signature to verify.
  116. * sigLen [in] Size of signature in bytes.
  117. * msg [in] Message to verify.
  118. * msgLen [in] Length of the message in bytes.
  119. * res [out] *res is set to 1 on successful verification.
  120. * key [in] Dilithium key to use to verify.
  121. * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and
  122. * BUFFER_E when sigLen is less than DILITHIUM_LEVEL2_SIG_SIZE,
  123. * 0 otherwise.
  124. */
  125. int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
  126. word32 msgLen, int* res, dilithium_key* key)
  127. {
  128. int ret = 0;
  129. #ifdef HAVE_LIBOQS
  130. OQS_SIG *oqssig = NULL;
  131. if (key == NULL || sig == NULL || msg == NULL || res == NULL) {
  132. ret = BAD_FUNC_ARG;
  133. }
  134. if ((ret == 0) && (!key->pubKeySet)) {
  135. ret = BAD_FUNC_ARG;
  136. }
  137. if (ret == 0) {
  138. if (key->level == 2) {
  139. oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_2);
  140. }
  141. else if (key->level == 3) {
  142. oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_3);
  143. }
  144. else if (key->level == 5) {
  145. oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_5);
  146. }
  147. else {
  148. ret = SIG_TYPE_E;
  149. }
  150. }
  151. if ((ret == 0) &&
  152. (OQS_SIG_verify(oqssig, msg, msgLen, sig, sigLen, key->p)
  153. == OQS_ERROR)) {
  154. ret = SIG_VERIFY_E;
  155. }
  156. if (ret == 0) {
  157. *res = 1;
  158. }
  159. if (oqssig != NULL) {
  160. OQS_SIG_free(oqssig);
  161. }
  162. #else
  163. ret = NOT_COMPILED_IN;
  164. #endif
  165. return ret;
  166. }
  167. /* Initialize the dilithium private/public key.
  168. *
  169. * key [in] Dilithium key.
  170. * returns BAD_FUNC_ARG when key is NULL
  171. */
  172. int wc_dilithium_init(dilithium_key* key)
  173. {
  174. if (key == NULL) {
  175. return BAD_FUNC_ARG;
  176. }
  177. ForceZero(key, sizeof(key));
  178. return 0;
  179. }
  180. /* Set the level of the dilithium private/public key.
  181. *
  182. * key [out] Dilithium key.
  183. * level [in] Either 2,3 or 5.
  184. * returns BAD_FUNC_ARG when key is NULL or level is a bad values.
  185. */
  186. int wc_dilithium_set_level(dilithium_key* key, byte level)
  187. {
  188. if (key == NULL) {
  189. return BAD_FUNC_ARG;
  190. }
  191. if (level != 2 && level != 3 && level != 5) {
  192. return BAD_FUNC_ARG;
  193. }
  194. key->level = level;
  195. key->pubKeySet = 0;
  196. key->prvKeySet = 0;
  197. return 0;
  198. }
  199. /* Get the level of the dilithium private/public key.
  200. *
  201. * key [in] Dilithium key.
  202. * level [out] The level.
  203. * returns BAD_FUNC_ARG when key is NULL or level has not been set.
  204. */
  205. int wc_dilithium_get_level(dilithium_key* key, byte* level)
  206. {
  207. if (key == NULL || level == NULL) {
  208. return BAD_FUNC_ARG;
  209. }
  210. if (key->level != 2 && key->level != 3 && key->level != 5) {
  211. return BAD_FUNC_ARG;
  212. }
  213. *level = key->level;
  214. return 0;
  215. }
  216. /* Clears the dilithium key data
  217. *
  218. * key [in] Dilithium key.
  219. */
  220. void wc_dilithium_free(dilithium_key* key)
  221. {
  222. if (key != NULL) {
  223. ForceZero(key, sizeof(key));
  224. }
  225. }
  226. /* Export the dilithium public key.
  227. *
  228. * key [in] Dilithium public key.
  229. * out [in] Array to hold public key.
  230. * outLen [in/out] On in, the number of bytes in array.
  231. * On out, the number bytes put into array.
  232. * returns BAD_FUNC_ARG when a parameter is NULL,
  233. * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_PUB_KEY_SIZE,
  234. * 0 otherwise.
  235. */
  236. int wc_dilithium_export_public(dilithium_key* key,
  237. byte* out, word32* outLen)
  238. {
  239. /* sanity check on arguments */
  240. if ((key == NULL) || (out == NULL) || (outLen == NULL)) {
  241. return BAD_FUNC_ARG;
  242. }
  243. if ((key->level != 1) && (key->level != 5)) {
  244. return BAD_FUNC_ARG;
  245. }
  246. if (!key->pubKeySet) {
  247. return BAD_FUNC_ARG;
  248. }
  249. /* check and set up out length */
  250. if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_PUB_KEY_SIZE)) {
  251. *outLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE;
  252. return BUFFER_E;
  253. }
  254. else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_PUB_KEY_SIZE)) {
  255. *outLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE;
  256. return BUFFER_E;
  257. }
  258. else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_PUB_KEY_SIZE)) {
  259. *outLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE;
  260. return BUFFER_E;
  261. }
  262. if (key->level == 2) {
  263. *outLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE;
  264. XMEMCPY(out, key->p, DILITHIUM_LEVEL2_PUB_KEY_SIZE);
  265. }
  266. else if (key->level == 3) {
  267. *outLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE;
  268. XMEMCPY(out, key->p, DILITHIUM_LEVEL3_PUB_KEY_SIZE);
  269. }
  270. else if (key->level == 5) {
  271. *outLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE;
  272. XMEMCPY(out, key->p, DILITHIUM_LEVEL5_PUB_KEY_SIZE);
  273. }
  274. return 0;
  275. }
  276. /* Import a dilithium public key from a byte array.
  277. * Public key encoded in big-endian.
  278. *
  279. * in [in] Array holding public key.
  280. * inLen [in] Number of bytes of data in array.
  281. * key [in] Dilithium public key.
  282. * returns BAD_FUNC_ARG when a parameter is NULL or key format is not supported,
  283. * 0 otherwise.
  284. */
  285. int wc_dilithium_import_public(const byte* in, word32 inLen,
  286. dilithium_key* key)
  287. {
  288. /* sanity check on arguments */
  289. if ((in == NULL) || (key == NULL)) {
  290. return BAD_FUNC_ARG;
  291. }
  292. if ((key->level != 2) && (key->level != 3) && (key->level != 5)) {
  293. return BAD_FUNC_ARG;
  294. }
  295. if ((key->level == 2) && (inLen != DILITHIUM_LEVEL2_PUB_KEY_SIZE)) {
  296. return BAD_FUNC_ARG;
  297. }
  298. else if ((key->level == 3) && (inLen != DILITHIUM_LEVEL3_PUB_KEY_SIZE)) {
  299. return BAD_FUNC_ARG;
  300. }
  301. else if ((key->level == 5) && (inLen != DILITHIUM_LEVEL5_PUB_KEY_SIZE)) {
  302. return BAD_FUNC_ARG;
  303. }
  304. XMEMCPY(key->p, in, inLen);
  305. key->pubKeySet = 1;
  306. return 0;
  307. }
  308. static int parse_private_key(const byte* priv, word32 privSz,
  309. byte** out, word32 *outSz,
  310. dilithium_key* key) {
  311. word32 idx = 0;
  312. int ret = 0;
  313. int length = 0;
  314. /* sanity check on arguments */
  315. if ((priv == NULL) || (key == NULL)) {
  316. return BAD_FUNC_ARG;
  317. }
  318. if ((key->level != 2) && (key->level != 3) && (key->level != 5)) {
  319. return BAD_FUNC_ARG;
  320. }
  321. /* At this point, it is still a PKCS8 private key. */
  322. if ((ret = ToTraditionalInline(priv, &idx, privSz)) < 0) {
  323. return ret;
  324. }
  325. /* Now it is a octet_string(concat(priv,pub)) */
  326. if ((ret = GetOctetString(priv, &idx, &length, privSz)) < 0) {
  327. return ret;
  328. }
  329. *out = (byte *)priv + idx;
  330. *outSz = privSz - idx;
  331. /* And finally it is concat(priv,pub). Key size check. */
  332. if ((key->level == 2) && (*outSz != DILITHIUM_LEVEL2_KEY_SIZE +
  333. DILITHIUM_LEVEL2_PUB_KEY_SIZE)) {
  334. return BAD_FUNC_ARG;
  335. }
  336. else if ((key->level == 3) && (*outSz != DILITHIUM_LEVEL3_KEY_SIZE +
  337. DILITHIUM_LEVEL3_PUB_KEY_SIZE)) {
  338. return BAD_FUNC_ARG;
  339. }
  340. else if ((key->level == 5) && (*outSz != DILITHIUM_LEVEL5_KEY_SIZE +
  341. DILITHIUM_LEVEL5_PUB_KEY_SIZE)) {
  342. return BAD_FUNC_ARG;
  343. }
  344. return 0;
  345. }
  346. /* Import a dilithium private key from a byte array.
  347. *
  348. * priv [in] Array holding private key.
  349. * privSz [in] Number of bytes of data in array.
  350. * key [in] Dilithium private key.
  351. * returns BAD_FUNC_ARG when a parameter is NULL or privSz is less than
  352. * DILITHIUM_LEVEL2_KEY_SIZE,
  353. * 0 otherwise.
  354. */
  355. int wc_dilithium_import_private_only(const byte* priv, word32 privSz,
  356. dilithium_key* key)
  357. {
  358. int ret = 0;
  359. byte *newPriv = NULL;
  360. word32 newPrivSz = 0;
  361. if ((ret = parse_private_key(priv, privSz, &newPriv, &newPrivSz, key))
  362. != 0) {
  363. return ret;
  364. }
  365. if (key->level == 2) {
  366. XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL2_KEY_SIZE);
  367. }
  368. else if (key->level == 3) {
  369. XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL3_KEY_SIZE);
  370. }
  371. else if (key->level == 5) {
  372. XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL5_KEY_SIZE);
  373. }
  374. key->prvKeySet = 1;
  375. return 0;
  376. }
  377. /* Import a dilithium private and public keys from byte array(s).
  378. *
  379. * priv [in] Array holding private key or private+public keys
  380. * privSz [in] Number of bytes of data in private key array.
  381. * pub [in] Array holding public key (or NULL).
  382. * pubSz [in] Number of bytes of data in public key array (or 0).
  383. * key [in] Dilithium private/public key.
  384. * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid
  385. * combination of keys/lengths is supplied, 0 otherwise.
  386. */
  387. int wc_dilithium_import_private_key(const byte* priv, word32 privSz,
  388. const byte* pub, word32 pubSz,
  389. dilithium_key* key)
  390. {
  391. int ret = 0;
  392. byte *newPriv = NULL;
  393. word32 newPrivSz = 0;
  394. if ((ret = parse_private_key(priv, privSz, &newPriv, &newPrivSz, key))
  395. != 0) {
  396. return ret;
  397. }
  398. if (pub == NULL) {
  399. if (pubSz != 0) {
  400. return BAD_FUNC_ARG;
  401. }
  402. if ((newPrivSz != DILITHIUM_LEVEL2_PRV_KEY_SIZE) &&
  403. (newPrivSz != DILITHIUM_LEVEL3_PRV_KEY_SIZE) &&
  404. (newPrivSz != DILITHIUM_LEVEL5_PRV_KEY_SIZE)) {
  405. return BAD_FUNC_ARG;
  406. }
  407. if (key->level == 2) {
  408. pub = newPriv + DILITHIUM_LEVEL2_KEY_SIZE;
  409. pubSz = DILITHIUM_LEVEL2_PUB_KEY_SIZE;
  410. }
  411. else if (key->level == 3) {
  412. pub = newPriv + DILITHIUM_LEVEL3_KEY_SIZE;
  413. pubSz = DILITHIUM_LEVEL3_PUB_KEY_SIZE;
  414. }
  415. else if (key->level == 5) {
  416. pub = newPriv + DILITHIUM_LEVEL5_KEY_SIZE;
  417. pubSz = DILITHIUM_LEVEL5_PUB_KEY_SIZE;
  418. }
  419. }
  420. else if ((pubSz != DILITHIUM_LEVEL2_PUB_KEY_SIZE) &&
  421. (pubSz != DILITHIUM_LEVEL3_PUB_KEY_SIZE) &&
  422. (pubSz != DILITHIUM_LEVEL5_PUB_KEY_SIZE)) {
  423. return BAD_FUNC_ARG;
  424. }
  425. /* import public key */
  426. ret = wc_dilithium_import_public(pub, pubSz, key);
  427. if (ret == 0) {
  428. /* make the private key (priv + pub) */
  429. if (key->level == 2) {
  430. XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL2_KEY_SIZE);
  431. }
  432. else if (key->level == 3) {
  433. XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL3_KEY_SIZE);
  434. }
  435. else if (key->level == 5) {
  436. XMEMCPY(key->k, newPriv, DILITHIUM_LEVEL5_KEY_SIZE);
  437. }
  438. key->prvKeySet = 1;
  439. }
  440. return ret;
  441. }
  442. /* Export the dilithium private key.
  443. *
  444. * key [in] Dilithium private key.
  445. * out [in] Array to hold private key.
  446. * outLen [in/out] On in, the number of bytes in array.
  447. * On out, the number bytes put into array.
  448. * returns BAD_FUNC_ARG when a parameter is NULL,
  449. * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_KEY_SIZE,
  450. * 0 otherwise.
  451. */
  452. int wc_dilithium_export_private_only(dilithium_key* key, byte* out,
  453. word32* outLen)
  454. {
  455. /* sanity checks on arguments */
  456. if ((key == NULL) || (out == NULL) || (outLen == NULL)) {
  457. return BAD_FUNC_ARG;
  458. }
  459. if ((key->level != 2) && (key->level != 3) && (key->level != 5)) {
  460. return BAD_FUNC_ARG;
  461. }
  462. /* check and set up out length */
  463. if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_KEY_SIZE)) {
  464. *outLen = DILITHIUM_LEVEL2_KEY_SIZE;
  465. return BUFFER_E;
  466. }
  467. else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_KEY_SIZE)) {
  468. *outLen = DILITHIUM_LEVEL3_KEY_SIZE;
  469. return BUFFER_E;
  470. }
  471. else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_KEY_SIZE)) {
  472. *outLen = DILITHIUM_LEVEL5_KEY_SIZE;
  473. return BUFFER_E;
  474. }
  475. if (key->level == 2) {
  476. *outLen = DILITHIUM_LEVEL2_KEY_SIZE;
  477. }
  478. else if (key->level == 3) {
  479. *outLen = DILITHIUM_LEVEL3_KEY_SIZE;
  480. }
  481. else if (key->level == 5) {
  482. *outLen = DILITHIUM_LEVEL5_KEY_SIZE;
  483. }
  484. XMEMCPY(out, key->k, *outLen);
  485. return 0;
  486. }
  487. /* Export the dilithium private and public key.
  488. *
  489. * key [in] Dilithium private/public key.
  490. * out [in] Array to hold private and public key.
  491. * outLen [in/out] On in, the number of bytes in array.
  492. * On out, the number bytes put into array.
  493. * returns BAD_FUNC_ARG when a parameter is NULL,
  494. * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_PRV_KEY_SIZE,
  495. * 0 otherwise.
  496. */
  497. int wc_dilithium_export_private(dilithium_key* key, byte* out, word32* outLen)
  498. {
  499. /* sanity checks on arguments */
  500. if ((key == NULL) || (out == NULL) || (outLen == NULL)) {
  501. return BAD_FUNC_ARG;
  502. }
  503. if ((key->level != 2) && (key->level != 3) && (key->level != 5)) {
  504. return BAD_FUNC_ARG;
  505. }
  506. if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_PRV_KEY_SIZE)) {
  507. *outLen = DILITHIUM_LEVEL2_PRV_KEY_SIZE;
  508. return BUFFER_E;
  509. }
  510. else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_PRV_KEY_SIZE)) {
  511. *outLen = DILITHIUM_LEVEL3_PRV_KEY_SIZE;
  512. return BUFFER_E;
  513. }
  514. else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_PRV_KEY_SIZE)) {
  515. *outLen = DILITHIUM_LEVEL5_PRV_KEY_SIZE;
  516. return BUFFER_E;
  517. }
  518. if (key->level == 2) {
  519. *outLen = DILITHIUM_LEVEL2_PRV_KEY_SIZE;
  520. XMEMCPY(out, key->k, DILITHIUM_LEVEL2_PRV_KEY_SIZE);
  521. XMEMCPY(out + DILITHIUM_LEVEL2_PRV_KEY_SIZE, key->p,
  522. DILITHIUM_LEVEL2_PUB_KEY_SIZE);
  523. }
  524. else if (key->level == 3) {
  525. *outLen = DILITHIUM_LEVEL3_PRV_KEY_SIZE;
  526. XMEMCPY(out, key->k, DILITHIUM_LEVEL3_PRV_KEY_SIZE);
  527. XMEMCPY(out + DILITHIUM_LEVEL3_PRV_KEY_SIZE, key->p,
  528. DILITHIUM_LEVEL3_PUB_KEY_SIZE);
  529. }
  530. else if (key->level == 5) {
  531. *outLen = DILITHIUM_LEVEL5_PRV_KEY_SIZE;
  532. XMEMCPY(out, key->k, DILITHIUM_LEVEL5_PRV_KEY_SIZE);
  533. XMEMCPY(out + DILITHIUM_LEVEL5_PRV_KEY_SIZE, key->p,
  534. DILITHIUM_LEVEL5_PUB_KEY_SIZE);
  535. }
  536. return 0;
  537. }
  538. /* Export the dilithium private and public key.
  539. *
  540. * key [in] Dilithium private/public key.
  541. * priv [in] Array to hold private key.
  542. * privSz [in/out] On in, the number of bytes in private key array.
  543. * pub [in] Array to hold public key.
  544. * pubSz [in/out] On in, the number of bytes in public key array.
  545. * On out, the number bytes put into array.
  546. * returns BAD_FUNC_ARG when a parameter is NULL,
  547. * BUFFER_E when privSz is less than DILITHIUM_LEVEL2_PRV_KEY_SIZE or pubSz is less
  548. * than DILITHIUM_LEVEL2_PUB_KEY_SIZE,
  549. * 0 otherwise.
  550. */
  551. int wc_dilithium_export_key(dilithium_key* key, byte* priv, word32 *privSz,
  552. byte* pub, word32 *pubSz)
  553. {
  554. int ret = 0;
  555. /* export private part */
  556. ret = wc_dilithium_export_private(key, priv, privSz);
  557. if (ret == 0) {
  558. /* export public part */
  559. ret = wc_dilithium_export_public(key, pub, pubSz);
  560. }
  561. return ret;
  562. }
  563. /* Check the public key of the dilithium key matches the private key.
  564. *
  565. * key [in] Dilithium private/public key.
  566. * returns BAD_FUNC_ARG when key is NULL,
  567. * PUBLIC_KEY_E when the public key is not set or doesn't match,
  568. * other -ve value on hash failure,
  569. * 0 otherwise.
  570. */
  571. int wc_dilithium_check_key(dilithium_key* key)
  572. {
  573. if (key == NULL) {
  574. return BAD_FUNC_ARG;
  575. }
  576. /* Assume everything is fine. */
  577. return 0;
  578. }
  579. /* Returns the size of a dilithium private key.
  580. *
  581. * key [in] Dilithium private/public key.
  582. * returns BAD_FUNC_ARG when key is NULL,
  583. * DILITHIUM_LEVEL2_KEY_SIZE otherwise.
  584. */
  585. int wc_dilithium_size(dilithium_key* key)
  586. {
  587. if (key == NULL) {
  588. return BAD_FUNC_ARG;
  589. }
  590. if (key->level == 2) {
  591. return DILITHIUM_LEVEL2_KEY_SIZE;
  592. }
  593. else if (key->level == 3) {
  594. return DILITHIUM_LEVEL3_KEY_SIZE;
  595. }
  596. else if (key->level == 5) {
  597. return DILITHIUM_LEVEL5_KEY_SIZE;
  598. }
  599. return BAD_FUNC_ARG;
  600. }
  601. /* Returns the size of a dilithium private plus public key.
  602. *
  603. * key [in] Dilithium private/public key.
  604. * returns BAD_FUNC_ARG when key is NULL,
  605. * DILITHIUM_LEVEL2_PRV_KEY_SIZE otherwise.
  606. */
  607. int wc_dilithium_priv_size(dilithium_key* key)
  608. {
  609. if (key == NULL) {
  610. return BAD_FUNC_ARG;
  611. }
  612. if (key->level == 2) {
  613. return DILITHIUM_LEVEL2_PRV_KEY_SIZE;
  614. }
  615. else if (key->level == 3) {
  616. return DILITHIUM_LEVEL3_PRV_KEY_SIZE;
  617. }
  618. else if (key->level == 5) {
  619. return DILITHIUM_LEVEL5_PRV_KEY_SIZE;
  620. }
  621. return BAD_FUNC_ARG;
  622. }
  623. /* Returns the size of a dilithium public key.
  624. *
  625. * key [in] Dilithium private/public key.
  626. * returns BAD_FUNC_ARG when key is NULL,
  627. * DILITHIUM_LEVEL2_PUB_KEY_SIZE otherwise.
  628. */
  629. int wc_dilithium_pub_size(dilithium_key* key)
  630. {
  631. if (key == NULL) {
  632. return BAD_FUNC_ARG;
  633. }
  634. if (key->level == 2) {
  635. return DILITHIUM_LEVEL2_PUB_KEY_SIZE;
  636. }
  637. else if (key->level == 3) {
  638. return DILITHIUM_LEVEL3_PUB_KEY_SIZE;
  639. }
  640. else if (key->level == 5) {
  641. return DILITHIUM_LEVEL5_PUB_KEY_SIZE;
  642. }
  643. return BAD_FUNC_ARG;
  644. }
  645. /* Returns the size of a dilithium signature.
  646. *
  647. * key [in] Dilithium private/public key.
  648. * returns BAD_FUNC_ARG when key is NULL,
  649. * DILITHIUM_LEVEL2_SIG_SIZE otherwise.
  650. */
  651. int wc_dilithium_sig_size(dilithium_key* key)
  652. {
  653. if (key == NULL) {
  654. return BAD_FUNC_ARG;
  655. }
  656. if (key->level == 2) {
  657. return DILITHIUM_LEVEL2_SIG_SIZE;
  658. }
  659. else if (key->level == 3) {
  660. return DILITHIUM_LEVEL3_SIG_SIZE;
  661. }
  662. else if (key->level == 5) {
  663. return DILITHIUM_LEVEL5_SIG_SIZE;
  664. }
  665. return BAD_FUNC_ARG;
  666. }
  667. int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx,
  668. dilithium_key* key, word32 inSz)
  669. {
  670. int ret = 0;
  671. byte privKey[DILITHIUM_MAX_KEY_SIZE], pubKey[DILITHIUM_MAX_PUB_KEY_SIZE];
  672. word32 privKeyLen = (word32)sizeof(privKey);
  673. word32 pubKeyLen = (word32)sizeof(pubKey);
  674. int keytype = 0;
  675. if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) {
  676. return BAD_FUNC_ARG;
  677. }
  678. if (key->level == 2) {
  679. keytype = DILITHIUM_LEVEL2k;
  680. }
  681. else if (key->level == 3) {
  682. keytype = DILITHIUM_LEVEL3k;
  683. }
  684. else if (key->level == 5) {
  685. keytype = DILITHIUM_LEVEL5k;
  686. }
  687. else {
  688. return BAD_FUNC_ARG;
  689. }
  690. ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen,
  691. pubKey, &pubKeyLen, keytype);
  692. if (ret == 0) {
  693. if (pubKeyLen == 0) {
  694. ret = wc_dilithium_import_private_only(input, inSz, key);
  695. }
  696. else {
  697. ret = wc_dilithium_import_private_key(privKey, privKeyLen,
  698. pubKey, pubKeyLen, key);
  699. }
  700. }
  701. return ret;
  702. }
  703. int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx,
  704. dilithium_key* key, word32 inSz)
  705. {
  706. int ret = 0;
  707. byte pubKey[DILITHIUM_MAX_PUB_KEY_SIZE];
  708. word32 pubKeyLen = (word32)sizeof(pubKey);
  709. int keytype = 0;
  710. if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) {
  711. return BAD_FUNC_ARG;
  712. }
  713. if (key->level == 2) {
  714. keytype = DILITHIUM_LEVEL2k;
  715. }
  716. else if (key->level == 3) {
  717. keytype = DILITHIUM_LEVEL3k;
  718. }
  719. else if (key->level == 5) {
  720. keytype = DILITHIUM_LEVEL5k;
  721. }
  722. else {
  723. return BAD_FUNC_ARG;
  724. }
  725. ret = DecodeAsymKeyPublic(input, inOutIdx, inSz, pubKey, &pubKeyLen,
  726. keytype);
  727. if (ret == 0) {
  728. ret = wc_dilithium_import_public(pubKey, pubKeyLen, key);
  729. }
  730. return ret;
  731. }
  732. #ifdef WC_ENABLE_ASYM_KEY_EXPORT
  733. /* Encode the public part of an Dilithium key in DER.
  734. *
  735. * Pass NULL for output to get the size of the encoding.
  736. *
  737. * @param [in] key Dilithium key object.
  738. * @param [out] output Buffer to put encoded data in.
  739. * @param [in] outLen Size of buffer in bytes.
  740. * @param [in] withAlg Whether to use SubjectPublicKeyInfo format.
  741. * @return Size of encoded data in bytes on success.
  742. * @return BAD_FUNC_ARG when key is NULL.
  743. * @return MEMORY_E when dynamic memory allocation failed.
  744. */
  745. int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, word32 inLen,
  746. int withAlg)
  747. {
  748. int ret;
  749. byte pubKey[DILITHIUM_MAX_PUB_KEY_SIZE];
  750. word32 pubKeyLen = (word32)sizeof(pubKey);
  751. int keytype = 0;
  752. if (key == NULL || output == NULL) {
  753. return BAD_FUNC_ARG;
  754. }
  755. if (key->level == 2) {
  756. keytype = DILITHIUM_LEVEL2k;
  757. }
  758. else if (key->level == 3) {
  759. keytype = DILITHIUM_LEVEL3k;
  760. }
  761. else if (key->level == 5) {
  762. keytype = DILITHIUM_LEVEL5k;
  763. }
  764. else {
  765. return BAD_FUNC_ARG;
  766. }
  767. ret = wc_dilithium_export_public(key, pubKey, &pubKeyLen);
  768. if (ret == 0) {
  769. ret = SetAsymKeyDerPublic(pubKey, pubKeyLen, output, inLen, keytype,
  770. withAlg);
  771. }
  772. return ret;
  773. }
  774. #endif
  775. int wc_Dilithium_KeyToDer(dilithium_key* key, byte* output, word32 inLen)
  776. {
  777. if (key == NULL) {
  778. return BAD_FUNC_ARG;
  779. }
  780. if (key->level == 2) {
  781. return SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, key->p,
  782. DILITHIUM_LEVEL2_KEY_SIZE, output, inLen,
  783. DILITHIUM_LEVEL2k);
  784. }
  785. else if (key->level == 3) {
  786. return SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, key->p,
  787. DILITHIUM_LEVEL3_KEY_SIZE, output, inLen,
  788. DILITHIUM_LEVEL3k);
  789. }
  790. else if (key->level == 5) {
  791. return SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, key->p,
  792. DILITHIUM_LEVEL5_KEY_SIZE, output, inLen,
  793. DILITHIUM_LEVEL5k);
  794. }
  795. return BAD_FUNC_ARG;
  796. }
  797. int wc_Dilithium_PrivateKeyToDer(dilithium_key* key, byte* output, word32 inLen)
  798. {
  799. if (key == NULL) {
  800. return BAD_FUNC_ARG;
  801. }
  802. if (key->level == 2) {
  803. return SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, NULL, 0, output,
  804. inLen, DILITHIUM_LEVEL2k);
  805. }
  806. else if (key->level == 3) {
  807. return SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, NULL, 0, output,
  808. inLen, DILITHIUM_LEVEL3k);
  809. }
  810. else if (key->level == 5) {
  811. return SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, NULL, 0, output,
  812. inLen, DILITHIUM_LEVEL5k);
  813. }
  814. return BAD_FUNC_ARG;
  815. }
  816. #endif /* HAVE_PQC && HAVE_DILITHIUM */