/* * Test for wrong Whirlpool variant, * Ref: http://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html */ static void crypt_hash_test_whirlpool_bug(void) { struct crypt_hash *h; char buf[2] = "\0\0", hash_out1[64], hash_out2[64]; int r; if (crypto_backend_whirlpool_bug >= 0) return; crypto_backend_whirlpool_bug = 0; if (crypt_hash_init(&h, "whirlpool")) return; /* One shot */ if ((r = crypt_hash_write(h, &buf[0], 2)) || (r = crypt_hash_final(h, hash_out1, 64))) { crypt_hash_destroy(h); return; } /* Split buf (crypt_hash_final resets hash state) */ if ((r = crypt_hash_write(h, &buf[0], 1)) || (r = crypt_hash_write(h, &buf[1], 1)) || (r = crypt_hash_final(h, hash_out2, 64))) { crypt_hash_destroy(h); return; } crypt_hash_destroy(h); if (memcmp(hash_out1, hash_out2, 64)) crypto_backend_whirlpool_bug = 1; }
static int hash(const char *hash_name, size_t key_size, char *key, size_t passphrase_size, const char *passphrase) { struct crypt_hash *md = NULL; size_t len; int round, i, r = 0; if (crypt_hash_init(&md, hash_name)) return -ENOENT; len = crypt_hash_size(hash_name); for(round = 0; key_size && !r; round++) { /* hack from hashalot to avoid null bytes in key */ for(i = 0; i < round; i++) if (crypt_hash_write(md, "A", 1)) r = 1; if (crypt_hash_write(md, passphrase, passphrase_size)) r = 1; if (len > key_size) len = key_size; if (crypt_hash_final(md, key, len)) r = 1; key += len; key_size -= len; } crypt_hash_destroy(md); return r; }
static int verify_hash_block(const char *hash_name, int version, char *hash, size_t hash_size, const char *data, size_t data_size, const char *salt, size_t salt_size) { struct crypt_hash *ctx = NULL; int r; if (crypt_hash_init(&ctx, hash_name)) return -EINVAL; if (version == 1 && (r = crypt_hash_write(ctx, salt, salt_size))) goto out; if ((r = crypt_hash_write(ctx, data, data_size))) goto out; if (version == 0 && (r = crypt_hash_write(ctx, salt, salt_size))) goto out; r = crypt_hash_final(ctx, hash, hash_size); out: crypt_hash_destroy(ctx); return r; }
static int hash_key(const char *src, size_t src_len, char *dst, size_t dst_len, const char *hash_name) { struct crypt_hash *hd = NULL; int r; if (crypt_hash_init(&hd, hash_name)) return -EINVAL; r = crypt_hash_write(hd, src, src_len); if (!r) r = crypt_hash_final(hd, dst, dst_len); crypt_hash_destroy(hd); return r; }
static int hash_buf(const char *src, char *dst, uint32_t iv, size_t len, const char *hash_name) { struct crypt_hash *hd = NULL; char *iv_char = (char *)&iv; int r; iv = htonl(iv); if (crypt_hash_init(&hd, hash_name)) return -EINVAL; if ((r = crypt_hash_write(hd, iv_char, sizeof(uint32_t)))) goto out; if ((r = crypt_hash_write(hd, src, len))) goto out; r = crypt_hash_final(hd, dst, len); out: crypt_hash_destroy(hd); return r; }
/* * Calculate hash (checksum) of |LUKS2_bin|LUKS2_JSON_area| from in-memory structs. * LUKS2 on-disk header contains uniques salt both for primary and secondary header. * Checksum is always calculated with zeroed checksum field in binary header. */ static int hdr_checksum_calculate(const char *alg, struct luks2_hdr_disk *hdr_disk, const char *json_area, size_t json_len) { struct crypt_hash *hd = NULL; int hash_size, r; hash_size = crypt_hash_size(alg); if (hash_size <= 0 || crypt_hash_init(&hd, alg)) return -EINVAL; /* Binary header, csum zeroed. */ r = crypt_hash_write(hd, (char*)hdr_disk, LUKS2_HDR_BIN_LEN); /* JSON area (including unused space) */ if (!r) r = crypt_hash_write(hd, json_area, json_len); if (!r) r = crypt_hash_final(hd, (char*)hdr_disk->csum, (size_t)hash_size); crypt_hash_destroy(hd); return r; }