PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/test-crypto-pbkdf.c

https://github.com/mstsirkin/qemu
C | 445 lines | 386 code | 28 blank | 31 comment | 9 complexity | 7215e20fa9861fc2231e3ffe1c53cb5d MD5 | raw file
  1. /*
  2. * QEMU Crypto cipher algorithms
  3. *
  4. * Copyright (c) 2015-2016 Red Hat, Inc.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. #include "qemu/osdep.h"
  21. #include "qapi/error.h"
  22. #include "crypto/init.h"
  23. #ifndef _WIN32
  24. #include <sys/resource.h>
  25. #endif
  26. #if ((defined(CONFIG_NETTLE) || defined(CONFIG_GCRYPT)) && \
  27. (defined(_WIN32) || defined(RUSAGE_THREAD)))
  28. #include "crypto/pbkdf.h"
  29. typedef struct QCryptoPbkdfTestData QCryptoPbkdfTestData;
  30. struct QCryptoPbkdfTestData {
  31. const char *path;
  32. QCryptoHashAlgorithm hash;
  33. unsigned int iterations;
  34. const char *key;
  35. size_t nkey;
  36. const char *salt;
  37. size_t nsalt;
  38. const char *out;
  39. size_t nout;
  40. bool slow;
  41. };
  42. /* This test data comes from cryptsetup package
  43. *
  44. * $SRC/lib/crypto_backend/pbkdf2_generic.c
  45. *
  46. * under LGPLv2.1+ license
  47. */
  48. static QCryptoPbkdfTestData test_data[] = {
  49. /* RFC 3962 test data */
  50. {
  51. .path = "/crypto/pbkdf/rfc3962/sha1/iter1",
  52. .hash = QCRYPTO_HASH_ALG_SHA1,
  53. .iterations = 1,
  54. .key = "password",
  55. .nkey = 8,
  56. .salt = "ATHENA.MIT.EDUraeburn",
  57. .nsalt = 21,
  58. .out = "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01"
  59. "\x56\x5a\x11\x22\xb2\x56\x35\x15"
  60. "\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3"
  61. "\x33\xec\xc0\xe2\xe1\xf7\x08\x37",
  62. .nout = 32
  63. },
  64. {
  65. .path = "/crypto/pbkdf/rfc3962/sha1/iter2",
  66. .hash = QCRYPTO_HASH_ALG_SHA1,
  67. .iterations = 2,
  68. .key = "password",
  69. .nkey = 8,
  70. .salt = "ATHENA.MIT.EDUraeburn",
  71. .nsalt = 21,
  72. .out = "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e"
  73. "\x98\x8b\x62\xc7\x3c\xda\x93\x5d"
  74. "\xa0\x53\x78\xb9\x32\x44\xec\x8f"
  75. "\x48\xa9\x9e\x61\xad\x79\x9d\x86",
  76. .nout = 32
  77. },
  78. {
  79. .path = "/crypto/pbkdf/rfc3962/sha1/iter1200a",
  80. .hash = QCRYPTO_HASH_ALG_SHA1,
  81. .iterations = 1200,
  82. .key = "password",
  83. .nkey = 8,
  84. .salt = "ATHENA.MIT.EDUraeburn",
  85. .nsalt = 21,
  86. .out = "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e"
  87. "\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b"
  88. "\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f"
  89. "\x70\x8a\x31\xe2\xe6\x2b\x1e\x13",
  90. .nout = 32
  91. },
  92. {
  93. .path = "/crypto/pbkdf/rfc3962/sha1/iter5",
  94. .hash = QCRYPTO_HASH_ALG_SHA1,
  95. .iterations = 5,
  96. .key = "password",
  97. .nkey = 8,
  98. .salt = "\0224VxxV4\022", /* "\x1234567878563412 */
  99. .nsalt = 8,
  100. .out = "\xd1\xda\xa7\x86\x15\xf2\x87\xe6"
  101. "\xa1\xc8\xb1\x20\xd7\x06\x2a\x49"
  102. "\x3f\x98\xd2\x03\xe6\xbe\x49\xa6"
  103. "\xad\xf4\xfa\x57\x4b\x6e\x64\xee",
  104. .nout = 32
  105. },
  106. {
  107. .path = "/crypto/pbkdf/rfc3962/sha1/iter1200b",
  108. .hash = QCRYPTO_HASH_ALG_SHA1,
  109. .iterations = 1200,
  110. .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  111. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  112. .nkey = 64,
  113. .salt = "pass phrase equals block size",
  114. .nsalt = 29,
  115. .out = "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b"
  116. "\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9"
  117. "\xc5\xec\x59\xf1\xa4\x52\xf5\xcc"
  118. "\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1",
  119. .nout = 32
  120. },
  121. {
  122. .path = "/crypto/pbkdf/rfc3962/sha1/iter1200c",
  123. .hash = QCRYPTO_HASH_ALG_SHA1,
  124. .iterations = 1200,
  125. .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  126. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  127. .nkey = 65,
  128. .salt = "pass phrase exceeds block size",
  129. .nsalt = 30,
  130. .out = "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5"
  131. "\x1b\x10\xe6\xa6\x87\x21\xbe\x61"
  132. "\x1a\x8b\x4d\x28\x26\x01\xdb\x3b"
  133. "\x36\xbe\x92\x46\x91\x5e\xc8\x2a",
  134. .nout = 32
  135. },
  136. {
  137. .path = "/crypto/pbkdf/rfc3962/sha1/iter50",
  138. .hash = QCRYPTO_HASH_ALG_SHA1,
  139. .iterations = 50,
  140. .key = "\360\235\204\236", /* g-clef ("\xf09d849e) */
  141. .nkey = 4,
  142. .salt = "EXAMPLE.COMpianist",
  143. .nsalt = 18,
  144. .out = "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43"
  145. "\xa5\xb8\xbb\x27\x6a\x40\x3b\x39"
  146. "\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2"
  147. "\x81\xff\x30\x69\xe1\xe9\x4f\x52",
  148. .nout = 32
  149. },
  150. /* RFC-6070 test data */
  151. {
  152. .path = "/crypto/pbkdf/rfc6070/sha1/iter1",
  153. .hash = QCRYPTO_HASH_ALG_SHA1,
  154. .iterations = 1,
  155. .key = "password",
  156. .nkey = 8,
  157. .salt = "salt",
  158. .nsalt = 4,
  159. .out = "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9"
  160. "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6",
  161. .nout = 20
  162. },
  163. {
  164. .path = "/crypto/pbkdf/rfc6070/sha1/iter2",
  165. .hash = QCRYPTO_HASH_ALG_SHA1,
  166. .iterations = 2,
  167. .key = "password",
  168. .nkey = 8,
  169. .salt = "salt",
  170. .nsalt = 4,
  171. .out = "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e"
  172. "\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57",
  173. .nout = 20
  174. },
  175. {
  176. .path = "/crypto/pbkdf/rfc6070/sha1/iter4096",
  177. .hash = QCRYPTO_HASH_ALG_SHA1,
  178. .iterations = 4096,
  179. .key = "password",
  180. .nkey = 8,
  181. .salt = "salt",
  182. .nsalt = 4,
  183. .out = "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad"
  184. "\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1",
  185. .nout = 20
  186. },
  187. {
  188. .path = "/crypto/pbkdf/rfc6070/sha1/iter16777216",
  189. .hash = QCRYPTO_HASH_ALG_SHA1,
  190. .iterations = 16777216,
  191. .key = "password",
  192. .nkey = 8,
  193. .salt = "salt",
  194. .nsalt = 4,
  195. .out = "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94"
  196. "\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84",
  197. .nout = 20,
  198. .slow = true,
  199. },
  200. {
  201. .path = "/crypto/pbkdf/rfc6070/sha1/iter4096a",
  202. .hash = QCRYPTO_HASH_ALG_SHA1,
  203. .iterations = 4096,
  204. .key = "passwordPASSWORDpassword",
  205. .nkey = 24,
  206. .salt = "saltSALTsaltSALTsaltSALTsaltSALTsalt",
  207. .nsalt = 36,
  208. .out = "\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8"
  209. "\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96"
  210. "\x4c\xf2\xf0\x70\x38",
  211. .nout = 25
  212. },
  213. {
  214. .path = "/crypto/pbkdf/rfc6070/sha1/iter4096b",
  215. .hash = QCRYPTO_HASH_ALG_SHA1,
  216. .iterations = 4096,
  217. .key = "pass\0word",
  218. .nkey = 9,
  219. .salt = "sa\0lt",
  220. .nsalt = 5,
  221. .out = "\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37"
  222. "\xd7\xf0\x34\x25\xe0\xc3",
  223. .nout = 16
  224. },
  225. /* non-RFC misc test data */
  226. #ifdef CONFIG_NETTLE
  227. {
  228. /* empty password test.
  229. * Broken with libgcrypt <= 1.5.0, hence CONFIG_NETTLE */
  230. .path = "/crypto/pbkdf/nonrfc/sha1/iter2",
  231. .hash = QCRYPTO_HASH_ALG_SHA1,
  232. .iterations = 2,
  233. .key = "",
  234. .nkey = 0,
  235. .salt = "salt",
  236. .nsalt = 4,
  237. .out = "\x13\x3a\x4c\xe8\x37\xb4\xd2\x52\x1e\xe2"
  238. "\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97",
  239. .nout = 20
  240. },
  241. #endif
  242. {
  243. /* Password exceeds block size test */
  244. .path = "/crypto/pbkdf/nonrfc/sha256/iter1200",
  245. .hash = QCRYPTO_HASH_ALG_SHA256,
  246. .iterations = 1200,
  247. .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  248. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  249. .nkey = 65,
  250. .salt = "pass phrase exceeds block size",
  251. .nsalt = 30,
  252. .out = "\x22\x34\x4b\xc4\xb6\xe3\x26\x75"
  253. "\xa8\x09\x0f\x3e\xa8\x0b\xe0\x1d"
  254. "\x5f\x95\x12\x6a\x2c\xdd\xc3\xfa"
  255. "\xcc\x4a\x5e\x6d\xca\x04\xec\x58",
  256. .nout = 32
  257. },
  258. {
  259. .path = "/crypto/pbkdf/nonrfc/sha512/iter1200",
  260. .hash = QCRYPTO_HASH_ALG_SHA512,
  261. .iterations = 1200,
  262. .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  263. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  264. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  265. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  266. .nkey = 129,
  267. .salt = "pass phrase exceeds block size",
  268. .nsalt = 30,
  269. .out = "\x0f\xb2\xed\x2c\x0e\x6e\xfb\x7d"
  270. "\x7d\x8e\xdd\x58\x01\xb4\x59\x72"
  271. "\x99\x92\x16\x30\x5e\xa4\x36\x8d"
  272. "\x76\x14\x80\xf3\xe3\x7a\x22\xb9",
  273. .nout = 32
  274. },
  275. {
  276. .path = "/crypto/pbkdf/nonrfc/sha224/iter1200",
  277. .hash = QCRYPTO_HASH_ALG_SHA224,
  278. .iterations = 1200,
  279. .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  280. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  281. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  282. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  283. .nkey = 129,
  284. .salt = "pass phrase exceeds block size",
  285. .nsalt = 30,
  286. .out = "\x13\x3b\x88\x0c\x0e\x52\xa2\x41"
  287. "\x49\x33\x35\xa6\xc3\x83\xae\x23"
  288. "\xf6\x77\x43\x9e\x5b\x30\x92\x3e"
  289. "\x4a\x3a\xaa\x24\x69\x3c\xed\x20",
  290. .nout = 32
  291. },
  292. {
  293. .path = "/crypto/pbkdf/nonrfc/sha384/iter1200",
  294. .hash = QCRYPTO_HASH_ALG_SHA384,
  295. .iterations = 1200,
  296. .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  297. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  298. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  299. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  300. .nkey = 129,
  301. .salt = "pass phrase exceeds block size",
  302. .nsalt = 30,
  303. .out = "\xfe\xe3\xe1\x84\xc9\x25\x3e\x10"
  304. "\x47\xc8\x7d\x53\xc6\xa5\xe3\x77"
  305. "\x29\x41\x76\xbd\x4b\xe3\x9b\xac"
  306. "\x05\x6c\x11\xdd\x17\xc5\x93\x80",
  307. .nout = 32
  308. },
  309. {
  310. .path = "/crypto/pbkdf/nonrfc/ripemd160/iter1200",
  311. .hash = QCRYPTO_HASH_ALG_RIPEMD160,
  312. .iterations = 1200,
  313. .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  314. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  315. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  316. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  317. .nkey = 129,
  318. .salt = "pass phrase exceeds block size",
  319. .nsalt = 30,
  320. .out = "\xd6\xcb\xd8\xa7\xdb\x0c\xa2\x2a"
  321. "\x23\x5e\x47\xaf\xdb\xda\xa8\xef"
  322. "\xe4\x01\x0d\x6f\xb5\x33\xc8\xbd"
  323. "\xce\xbf\x91\x14\x8b\x5c\x48\x41",
  324. .nout = 32
  325. },
  326. #if 0
  327. {
  328. .path = "/crypto/pbkdf/nonrfc/whirlpool/iter1200",
  329. .hash = QCRYPTO_HASH_ALG_WHIRLPOOL,
  330. .iterations = 1200,
  331. .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  332. "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  333. .nkey = 65,
  334. .salt = "pass phrase exceeds block size",
  335. .nsalt = 30,
  336. .out = "\x9c\x1c\x74\xf5\x88\x26\xe7\x6a"
  337. "\x53\x58\xf4\x0c\x39\xe7\x80\x89"
  338. "\x07\xc0\x31\x19\x9a\x50\xa2\x48"
  339. "\xf1\xd9\xfe\x78\x64\xe5\x84\x50",
  340. .nout = 32
  341. }
  342. #endif
  343. };
  344. static inline char hex(int i)
  345. {
  346. if (i < 10) {
  347. return '0' + i;
  348. }
  349. return 'a' + (i - 10);
  350. }
  351. static char *hex_string(const uint8_t *bytes,
  352. size_t len)
  353. {
  354. char *hexstr = g_new0(char, len * 2 + 1);
  355. size_t i;
  356. for (i = 0; i < len; i++) {
  357. hexstr[i * 2] = hex((bytes[i] >> 4) & 0xf);
  358. hexstr[i * 2 + 1] = hex(bytes[i] & 0xf);
  359. }
  360. hexstr[len * 2] = '\0';
  361. return hexstr;
  362. }
  363. static void test_pbkdf(const void *opaque)
  364. {
  365. const QCryptoPbkdfTestData *data = opaque;
  366. size_t nout = data->nout;
  367. uint8_t *out = g_new0(uint8_t, nout);
  368. gchar *expect, *actual;
  369. qcrypto_pbkdf2(data->hash,
  370. (uint8_t *)data->key, data->nkey,
  371. (uint8_t *)data->salt, data->nsalt,
  372. data->iterations,
  373. (uint8_t *)out, nout,
  374. &error_abort);
  375. expect = hex_string((const uint8_t *)data->out, data->nout);
  376. actual = hex_string(out, nout);
  377. g_assert_cmpstr(actual, ==, expect);
  378. g_free(actual);
  379. g_free(expect);
  380. g_free(out);
  381. }
  382. static void test_pbkdf_timing(void)
  383. {
  384. uint8_t key[32];
  385. uint8_t salt[32];
  386. int iters;
  387. memset(key, 0x5d, sizeof(key));
  388. memset(salt, 0x7c, sizeof(salt));
  389. iters = qcrypto_pbkdf2_count_iters(QCRYPTO_HASH_ALG_SHA256,
  390. key, sizeof(key),
  391. salt, sizeof(salt),
  392. 32,
  393. &error_abort);
  394. g_assert(iters >= (1 << 15));
  395. }
  396. int main(int argc, char **argv)
  397. {
  398. size_t i;
  399. g_test_init(&argc, &argv, NULL);
  400. g_assert(qcrypto_init(NULL) == 0);
  401. for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
  402. if (!test_data[i].slow ||
  403. g_test_slow()) {
  404. g_test_add_data_func(test_data[i].path, &test_data[i], test_pbkdf);
  405. }
  406. }
  407. if (g_test_slow()) {
  408. g_test_add_func("/crypt0/pbkdf/timing", test_pbkdf_timing);
  409. }
  410. return g_test_run();
  411. }
  412. #else
  413. int main(int argc, char **argv)
  414. {
  415. return 0;
  416. }
  417. #endif