argon2-core.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. /*
  2. * Argon2 source code package
  3. *
  4. * Written by Daniel Dinu and Dmitry Khovratovich, 2015
  5. *
  6. * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
  7. *
  8. * You should have received a copy of the CC0 Public Domain Dedication along
  9. * with
  10. * this software. If not, see
  11. * <http://creativecommons.org/publicdomain/zero/1.0/>.
  12. */
  13. #include <errno.h>
  14. #include <stdint.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <sys/types.h>
  19. #ifdef HAVE_SYS_MMAN_H
  20. # include <sys/mman.h>
  21. #endif
  22. #include "crypto_generichash_blake2b.h"
  23. #include "private/common.h"
  24. #include "private/implementations.h"
  25. #include "runtime.h"
  26. #include "utils.h"
  27. #include "argon2-core.h"
  28. #include "blake2b-long.h"
  29. #if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
  30. # define MAP_ANON MAP_ANONYMOUS
  31. #endif
  32. #ifndef MAP_NOCORE
  33. # define MAP_NOCORE 0
  34. #endif
  35. #ifndef MAP_POPULATE
  36. # define MAP_POPULATE 0
  37. #endif
  38. static fill_segment_fn fill_segment = fill_segment_ref;
  39. static void
  40. load_block(block *dst, const void *input)
  41. {
  42. unsigned i;
  43. for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
  44. dst->v[i] = LOAD64_LE((const uint8_t *) input + i * sizeof(dst->v[i]));
  45. }
  46. }
  47. static void
  48. store_block(void *output, const block *src)
  49. {
  50. unsigned i;
  51. for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
  52. STORE64_LE((uint8_t *) output + i * sizeof(src->v[i]), src->v[i]);
  53. }
  54. }
  55. /***************Memory allocators*****************/
  56. /* Allocates memory to the given pointer
  57. * @param memory pointer to the pointer to the memory
  58. * @param m_cost number of blocks to allocate in the memory
  59. * @return ARGON2_OK if @memory is a valid pointer and memory is allocated
  60. */
  61. static int allocate_memory(block_region **region, uint32_t m_cost);
  62. static int
  63. allocate_memory(block_region **region, uint32_t m_cost)
  64. {
  65. void * base;
  66. block *memory;
  67. size_t memory_size;
  68. if (region == NULL) {
  69. return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
  70. }
  71. memory_size = sizeof(block) * m_cost;
  72. if (m_cost == 0 || memory_size / m_cost != sizeof(block)) {
  73. return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
  74. }
  75. *region = (block_region *) malloc(sizeof(block_region));
  76. if (*region == NULL) {
  77. return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
  78. }
  79. (*region)->base = (*region)->memory = NULL;
  80. #if defined(MAP_ANON) && defined(HAVE_MMAP)
  81. if ((base = mmap(NULL, memory_size, PROT_READ | PROT_WRITE,
  82. MAP_ANON | MAP_PRIVATE | MAP_NOCORE | MAP_POPULATE,
  83. -1, 0)) == MAP_FAILED) {
  84. base = NULL; /* LCOV_EXCL_LINE */
  85. } /* LCOV_EXCL_LINE */
  86. memcpy(&memory, &base, sizeof memory);
  87. #elif defined(HAVE_POSIX_MEMALIGN)
  88. if ((errno = posix_memalign((void **) &base, 64, memory_size)) != 0) {
  89. base = NULL;
  90. }
  91. memcpy(&memory, &base, sizeof memory);
  92. #else
  93. memory = NULL;
  94. if (memory_size + 63 < memory_size) {
  95. base = NULL;
  96. errno = ENOMEM;
  97. } else if ((base = malloc(memory_size + 63)) != NULL) {
  98. uint8_t *aligned = ((uint8_t *) base) + 63;
  99. aligned -= (uintptr_t) aligned & 63;
  100. memcpy(&memory, &aligned, sizeof memory);
  101. }
  102. #endif
  103. if (base == NULL) {
  104. /* LCOV_EXCL_START */
  105. free(*region);
  106. *region = NULL;
  107. return ARGON2_MEMORY_ALLOCATION_ERROR;
  108. /* LCOV_EXCL_STOP */
  109. }
  110. (*region)->base = base;
  111. (*region)->memory = memory;
  112. (*region)->size = memory_size;
  113. return ARGON2_OK;
  114. }
  115. /*********Memory functions*/
  116. /* Clears memory
  117. * @param instance pointer to the current instance
  118. * @param clear_memory indicates if we clear the memory with zeros.
  119. */
  120. static void clear_memory(argon2_instance_t *instance, int clear);
  121. static void
  122. clear_memory(argon2_instance_t *instance, int clear)
  123. {
  124. /* LCOV_EXCL_START */
  125. if (clear) {
  126. if (instance->region != NULL) {
  127. sodium_memzero(instance->region->memory,
  128. sizeof(block) * instance->memory_blocks);
  129. }
  130. if (instance->pseudo_rands != NULL) {
  131. sodium_memzero(instance->pseudo_rands,
  132. sizeof(uint64_t) * instance->segment_length);
  133. }
  134. }
  135. /* LCOV_EXCL_STOP */
  136. }
  137. /* Deallocates memory
  138. * @param memory pointer to the blocks
  139. */
  140. static void free_memory(block_region *region);
  141. static void
  142. free_memory(block_region *region)
  143. {
  144. if (region && region->base) {
  145. #if defined(MAP_ANON) && defined(HAVE_MMAP)
  146. if (munmap(region->base, region->size)) {
  147. return; /* LCOV_EXCL_LINE */
  148. }
  149. #else
  150. free(region->base);
  151. #endif
  152. }
  153. free(region);
  154. }
  155. void
  156. free_instance(argon2_instance_t *instance, int flags)
  157. {
  158. /* Clear memory */
  159. clear_memory(instance, flags & ARGON2_FLAG_CLEAR_MEMORY);
  160. /* Deallocate the memory */
  161. free(instance->pseudo_rands);
  162. instance->pseudo_rands = NULL;
  163. free_memory(instance->region);
  164. instance->region = NULL;
  165. }
  166. void
  167. finalize(const argon2_context *context, argon2_instance_t *instance)
  168. {
  169. if (context != NULL && instance != NULL) {
  170. block blockhash;
  171. uint32_t l;
  172. copy_block(&blockhash,
  173. instance->region->memory + instance->lane_length - 1);
  174. /* XOR the last blocks */
  175. for (l = 1; l < instance->lanes; ++l) {
  176. uint32_t last_block_in_lane =
  177. l * instance->lane_length + (instance->lane_length - 1);
  178. xor_block(&blockhash,
  179. instance->region->memory + last_block_in_lane);
  180. }
  181. /* Hash the result */
  182. {
  183. uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
  184. store_block(blockhash_bytes, &blockhash);
  185. blake2b_long(context->out, context->outlen, blockhash_bytes,
  186. ARGON2_BLOCK_SIZE);
  187. sodium_memzero(blockhash.v,
  188. ARGON2_BLOCK_SIZE); /* clear blockhash */
  189. sodium_memzero(blockhash_bytes,
  190. ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */
  191. }
  192. free_instance(instance, context->flags);
  193. }
  194. }
  195. void
  196. fill_memory_blocks(argon2_instance_t *instance, uint32_t pass)
  197. {
  198. argon2_position_t position;
  199. uint32_t l;
  200. uint32_t s;
  201. if (instance == NULL || instance->lanes == 0) {
  202. return; /* LCOV_EXCL_LINE */
  203. }
  204. position.pass = pass;
  205. for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
  206. position.slice = (uint8_t) s;
  207. for (l = 0; l < instance->lanes; ++l) {
  208. position.lane = l;
  209. position.index = 0;
  210. fill_segment(instance, position);
  211. }
  212. }
  213. }
  214. int
  215. validate_inputs(const argon2_context *context)
  216. {
  217. /* LCOV_EXCL_START */
  218. if (NULL == context) {
  219. return ARGON2_INCORRECT_PARAMETER;
  220. }
  221. if (NULL == context->out) {
  222. return ARGON2_OUTPUT_PTR_NULL;
  223. }
  224. /* Validate output length */
  225. if (ARGON2_MIN_OUTLEN > context->outlen) {
  226. return ARGON2_OUTPUT_TOO_SHORT;
  227. }
  228. if (ARGON2_MAX_OUTLEN < context->outlen) {
  229. return ARGON2_OUTPUT_TOO_LONG;
  230. }
  231. /* Validate password (required param) */
  232. if (NULL == context->pwd) {
  233. if (0 != context->pwdlen) {
  234. return ARGON2_PWD_PTR_MISMATCH;
  235. }
  236. }
  237. if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
  238. return ARGON2_PWD_TOO_SHORT;
  239. }
  240. if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
  241. return ARGON2_PWD_TOO_LONG;
  242. }
  243. /* Validate salt (required param) */
  244. if (NULL == context->salt) {
  245. if (0 != context->saltlen) {
  246. return ARGON2_SALT_PTR_MISMATCH;
  247. }
  248. }
  249. if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
  250. return ARGON2_SALT_TOO_SHORT;
  251. }
  252. if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
  253. return ARGON2_SALT_TOO_LONG;
  254. }
  255. /* Validate secret (optional param) */
  256. if (NULL == context->secret) {
  257. if (0 != context->secretlen) {
  258. return ARGON2_SECRET_PTR_MISMATCH;
  259. }
  260. } else {
  261. if (ARGON2_MIN_SECRET > context->secretlen) {
  262. return ARGON2_SECRET_TOO_SHORT;
  263. }
  264. if (ARGON2_MAX_SECRET < context->secretlen) {
  265. return ARGON2_SECRET_TOO_LONG;
  266. }
  267. }
  268. /* Validate associated data (optional param) */
  269. if (NULL == context->ad) {
  270. if (0 != context->adlen) {
  271. return ARGON2_AD_PTR_MISMATCH;
  272. }
  273. } else {
  274. if (ARGON2_MIN_AD_LENGTH > context->adlen) {
  275. return ARGON2_AD_TOO_SHORT;
  276. }
  277. if (ARGON2_MAX_AD_LENGTH < context->adlen) {
  278. return ARGON2_AD_TOO_LONG;
  279. }
  280. }
  281. /* Validate memory cost */
  282. if (ARGON2_MIN_MEMORY > context->m_cost) {
  283. return ARGON2_MEMORY_TOO_LITTLE;
  284. }
  285. if (ARGON2_MAX_MEMORY < context->m_cost) {
  286. return ARGON2_MEMORY_TOO_MUCH;
  287. }
  288. if (context->m_cost < 8 * context->lanes) {
  289. return ARGON2_MEMORY_TOO_LITTLE;
  290. }
  291. /* Validate time cost */
  292. if (ARGON2_MIN_TIME > context->t_cost) {
  293. return ARGON2_TIME_TOO_SMALL;
  294. }
  295. if (ARGON2_MAX_TIME < context->t_cost) {
  296. return ARGON2_TIME_TOO_LARGE;
  297. }
  298. /* Validate lanes */
  299. if (ARGON2_MIN_LANES > context->lanes) {
  300. return ARGON2_LANES_TOO_FEW;
  301. }
  302. if (ARGON2_MAX_LANES < context->lanes) {
  303. return ARGON2_LANES_TOO_MANY;
  304. }
  305. /* Validate threads */
  306. if (ARGON2_MIN_THREADS > context->threads) {
  307. return ARGON2_THREADS_TOO_FEW;
  308. }
  309. if (ARGON2_MAX_THREADS < context->threads) {
  310. return ARGON2_THREADS_TOO_MANY;
  311. }
  312. /* LCOV_EXCL_STOP */
  313. return ARGON2_OK;
  314. }
  315. void
  316. fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance)
  317. {
  318. uint32_t l;
  319. /* Make the first and second block in each lane as G(H0||i||0) or
  320. G(H0||i||1) */
  321. uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
  322. for (l = 0; l < instance->lanes; ++l) {
  323. STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
  324. STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
  325. blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
  326. ARGON2_PREHASH_SEED_LENGTH);
  327. load_block(&instance->region->memory[l * instance->lane_length + 0],
  328. blockhash_bytes);
  329. STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
  330. blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
  331. ARGON2_PREHASH_SEED_LENGTH);
  332. load_block(&instance->region->memory[l * instance->lane_length + 1],
  333. blockhash_bytes);
  334. }
  335. sodium_memzero(blockhash_bytes, ARGON2_BLOCK_SIZE);
  336. }
  337. void
  338. initial_hash(uint8_t *blockhash, argon2_context *context, argon2_type type)
  339. {
  340. crypto_generichash_blake2b_state BlakeHash;
  341. uint8_t value[4U /* sizeof(uint32_t) */];
  342. if (NULL == context || NULL == blockhash) {
  343. return; /* LCOV_EXCL_LINE */
  344. }
  345. crypto_generichash_blake2b_init(&BlakeHash, NULL, 0U,
  346. ARGON2_PREHASH_DIGEST_LENGTH);
  347. STORE32_LE(value, context->lanes);
  348. crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
  349. STORE32_LE(value, context->outlen);
  350. crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
  351. STORE32_LE(value, context->m_cost);
  352. crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
  353. STORE32_LE(value, context->t_cost);
  354. crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
  355. STORE32_LE(value, ARGON2_VERSION_NUMBER);
  356. crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
  357. STORE32_LE(value, (uint32_t) type);
  358. crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
  359. STORE32_LE(value, context->pwdlen);
  360. crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
  361. if (context->pwd != NULL) {
  362. crypto_generichash_blake2b_update(
  363. &BlakeHash, (const uint8_t *) context->pwd, context->pwdlen);
  364. /* LCOV_EXCL_START */
  365. if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
  366. sodium_memzero(context->pwd, context->pwdlen);
  367. context->pwdlen = 0;
  368. }
  369. /* LCOV_EXCL_STOP */
  370. }
  371. STORE32_LE(value, context->saltlen);
  372. crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
  373. if (context->salt != NULL) {
  374. crypto_generichash_blake2b_update(
  375. &BlakeHash, (const uint8_t *) context->salt, context->saltlen);
  376. }
  377. STORE32_LE(value, context->secretlen);
  378. crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
  379. /* LCOV_EXCL_START */
  380. if (context->secret != NULL) {
  381. crypto_generichash_blake2b_update(
  382. &BlakeHash, (const uint8_t *) context->secret, context->secretlen);
  383. if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
  384. sodium_memzero(context->secret, context->secretlen);
  385. context->secretlen = 0;
  386. }
  387. }
  388. /* LCOV_EXCL_STOP */
  389. STORE32_LE(value, context->adlen);
  390. crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
  391. /* LCOV_EXCL_START */
  392. if (context->ad != NULL) {
  393. crypto_generichash_blake2b_update(
  394. &BlakeHash, (const uint8_t *) context->ad, context->adlen);
  395. }
  396. /* LCOV_EXCL_STOP */
  397. crypto_generichash_blake2b_final(&BlakeHash, blockhash,
  398. ARGON2_PREHASH_DIGEST_LENGTH);
  399. }
  400. int
  401. initialize(argon2_instance_t *instance, argon2_context *context)
  402. {
  403. uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
  404. int result = ARGON2_OK;
  405. if (instance == NULL || context == NULL) {
  406. return ARGON2_INCORRECT_PARAMETER;
  407. }
  408. /* 1. Memory allocation */
  409. if ((instance->pseudo_rands = (uint64_t *)
  410. malloc(sizeof(uint64_t) * instance->segment_length)) == NULL) {
  411. return ARGON2_MEMORY_ALLOCATION_ERROR;
  412. }
  413. result = allocate_memory(&(instance->region), instance->memory_blocks);
  414. if (ARGON2_OK != result) {
  415. free_instance(instance, context->flags);
  416. return result;
  417. }
  418. /* 2. Initial hashing */
  419. /* H_0 + 8 extra bytes to produce the first blocks */
  420. /* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
  421. /* Hashing all inputs */
  422. initial_hash(blockhash, context, instance->type);
  423. /* Zeroing 8 extra bytes */
  424. sodium_memzero(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
  425. ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH);
  426. /* 3. Creating first blocks, we always have at least two blocks in a slice
  427. */
  428. fill_first_blocks(blockhash, instance);
  429. /* Clearing the hash */
  430. sodium_memzero(blockhash, ARGON2_PREHASH_SEED_LENGTH);
  431. return ARGON2_OK;
  432. }
  433. int
  434. argon2_pick_best_implementation(void)
  435. {
  436. /* LCOV_EXCL_START */
  437. #if defined(HAVE_AVX512FINTRIN_H) && defined(HAVE_AVX2INTRIN_H) && \
  438. defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
  439. if (sodium_runtime_has_avx512f()) {
  440. fill_segment = fill_segment_avx512f;
  441. return 0;
  442. }
  443. #endif
  444. #if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_TMMINTRIN_H) && \
  445. defined(HAVE_SMMINTRIN_H)
  446. if (sodium_runtime_has_avx2()) {
  447. fill_segment = fill_segment_avx2;
  448. return 0;
  449. }
  450. #endif
  451. #if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
  452. if (sodium_runtime_has_ssse3()) {
  453. fill_segment = fill_segment_ssse3;
  454. return 0;
  455. }
  456. #endif
  457. fill_segment = fill_segment_ref;
  458. return 0;
  459. /* LCOV_EXCL_STOP */
  460. }
  461. int
  462. _crypto_pwhash_argon2_pick_best_implementation(void)
  463. {
  464. return argon2_pick_best_implementation();
  465. }