You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

308 lines
11 KiB

  1. /*
  2. * Generate intermediate test vectors useful to test implementations.
  3. */
  4. // Number of sample vectors to be generated
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include "../fips202.h"
  9. #include "../params.h"
  10. #include "../randombytes.h"
  11. #include "../utils.h"
  12. #include "../wots.h"
  13. #include "../xmss_commons.h"
  14. #include "../xmss_core.h"
  15. #include <sys/random.h>
  16. #include <sys/stat.h>
  17. #include <json.h>
  18. #define MESSAGE_LEN 128u
  19. struct param_t {
  20. uint8_t oid;
  21. const char *name;
  22. const char *hash;
  23. unsigned height;
  24. unsigned n_samples;
  25. };
  26. void sprint_hex(char *sbuf, unsigned char *buf, int len) {
  27. for (int i = 0; i < len; i++) {
  28. sprintf(&sbuf[2*i], "%02X", buf[i]);
  29. }
  30. sbuf[2*len] = '\0';
  31. }
  32. void vectors_keygen(uint32_t oid, json_object *jreq, json_object *jres, uint32_t n_samples) {
  33. xmss_params params;
  34. struct json_object *tc_req, *tcs_req, *tc_res, *tcs_res;
  35. xmss_parse_oid(&params, oid);
  36. unsigned char seed[params.n * 3];
  37. unsigned char pk[params.pk_bytes + XMSS_OID_LEN];
  38. unsigned char sk[params.sk_bytes + XMSS_OID_LEN];
  39. char *sbuf;
  40. unsigned i;
  41. tcs_req = json_object_new_array();
  42. tcs_res = json_object_new_array();
  43. for (i = 0; i < XMSS_OID_LEN; i++) {
  44. pk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF;
  45. sk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF;
  46. }
  47. for (size_t i=0; i<n_samples; i++) {
  48. tc_req = json_object_new_object();
  49. tc_res = json_object_new_object();
  50. randombytes(seed, 3*params.n);
  51. xmssmt_core_seed_keypair(&params, &pk[XMSS_OID_LEN], &sk[XMSS_OID_LEN], seed);
  52. json_object_object_add(tc_req, "tcId", json_object_new_int(i+1));
  53. sbuf = malloc(2*params.n + 1);
  54. sprint_hex(sbuf, seed, params.n);
  55. json_object_object_add(tc_req, "S_XMSS", json_object_new_string(sbuf));
  56. sprint_hex(sbuf, &seed[params.n], params.n);
  57. json_object_object_add(tc_req, "SK_PRF", json_object_new_string(sbuf));
  58. sprint_hex(sbuf, &seed[2*params.n], params.n);
  59. json_object_object_add(tc_req, "I", json_object_new_string(sbuf));
  60. free(sbuf);
  61. json_object_object_add(tc_res, "tcId", json_object_new_int(i+1));
  62. sbuf = malloc(2*(params.pk_bytes + XMSS_OID_LEN) + 1);
  63. sprint_hex(sbuf, pk, params.pk_bytes + XMSS_OID_LEN);
  64. json_object_object_add(tc_res, "publicKey", json_object_new_string(sbuf));
  65. free(sbuf);
  66. sbuf = malloc(2*(params.sk_bytes + XMSS_OID_LEN) + 1);
  67. sprint_hex(sbuf, sk, params.sk_bytes + XMSS_OID_LEN);
  68. json_object_object_add(tc_res, "secretKey", json_object_new_string(sbuf));
  69. free(sbuf);
  70. json_object_array_add(tcs_req,tc_req);
  71. json_object_array_add(tcs_res,tc_res);
  72. }
  73. json_object_object_add(jreq, "tests", tcs_req);
  74. json_object_object_add(jres, "tests", tcs_res);
  75. }
  76. void json_header_keygen(json_object *jobj) {
  77. json_object_object_add(jobj, "vsId", json_object_new_int(0));
  78. json_object_object_add(jobj, "algorithm", json_object_new_string("XMSS"));
  79. json_object_object_add(jobj, "mode", json_object_new_string("keyGen"));
  80. json_object_object_add(jobj, "revision", json_object_new_string("1.0"));
  81. json_object_object_add(jobj, "isSample", json_object_new_boolean(1));
  82. }
  83. void keygen_KAT(const struct param_t *h) {
  84. struct json_object *jres, *jreq, *tgs_req, *tgs_res, *tg_req, *tg_res;
  85. char buf[256];
  86. jreq = json_object_new_object();
  87. jres = json_object_new_object();
  88. json_header_keygen(jreq);
  89. json_header_keygen(jres);
  90. tgs_req = json_object_new_array();
  91. tgs_res = json_object_new_array();
  92. tg_req = json_object_new_object();
  93. tg_res = json_object_new_object();
  94. // Request file
  95. json_object_object_add(tg_req, "tgId", json_object_new_int(1));
  96. json_object_object_add(tg_req, "testType", json_object_new_string("AFT"));
  97. json_object_object_add(tg_req, "OID", json_object_new_int(h->oid));
  98. json_object_object_add(tg_req, "param", json_object_new_string(h->name));
  99. // Response file
  100. json_object_object_add(tg_res, "tgId", json_object_new_int(1));
  101. json_object_object_add(tg_req, "OID", json_object_new_int(h->oid));
  102. vectors_keygen(h->oid, tg_req, tg_res, h->n_samples);
  103. json_object_array_add(tgs_req, tg_req);
  104. json_object_array_add(tgs_res, tg_res);
  105. json_object_object_add(jreq, "testGroups", tgs_req);
  106. json_object_object_add(jres, "testGroups", tgs_res);
  107. sprintf(buf, "XMSS-%s-%s-H%u", "keyGen", h->hash, h->height);
  108. mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
  109. sprintf(buf, "XMSS-%s-%s-H%u/%s", "keyGen", h->hash, h->height, "prompt.json");
  110. json_object_to_file_ext(buf, jreq, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
  111. sprintf(buf, "XMSS-%s-%s-H%u/%s", "keyGen", h->hash, h->height, "expectedResults.json");
  112. json_object_to_file_ext(buf, jres, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
  113. json_object_put(jres);
  114. json_object_put(jreq);
  115. }
  116. void json_header_siggen(json_object *jobj) {
  117. json_object_object_add(jobj, "vsId", json_object_new_int(0));
  118. json_object_object_add(jobj, "algorithm", json_object_new_string("XMSS"));
  119. json_object_object_add(jobj, "mode", json_object_new_string("sigGen"));
  120. json_object_object_add(jobj, "revision", json_object_new_string("1.0"));
  121. json_object_object_add(jobj, "isSample", json_object_new_boolean(1));
  122. }
  123. void vectors_siggen(uint32_t oid, unsigned char *sk, json_object *jreq, json_object *jres, uint32_t n_samples) {
  124. xmss_params params;
  125. struct json_object *tc_req, *tcs_req, *tc_res, *tcs_res;
  126. xmss_parse_oid(&params, oid);
  127. unsigned char sm[params.sig_bytes + MESSAGE_LEN];
  128. unsigned long long smlen = 0;
  129. unsigned char msg[MESSAGE_LEN];
  130. unsigned q;
  131. unsigned height = 1u << (params.full_height);
  132. char *sbuf;
  133. tcs_req = json_object_new_array();
  134. tcs_res = json_object_new_array();
  135. for (size_t i=0; i<n_samples; i++) {
  136. tc_req = json_object_new_object();
  137. tc_res = json_object_new_object();
  138. randombytes(msg, MESSAGE_LEN);
  139. randombytes((void*)&q, sizeof(q));
  140. q = q % height;
  141. smlen = 0;
  142. ull_to_bytes(sk, params.index_bytes, q);
  143. xmss_core_sign(&params, sk, sm, &smlen, msg, MESSAGE_LEN);
  144. json_object_object_add(tc_res, "tcId", json_object_new_int(i+1));
  145. json_object_object_add(tc_req, "tcId", json_object_new_int(i+1));
  146. sbuf = malloc(2*MESSAGE_LEN + 1);
  147. sprint_hex(sbuf, msg, MESSAGE_LEN);
  148. json_object_object_add(tc_req, "message", json_object_new_string(sbuf));
  149. free(sbuf);
  150. sbuf = malloc(2*smlen + 1);
  151. sprint_hex(sbuf, sm, smlen);
  152. json_object_object_add(tc_res, "signature", json_object_new_string(sbuf));
  153. free(sbuf);
  154. json_object_object_add(tc_req, "q", json_object_new_int(q));
  155. json_object_array_add(tcs_req, tc_req);
  156. json_object_array_add(tcs_res, tc_res);
  157. }
  158. json_object_object_add(jreq, "tests", tcs_req);
  159. json_object_object_add(jres, "tests", tcs_res);
  160. }
  161. void siggen_KAT(const struct param_t *h) {
  162. xmss_params params;
  163. struct json_object *jres, *jreq, *tgs_req, *tgs_res, *tg_req, *tg_res;
  164. xmss_parse_oid(&params, h->oid);
  165. char buf[256], *sbuf;
  166. unsigned char seed[params.n * 3];
  167. unsigned char pk[params.pk_bytes + XMSS_OID_LEN];
  168. unsigned char sk[params.sk_bytes + XMSS_OID_LEN];
  169. size_t i;
  170. jreq = json_object_new_object();
  171. jres = json_object_new_object();
  172. json_header_siggen(jreq);
  173. json_header_siggen(jres);
  174. tgs_req = json_object_new_array();
  175. tgs_res = json_object_new_array();
  176. tg_req = json_object_new_object();
  177. tg_res = json_object_new_object();
  178. // Store key OIDs
  179. for (i = 0; i < XMSS_OID_LEN; i++) {
  180. pk[XMSS_OID_LEN - i - 1] = (h->oid >> (8 * i)) & 0xFF;
  181. sk[XMSS_OID_LEN - i - 1] = (h->oid >> (8 * i)) & 0xFF;
  182. }
  183. // Request file
  184. json_object_object_add(tg_req, "tgId", json_object_new_int(1));
  185. json_object_object_add(tg_req, "testType", json_object_new_string("AFT"));
  186. json_object_object_add(tg_req, "OID", json_object_new_int(h->oid));
  187. json_object_object_add(tg_req, "param", json_object_new_string(h->name));
  188. // Response file
  189. json_object_object_add(tg_res, "tgId", json_object_new_int(1));
  190. json_object_object_add(tg_res, "OID", json_object_new_int(h->oid));
  191. randombytes(seed, 3*params.n);
  192. xmssmt_core_seed_keypair(&params, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN, seed);
  193. sbuf = malloc(2*params.n + 1);
  194. sprint_hex(sbuf, seed, params.n);
  195. json_object_object_add(tg_req, "S_XMSS", json_object_new_string(sbuf));
  196. sprint_hex(sbuf, &seed[params.n], params.n);
  197. json_object_object_add(tg_req, "SK_PRF", json_object_new_string(sbuf));
  198. sprint_hex(sbuf, &seed[2*params.n], params.n);
  199. json_object_object_add(tg_req, "I", json_object_new_string(sbuf));
  200. free(sbuf);
  201. sbuf = malloc(2*params.n + 1);
  202. // Store 'root' from the public key (same as in the secret key)
  203. sprint_hex(sbuf, pk + XMSS_OID_LEN, params.n);
  204. json_object_object_add(tg_req, "PK_root", json_object_new_string(sbuf));
  205. free(sbuf);
  206. sbuf = malloc(2*(params.pk_bytes + XMSS_OID_LEN) + 1);
  207. sprint_hex(sbuf, pk, params.pk_bytes + XMSS_OID_LEN);
  208. json_object_object_add(tg_res, "publicKey", json_object_new_string(sbuf));
  209. free(sbuf);
  210. vectors_siggen(h->oid, sk + XMSS_OID_LEN, tg_req, tg_res, h->n_samples);
  211. json_object_array_add(tgs_req, tg_req);
  212. json_object_array_add(tgs_res, tg_res);
  213. json_object_object_add(jreq, "testGroups", tgs_req);
  214. json_object_object_add(jres, "testGroups", tgs_res);
  215. sprintf(buf, "XMSS-%s-%s-H%u", "sigGen", h->hash, h->height);
  216. mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
  217. sprintf(buf, "XMSS-%s-%s-H%u/%s", "sigGen", h->hash, h->height, "prompt.json");
  218. json_object_to_file_ext(buf, jreq, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
  219. sprintf(buf, "XMSS-%s-%s-H%u/%s", "sigGen", h->hash, h->height, "expectedResults.json");
  220. json_object_to_file_ext(buf, jres, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
  221. json_object_put(jreq);
  222. json_object_put(jres);
  223. }
  224. int main() {
  225. const struct param_t OIDs[] = {
  226. {0x01, "XMSS-SHA2_10_256", "SHA256-N32", 10, 10}, // H10
  227. {0x0D, "XMSS-SHA2_10_192", "SHA256-N24", 10, 10}, // H10
  228. {0x10, "XMSS-SHAKE256_10_256", "SHAKE256-N32", 10, 10}, // H10
  229. {0x13, "XMSS-SHAKE256_10_192", "SHAKE256-N24", 10, 10}, // H10
  230. {0x02, "XMSS-SHA2_16_256", "SHA256-N32", 16, 5}, // H16
  231. {0x0E, "XMSS-SHA2_16_192", "SHA256-N24", 16, 5}, // H16
  232. {0x11, "XMSS-SHAKE256_16_256", "SHAKE256-N32", 16, 5}, // H16
  233. {0x14, "XMSS-SHAKE256_16_192", "SHAKE256-N24", 16, 5}, // H16
  234. {0x03, "XMSS-SHA2_20_256", "SHA256-N32", 20, 3}, // H20
  235. {0x0F, "XMSS-SHA2_20_192", "SHA256-N24", 20, 3}, // H20
  236. {0x12, "XMSS-SHAKE256_20_256", "SHAKE256-N32", 20, 3}, // H20
  237. {0x15, "XMSS-SHAKE256_20_192", "SHAKE256-N24", 20, 3} // H20
  238. };
  239. for (size_t i=0; i<sizeof(OIDs)/sizeof(OIDs[0]); i++) {
  240. keygen_KAT(&OIDs[i]);
  241. siggen_KAT(&OIDs[i]);
  242. }
  243. }