void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) { char u[WHIRLPOOL_DIGESTSIZE]; int b, l, r; if (dklen % WHIRLPOOL_DIGESTSIZE) { l = 1 + dklen / WHIRLPOOL_DIGESTSIZE; } else { l = dklen / WHIRLPOOL_DIGESTSIZE; } r = dklen - (l - 1) * WHIRLPOOL_DIGESTSIZE; /* first l - 1 blocks */ for (b = 1; b < l; b++) { derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, u, b); memcpy (dk, u, WHIRLPOOL_DIGESTSIZE); dk += WHIRLPOOL_DIGESTSIZE; } /* last block */ derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, u, b); memcpy (dk, u, r); /* Prevent possible leaks. */ burn (u, sizeof(u)); }
void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen) { hmac_whirlpool_ctx hmac; char key[WHIRLPOOL_DIGESTSIZE]; int b, l, r; /* If the password is longer than the hash algorithm block size, let pwd = whirlpool(pwd), as per HMAC specifications. */ if (pwd_len > WHIRLPOOL_BLOCKSIZE) { WHIRLPOOL_CTX tctx; WHIRLPOOL_init (&tctx); WHIRLPOOL_add ((unsigned char *) pwd, pwd_len * 8, &tctx); WHIRLPOOL_finalize (&tctx, (unsigned char *) key); pwd = key; pwd_len = WHIRLPOOL_DIGESTSIZE; burn (&tctx, sizeof(tctx)); // Prevent leaks } if (dklen % WHIRLPOOL_DIGESTSIZE) { l = 1 + dklen / WHIRLPOOL_DIGESTSIZE; } else { l = dklen / WHIRLPOOL_DIGESTSIZE; } r = dklen - (l - 1) * WHIRLPOOL_DIGESTSIZE; /* first l - 1 blocks */ for (b = 1; b < l; b++) { derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, b, &hmac); memcpy (dk, hmac.u, WHIRLPOOL_DIGESTSIZE); dk += WHIRLPOOL_DIGESTSIZE; } /* last block */ derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, b, &hmac); memcpy (dk, hmac.u, r); /* Prevent possible leaks. */ burn (&hmac, sizeof(hmac)); burn (key, sizeof(key)); }