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