/* Runs Argon2 with certain inputs and parameters, inputs not cleared. Prints the Base64-encoded hash string @out output array with at least 32 bytes allocated @pwd NULL-terminated string, presumably from argv[] @salt salt array @t_cost number of iterations @m_cost amount of requested memory in KB @lanes amount of requested parallelism @threads actual parallelism @type String, only "d" and "i" are accepted @encoded_only display only the encoded hash @raw_only display only the hexadecimal of the hash */ static void run(uint32_t outlen, char *pwd, char *salt, uint32_t t_cost, uint32_t m_cost, uint32_t lanes, uint32_t threads, argon2_type type, int encoded_only, int raw_only) { clock_t start_time, stop_time; size_t pwdlen, saltlen, encodedlen; int result; start_time = clock(); if (!pwd) { fatal("password missing"); } if (!salt) { secure_wipe_memory(pwd, strlen(pwd)); fatal("salt missing"); } pwdlen = strlen(pwd); saltlen = strlen(salt); if(UINT32_MAX < saltlen) { fatal("salt is too long"); } UNUSED_PARAMETER(lanes); unsigned char* out = malloc(outlen + 1); if (!out) { secure_wipe_memory(pwd, strlen(pwd)); fatal("could not allocate memory for output"); } encodedlen = argon2_encodedlen(t_cost, m_cost, lanes, (uint32_t)saltlen, outlen); char* encoded = malloc(encodedlen + 1); if (!encoded) { secure_wipe_memory(pwd, strlen(pwd)); fatal("could not allocate memory for hash"); } result = argon2_hash(t_cost, m_cost, threads, pwd, pwdlen, salt, saltlen, out, outlen, encoded, encodedlen, type, ARGON2_VERSION_NUMBER); if (result != ARGON2_OK) fatal(argon2_error_message(result)); stop_time = clock(); if (encoded_only) puts(encoded); if (raw_only) print_hex(out, outlen); if (encoded_only || raw_only) { free(out); free(encoded); return; } printf("Hash:\t\t"); print_hex(out, outlen); free(out); printf("Encoded:\t%s\n", encoded); printf("%2.3f seconds\n", ((double)stop_time - start_time) / (CLOCKS_PER_SEC)); result = argon2_verify(encoded, pwd, pwdlen, type); if (result != ARGON2_OK) fatal(argon2_error_message(result)); printf("Verification ok\n"); free(encoded); }
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen, argon2_type type) { argon2_context ctx; uint8_t *out; /* max values, to be updated in decode_string */ ctx.adlen = 512; ctx.saltlen = 512; ctx.outlen = 512; ctx.ad = malloc(ctx.adlen); ctx.salt = malloc(ctx.saltlen); ctx.out = malloc(ctx.outlen); out = malloc(ctx.outlen); decode_string(&ctx, encoded, type); argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen, ctx.salt, ctx.saltlen, out, ctx.outlen, NULL, 0, type); free(ctx.ad); free(ctx.salt); if (memcmp(out, ctx.out, ctx.outlen)) { free(out); free(ctx.out); return ARGON2_DECODING_FAIL; } free(out); free(ctx.out); return ARGON2_OK; }
void argon2hash(void *output, const void *input) { unsigned int t_costs = 2; unsigned int m_costs = 16; unsigned int Nfactor = m_costs/2; const uint32_t r = SCRYPT_R; const uint32_t p = SCRYPT_P; scrypt_aligned_alloc YX, V; uint8_t *X, *Y; uint32_t N, chunk_bytes, i; N = (1 << (Nfactor + 1)); chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2; V = scrypt_alloc((uint64_t)N * chunk_bytes); YX = scrypt_alloc((p + 1) * chunk_bytes); /* 1: X = PBKDF2(password, salt) */ Y = YX.ptr; X = Y + chunk_bytes; argon2_hash(output, input, t_costs, m_costs, N, X, Y, V.ptr, p, r); scrypt_free(&V); scrypt_free(&YX); }
int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost, const uint32_t parallelism, const void *pwd, const size_t pwdlen, const void *salt, const size_t saltlen, void *hash, const size_t hashlen) { return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, hash, hashlen, NULL, 0, Argon2_d); }
int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost, const uint32_t parallelism, const void *pwd, const size_t pwdlen, const void *salt, const size_t saltlen, const size_t hashlen, char *encoded, const size_t encodedlen) { return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, NULL, hashlen, encoded, encodedlen, Argon2_d); }
int crypto_argon2_hash(const uint32_t t_cost, const uint32_t m_cost, const uint32_t parallelism, const void *pwd, const size_t pwdlen, const void *salt, const size_t saltlen, void *hash, const size_t hashlen, char *encoded, const size_t encodedlen, argon2_type type, const uint32_t version) { return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, hash, hashlen, encoded, encodedlen, type, version); }
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen, argon2_type type) { argon2_context ctx; uint8_t *out; int ret; int decode_result; /* max values, to be updated in decode_string */ uint32_t encoded_len = strlen(encoded); ctx.adlen = encoded_len; ctx.saltlen = encoded_len; ctx.outlen = encoded_len; ctx.allocate_cbk = NULL; ctx.free_cbk = NULL; ctx.secret = NULL; ctx.secretlen = 0; ctx.ad = malloc(ctx.adlen); ctx.salt = malloc(ctx.saltlen); ctx.out = malloc(ctx.outlen); if (!ctx.out || !ctx.salt || !ctx.ad) { free(ctx.ad); free(ctx.salt); free(ctx.out); return ARGON2_MEMORY_ALLOCATION_ERROR; } out = malloc(ctx.outlen); if (!out) { free(ctx.ad); free(ctx.salt); free(ctx.out); return ARGON2_MEMORY_ALLOCATION_ERROR; } decode_result = decode_string(&ctx, encoded, type); if (decode_result != ARGON2_OK) { free(ctx.ad); free(ctx.salt); free(ctx.out); free(out); return decode_result; } ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen, ctx.salt, ctx.saltlen, out, ctx.outlen, NULL, 0, type); free(ctx.ad); free(ctx.salt); if (ret == ARGON2_OK && argon2_compare(out, ctx.out, ctx.outlen)) { ret = ARGON2_VERIFY_MISMATCH; } free(out); free(ctx.out); return ret; }
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen, argon2_type type) { argon2_context ctx; uint8_t *out; int ret; /* max values, to be updated in decode_string */ ctx.adlen = 512; ctx.saltlen = 512; ctx.outlen = 512; ctx.ad = malloc(ctx.adlen); ctx.salt = malloc(ctx.saltlen); ctx.out = malloc(ctx.outlen); if (!ctx.out || !ctx.salt || !ctx.ad) { free(ctx.ad); free(ctx.salt); free(ctx.out); return ARGON2_MEMORY_ALLOCATION_ERROR; } out = malloc(ctx.outlen); if (!out) { free(ctx.ad); free(ctx.salt); free(ctx.out); return ARGON2_MEMORY_ALLOCATION_ERROR; } if(decode_string(&ctx, encoded, type) != 1) { free(ctx.ad); free(ctx.salt); free(ctx.out); free(out); return ARGON2_DECODING_FAIL; } ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen, ctx.salt, ctx.saltlen, out, ctx.outlen, NULL, 0, type); free(ctx.ad); free(ctx.salt); if (ret != ARGON2_OK || argon2_compare(out, ctx.out, ctx.outlen)) { free(out); free(ctx.out); return ARGON2_DECODING_FAIL; } free(out); free(ctx.out); return ARGON2_OK; }
int scanhash_argon2(int thr_id, uint32_t *pdata, const uint32_t *ptarget, uint32_t max_nonce, uint64_t *hashes_done) { uint32_t n = pdata[19] - 1; const uint32_t first_nonce = pdata[19]; const uint32_t Htarg = ptarget[7]; uint32_t hash64[8] __attribute__((aligned(32))); uint32_t endiandata[32]; scrypt_aligned_alloc YX, V; uint8_t *X, *Y; uint32_t N, chunk_bytes; unsigned int t_costs = 2; unsigned int m_costs = 16; unsigned int Nfactor = m_costs/2; const uint32_t r = SCRYPT_R; const uint32_t p = SCRYPT_P; int i; uint64_t htmax[] = { 0, 0xF, 0xFF, 0xFFF, 0xFFFF, 0xFFFFF, 0xFFFFFF, 0xFFFFFFF, 0x10000000 }; uint32_t masks[] = { 0xFFFFFFFF, 0xFFFFFFF0, 0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, 0xFFF00000, 0xFF000000, 0xF0000000, 0 }; // we need bigendian data... for (int kk=0; kk < 32; kk++) { be32enc(&endiandata[kk], (pdata)[kk]); }; N = (1 << (Nfactor + 1)); chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2; V = scrypt_alloc((uint64_t)N * chunk_bytes); YX = scrypt_alloc((p + 1) * chunk_bytes); Y = YX.ptr; X = Y + chunk_bytes; #ifdef DEBUG_ALGO printf("[%d] Htarg=%X\n", thr_id, Htarg); #endif for (int m=0; m < sizeof(masks); m++) { if (Htarg <= htmax[m]) { uint32_t mask = masks[m]; do { pdata[19] = ++n; be32enc(&endiandata[19], n); argon2_hash(hash64, endiandata, t_costs, m_costs, N, X, Y, V.ptr, p, r); #ifndef DEBUG_ALGO if ((!(hash64[7] & mask)) && fulltest(hash64, ptarget)) { *hashes_done = n - first_nonce + 1; pdata[19] = n; scrypt_free(&V); scrypt_free(&YX); return 1; } #else if (!(n % 0x1000) && !thr_id) printf("."); if (!(hash64[7] & mask)) { printf("[%d]",thr_id); if (fulltest(hash64, ptarget)) { *hashes_done = n - first_nonce + 1; scrypt_free(&V); scrypt_free(&YX); return true; } } #endif } while (n < max_nonce && !work_restart[thr_id].restart); break; } } scrypt_free(&V); scrypt_free(&YX); *hashes_done = n - first_nonce + 1; pdata[19] = n; return 0; }
/* Runs Argon2 with certain inputs and parameters, inputs not cleared. Prints the Base64-encoded hash string @out output array with at least 32 bytes allocated @pwd NULL-terminated string, presumably from argv[] @salt salt array with at least SALTLEN_DEF bytes allocated @t_cost number of iterations @m_cost amount of requested memory in KB @lanes amount of requested parallelism @threads actual parallelism @type String, only "d" and "i" are accepted */ static void run(uint32_t outlen, char *pwd, char *salt, uint32_t t_cost, uint32_t m_cost, uint32_t lanes, uint32_t threads, argon2_type type) { clock_t start_time, stop_time; size_t pwdlen, saltlen, encodedlen; uint32_t i; int result; start_time = clock(); if (!pwd) { fatal("password missing"); } if (!salt) { secure_wipe_memory(pwd, strlen(pwd)); fatal("salt missing"); } pwdlen = strlen(pwd); saltlen = strlen(salt); UNUSED_PARAMETER(lanes); unsigned char* out = malloc(outlen + 1); if (!out) { secure_wipe_memory(pwd, strlen(pwd)); fatal("could not allocate memory for output"); } encodedlen = enclen(outlen, saltlen, t_cost, m_cost, lanes); char* encoded = malloc(encodedlen + 1); if (!encoded) { secure_wipe_memory(pwd, strlen(pwd)); fatal("could not allocate memory for hash"); } result = argon2_hash(t_cost, m_cost, threads, pwd, pwdlen, salt, saltlen, out, outlen, encoded, encodedlen, type); if (result != ARGON2_OK) fatal(argon2_error_message(result)); stop_time = clock(); printf("Hash:\t\t"); for (i = 0; i < outlen; ++i) { printf("%02x", out[i]); } free(out); printf("\n"); printf("Encoded:\t%s\n", encoded); printf("%2.3f seconds\n", ((double)stop_time - start_time) / (CLOCKS_PER_SEC)); result = argon2_verify(encoded, pwd, pwdlen, type); if (result != ARGON2_OK) fatal(argon2_error_message(result)); printf("Verification ok\n"); free(encoded); }