Change chunk HMAC to only check header, not full data. Digest in hdr int turn validates data.

This commit is contained in:
Moinak Ghosh 2012-10-19 21:51:27 +05:30
parent 1eb8c94fed
commit 315bb50264

61
main.c
View file

@ -292,8 +292,22 @@ redo:
goto cont; goto cont;
} }
cseg = tdat->compressed_chunk + cksum_bytes + mac_bytes;
HDR = *cseg;
cseg += CHUNK_FLAG_SZ;
_chunksize = tdat->chunksize;
if (HDR & CHSIZE_MASK) {
uchar_t *rseg;
tdat->rbytes -= ORIGINAL_CHUNKSZ;
tdat->len_cmp -= ORIGINAL_CHUNKSZ;
rseg = tdat->compressed_chunk + tdat->rbytes;
_chunksize = ntohll(*((ssize_t *)rseg));
}
/* /*
* Verify HMAC first before anything else. * If this was encrypted:
* Verify HMAC first before anything else and then decrypt compressed data.
*/ */
if (encrypt_type) { if (encrypt_type) {
unsigned int len; unsigned int len;
@ -304,7 +318,12 @@ redo:
hmac_reinit(&tdat->chunk_hmac); hmac_reinit(&tdat->chunk_hmac);
hmac_update(&tdat->chunk_hmac, (uchar_t *)&tdat->len_cmp_be, sizeof (tdat->len_cmp_be)); hmac_update(&tdat->chunk_hmac, (uchar_t *)&tdat->len_cmp_be, sizeof (tdat->len_cmp_be));
hmac_update(&tdat->chunk_hmac, tdat->compressed_chunk, hmac_update(&tdat->chunk_hmac, tdat->compressed_chunk,
tdat->len_cmp + cksum_bytes + mac_bytes + CHUNK_FLAG_SZ); cksum_bytes + mac_bytes + CHUNK_FLAG_SZ);
if (HDR & CHSIZE_MASK) {
uchar_t *rseg;
rseg = tdat->compressed_chunk + tdat->rbytes;
hmac_update(&tdat->chunk_hmac, rseg, ORIGINAL_CHUNKSZ);
}
hmac_final(&tdat->chunk_hmac, tdat->checksum, &len); hmac_final(&tdat->chunk_hmac, tdat->checksum, &len);
if (memcmp(checksum, tdat->checksum, len) != 0) { if (memcmp(checksum, tdat->checksum, len) != 0) {
/* /*
@ -316,27 +335,6 @@ redo:
sem_post(&tdat->cmp_done_sem); sem_post(&tdat->cmp_done_sem);
return; return;
} }
}
cseg = tdat->compressed_chunk + cksum_bytes + mac_bytes;
_chunksize = tdat->chunksize;
deserialize_checksum(tdat->checksum, tdat->compressed_chunk, cksum_bytes);
HDR = *cseg;
cseg += CHUNK_FLAG_SZ;
if (HDR & CHSIZE_MASK) {
uchar_t *rseg;
tdat->rbytes -= ORIGINAL_CHUNKSZ;
tdat->len_cmp -= ORIGINAL_CHUNKSZ;
rseg = tdat->compressed_chunk + tdat->rbytes;
_chunksize = ntohll(*((ssize_t *)rseg));
}
/*
* Decrypt compressed data if necessary.
*/
if (encrypt_type) {
uchar_t hmac[CKSUM_MAX_BYTES];
/* /*
* Encryption algorithm should not change the size and * Encryption algorithm should not change the size and
@ -354,6 +352,12 @@ redo:
} }
} }
/*
* Now that HMAC (if any) was verified, recover the stored message
* digest.
*/
deserialize_checksum(tdat->checksum, tdat->compressed_chunk, cksum_bytes);
if ((enable_rabin_scan || enable_fixed_scan) && (HDR & CHUNK_FLAG_DEDUP)) { if ((enable_rabin_scan || enable_fixed_scan) && (HDR & CHUNK_FLAG_DEDUP)) {
uchar_t *cmpbuf, *ubuf; uchar_t *cmpbuf, *ubuf;
@ -1144,6 +1148,7 @@ plain_compress:
tdat->len_cmp += CHUNK_FLAG_SZ; tdat->len_cmp += CHUNK_FLAG_SZ;
tdat->len_cmp += sizeof (len_cmp); tdat->len_cmp += sizeof (len_cmp);
tdat->len_cmp += (cksum_bytes + mac_bytes); tdat->len_cmp += (cksum_bytes + mac_bytes);
rbytes = tdat->len_cmp - len_cmp; // HDR size for HMAC
if (adapt_mode) if (adapt_mode)
type |= (rv << 4); type |= (rv << 4);
@ -1164,18 +1169,22 @@ plain_compress:
*(tdat->compressed_chunk) = type; *(tdat->compressed_chunk) = type;
/* /*
* If encrypting, compute HMAC for entire chunk (hdr + data) * If encrypting, compute HMAC for chunk header and trailer.
*/ */
if (encrypt_type) { if (encrypt_type) {
uchar_t *mac_ptr; uchar_t *mac_ptr;
unsigned int hlen; unsigned int hlen;
uchar_t chash[mac_bytes]; uchar_t chash[mac_bytes];
/* Clean out mac_bytes to 0 for stable hash. */ /* Clean out mac_bytes to 0 for stable HMAC. */
mac_ptr = tdat->cmp_seg + sizeof (tdat->len_cmp) + cksum_bytes; mac_ptr = tdat->cmp_seg + sizeof (tdat->len_cmp) + cksum_bytes;
memset(mac_ptr, 0, mac_bytes); memset(mac_ptr, 0, mac_bytes);
hmac_reinit(&tdat->chunk_hmac); hmac_reinit(&tdat->chunk_hmac);
hmac_update(&tdat->chunk_hmac, tdat->cmp_seg, tdat->len_cmp); hmac_update(&tdat->chunk_hmac, tdat->cmp_seg, rbytes);
if (type & CHSIZE_MASK)
hmac_update(&tdat->chunk_hmac,
tdat->cmp_seg + tdat->len_cmp - ORIGINAL_CHUNKSZ,
ORIGINAL_CHUNKSZ);
hmac_final(&tdat->chunk_hmac, chash, &hlen); hmac_final(&tdat->chunk_hmac, chash, &hlen);
serialize_checksum(chash, mac_ptr, hlen); serialize_checksum(chash, mac_ptr, hlen);
} }