From: Evan Hunt Date: Mon, 10 Jun 2013 21:19:22 +0000 (-0700) Subject: [rt33746] use CRC64 for map file error detection X-Git-Tag: v9.10.0a1~300 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=e59937c7283216ca22ce6e7937b06eab6d97f4ac;p=thirdparty%2Fbind9.git [rt33746] use CRC64 for map file error detection 3591. [func] Use CRC-64 to detect map file corruption at load time. [RT #33746] --- diff --git a/CHANGES b/CHANGES index 4d7ed093f91..5bb157cf9a8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +3591. [func] Use CRC-64 to detect map file corruption at load + time. [RT #33746] + 3590. [bug] When using RRL on recursive servers, defer rate-limiting until after recursion is complete; also, use correct rcode for slipped NXDOMAIN diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h index 85976506086..85c3479df83 100644 --- a/lib/dns/include/dns/rbt.h +++ b/lib/dns/include/dns/rbt.h @@ -22,10 +22,10 @@ /*! \file dns/rbt.h */ +#include #include #include #include -#include #include @@ -154,11 +154,11 @@ typedef isc_result_t (*dns_rbtfindcallback_t)(dns_rbtnode_t *node, typedef isc_result_t (*dns_rbtdatawriter_t)(FILE *file, unsigned char *data, isc_uint32_t version, - isc_sha1_t *sha1); + isc_uint64_t *crc); typedef isc_result_t (*dns_rbtdatafixer_t)(dns_rbtnode_t *rbtnode, void *base, size_t offset, - isc_sha1_t *sha1); + isc_uint64_t *crc); /***** ***** Chain Info diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index 5692bca78aa..7bc31cd60a9 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -28,13 +28,13 @@ #include /* uintptr_t */ #endif +#include #include #include #include #include #include #include -#include #include #include #include @@ -119,7 +119,7 @@ struct file_header { unsigned int bigendian:1; /* big or little endian system */ unsigned int rdataset_fixed:1; /* compiled with --enable-rrset-fixed */ unsigned int nodecount; /* shadow from rbt structure */ - unsigned char digest[ISC_SHA1_DIGESTLENGTH]; + isc_uint64_t crc; char version2[32]; /* repeated; must match version1 */ }; @@ -147,17 +147,17 @@ dns_rbt_zero_header(FILE *file); static isc_result_t write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset, - unsigned char *digest); + isc_uint64_t crc); static isc_result_t serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left, uintptr_t right, uintptr_t down, uintptr_t parent, - uintptr_t data, isc_sha1_t *sha1); + uintptr_t data, isc_uint64_t *crc); static isc_result_t serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, dns_rbtdatawriter_t datawriter, isc_uint32_t serial, - uintptr_t *where, isc_sha1_t *sha1); + uintptr_t *where, isc_uint64_t *crc); /* * The following functions allow you to get the actual address of a pointer * without having to use an if statement to check to see if that address is @@ -370,7 +370,7 @@ deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp); static isc_result_t treefix(dns_rbt_t *rbt, void *base, size_t size, dns_rbtnode_t *n, dns_name_t *name, - dns_rbtdatafixer_t datafixer, isc_sha1_t *sha1); + dns_rbtdatafixer_t datafixer, isc_uint64_t *crc); static isc_result_t deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node); @@ -415,7 +415,7 @@ dns_rbt_zero_header(FILE *file) { */ static isc_result_t write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset, - unsigned char *digest) + isc_uint64_t crc) { file_header_t header; isc_result_t result; @@ -442,7 +442,7 @@ write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset, header.nodecount = rbt->nodecount; - memcpy(header.digest, digest, sizeof(header.digest)); + header.crc = crc; location = ftell(file); if (location < 0) @@ -462,7 +462,7 @@ write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset, static isc_result_t serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left, uintptr_t right, uintptr_t down, uintptr_t parent, - uintptr_t data, isc_sha1_t *sha1) + uintptr_t data, isc_uint64_t *crc) { dns_rbtnode_t temp_node; long file_position; @@ -535,9 +535,9 @@ serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left, hexdump("node data", node_data, datasize); #endif - isc_sha1_update(sha1, (const isc_uint8_t *) &temp_node, + isc_crc64_update(crc, (const isc_uint8_t *) &temp_node, sizeof(dns_rbtnode_t)); - isc_sha1_update(sha1, (const isc_uint8_t *) node_data, datasize); + isc_crc64_update(crc, (const isc_uint8_t *) node_data, datasize); cleanup: return (result); @@ -546,7 +546,7 @@ serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left, static isc_result_t serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, dns_rbtdatawriter_t datawriter, isc_uint32_t serial, - uintptr_t *where, isc_sha1_t *sha1) + uintptr_t *where, isc_uint64_t *crc) { uintptr_t left = 0, right = 0, down = 0, data = 0; long location = 0; @@ -576,14 +576,14 @@ serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, * Serialize the rest of the tree. * * WARNING: A change in the order (from left, right, down) - * will break the way the sha1 hash is computed. + * will break the way the crc hash is computed. */ CHECK(serialize_nodes(file, getleft(node, NULL), location, - datawriter, serial, &left, sha1)); + datawriter, serial, &left, crc)); CHECK(serialize_nodes(file, getright(node, NULL), location, - datawriter, serial, &right, sha1)); + datawriter, serial, &right, crc)); CHECK(serialize_nodes(file, getdown(node, NULL), location, - datawriter, serial, &down, sha1)); + datawriter, serial, &down, crc)); if (node->data != NULL) { long ret; @@ -600,15 +600,14 @@ serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, return (ISC_R_FAILURE); data = ret; - datawriter(file, node->data, serial, sha1); + datawriter(file, node->data, serial, crc); } /* Seek back to reserved space. */ CHECK(isc_stdio_seek(file, location, SEEK_SET)); /* Serialize the current node. */ - CHECK(serialize_node(file, node, left, right, down, parent, data, - sha1)); + CHECK(serialize_node(file, node, left, right, down, parent, data, crc)); /* Ensure we are always at the end of the file. */ CHECK(isc_stdio_seek(file, 0, SEEK_END)); @@ -637,14 +636,13 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt, { isc_result_t result; long header_position, node_position, end_position; - unsigned char digest[ISC_SHA1_DIGESTLENGTH]; - isc_sha1_t sha1; + isc_uint64_t crc; REQUIRE(file != NULL); CHECK(isc_file_isplainfilefd(fileno(file))); - isc_sha1_init(&sha1); + isc_crc64_init(&crc); header_position = ftell(file); if (header_position < 0) @@ -658,8 +656,8 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt, if (node_position < 0) return (ISC_R_FAILURE); - CHECK(serialize_nodes(file, rbt->root, 0, datawriter, serial, NULL, - &sha1)); + CHECK(serialize_nodes(file, rbt->root, 0, datawriter, + serial, NULL, &crc)); end_position = ftell(file); if (end_position < 0) return (ISC_R_FAILURE); @@ -670,14 +668,14 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt, return (ISC_R_SUCCESS); } - isc_sha1_final(&sha1, digest); + isc_crc64_final(&crc); #ifdef DEBUG - hexdump("serializing digest", digest, sizeof(digest)); + hexdump("serializing CRC", crc, sizeof(crc)); #endif /* Serialize header */ CHECK(isc_stdio_seek(file, header_position, SEEK_SET)); - CHECK(write_header(file, rbt, HEADER_LENGTH, digest)); + CHECK(write_header(file, rbt, HEADER_LENGTH, crc)); /* Ensure we are always at the end of the file. */ CHECK(isc_stdio_seek(file, 0, SEEK_END)); @@ -696,7 +694,7 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt, static isc_result_t treefix(dns_rbt_t *rbt, void *base, size_t filesize, dns_rbtnode_t *n, - dns_name_t *name, dns_rbtdatafixer_t datafixer, isc_sha1_t *sha1) + dns_name_t *name, dns_rbtdatafixer_t datafixer, isc_uint64_t *crc) { isc_result_t result = ISC_R_SUCCESS; dns_fixedname_t fixed; @@ -774,16 +772,16 @@ treefix(dns_rbt_t *rbt, void *base, size_t filesize, dns_rbtnode_t *n, /* a change in the order (from left, right, down) will break hashing*/ if (n->left != NULL) CHECK(treefix(rbt, base, filesize, n->left, name, - datafixer, sha1)); + datafixer, crc)); if (n->right != NULL) CHECK(treefix(rbt, base, filesize, n->right, name, - datafixer, sha1)); + datafixer, crc)); if (n->down != NULL) CHECK(treefix(rbt, base, filesize, n->down, fullname, - datafixer, sha1)); + datafixer, crc)); if (datafixer != NULL && n->data != NULL) - CHECK(datafixer(n, base, filesize, sha1)); + CHECK(datafixer(n, base, filesize, crc)); rbt->nodecount++; node_data = (unsigned char *) n + sizeof(dns_rbtnode_t); @@ -797,9 +795,9 @@ treefix(dns_rbt_t *rbt, void *base, size_t filesize, dns_rbtnode_t *n, sizeof(dns_rbtnode_t)); hexdump("node data", node_data, datasize); #endif - isc_sha1_update(sha1, (const isc_uint8_t *) &header, + isc_crc64_update(crc, (const isc_uint8_t *) &header, sizeof(dns_rbtnode_t)); - isc_sha1_update(sha1, (const isc_uint8_t *) node_data, + isc_crc64_update(crc, (const isc_uint8_t *) node_data, datasize); cleanup: @@ -816,14 +814,13 @@ dns_rbt_deserialize_tree(void *base_address, size_t filesize, { isc_result_t result = ISC_R_SUCCESS; file_header_t *header; - unsigned char digest[ISC_SHA1_DIGESTLENGTH]; dns_rbt_t *rbt = NULL; - isc_sha1_t sha1; + isc_uint64_t crc; REQUIRE(originp == NULL || *originp == NULL); REQUIRE(rbtp != NULL && *rbtp == NULL); - isc_sha1_init(&sha1); + isc_crc64_init(&crc); CHECK(dns_rbt_create(mctx, deleter, deleter_arg, &rbt)); @@ -864,15 +861,15 @@ dns_rbt_deserialize_tree(void *base_address, size_t filesize, rehash(rbt, header->nodecount); CHECK(treefix(rbt, base_address, filesize, rbt->root, - dns_rootname, datafixer, &sha1)); + dns_rootname, datafixer, &crc)); - isc_sha1_final(&sha1, digest); + isc_crc64_final(&crc); #ifdef DEBUG - hexdump("deserializing digest", digest, sizeof(digest)); + hexdump("deserializing CRC", crc, sizeof(crc)); #endif /* Check file hash */ - if (memcmp(header->digest, digest, sizeof(digest)) != 0) { + if (header->crc != crc) { result = ISC_R_INVALIDFILE; goto cleanup; } diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index eb7221b521f..de78f75361e 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -27,6 +27,7 @@ /* #define inline */ +#include #include #include #include @@ -6997,7 +6998,7 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) { static isc_result_t rbt_datafixer(dns_rbtnode_t *rbtnode, void *base, size_t filesize, - isc_sha1_t *sha1) + isc_uint64_t *crc) { rdatasetheader_t *header; unsigned char *limit = ((unsigned char *) base) + filesize; @@ -7010,7 +7011,7 @@ rbt_datafixer(dns_rbtnode_t *rbtnode, void *base, size_t filesize, p = (unsigned char *) header; size = dns_rdataslab_size(p, sizeof(*header)); - isc_sha1_update(sha1, p, size); + isc_crc64_update(crc, p, size); #ifdef DEBUG hexdump("hashing header", p, sizeof(rdatasetheader_t)); hexdump("hashing slab", p + sizeof(rdatasetheader_t), @@ -7224,7 +7225,8 @@ endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { */ static isc_result_t rbt_datawriter(FILE *rbtfile, unsigned char *data, isc_uint32_t serial, - isc_sha1_t *sha1) { + isc_uint64_t *crc) +{ rdatasetheader_t newheader; rdatasetheader_t *header = (rdatasetheader_t *) data, *next; size_t where, size, cooked; @@ -7277,16 +7279,16 @@ rbt_datawriter(FILE *rbtfile, unsigned char *data, isc_uint32_t serial, hexdump("writing slab", p + sizeof(rdatasetheader_t), size - sizeof(rdatasetheader_t)); #endif - isc_sha1_update(sha1, (unsigned char *) &newheader, - sizeof(rdatasetheader_t)); + isc_crc64_update(crc, (unsigned char *) &newheader, + sizeof(rdatasetheader_t)); result = isc_stdio_write(&newheader, sizeof(rdatasetheader_t), 1, rbtfile, NULL); if (result != ISC_R_SUCCESS) return (result); - isc_sha1_update(sha1, p + sizeof(rdatasetheader_t), - size - sizeof(rdatasetheader_t)); + isc_crc64_update(crc, p + sizeof(rdatasetheader_t), + size - sizeof(rdatasetheader_t)); result = isc_stdio_write(p + sizeof(rdatasetheader_t), size - sizeof(rdatasetheader_t), 1, rbtfile, NULL); if (result != ISC_R_SUCCESS) diff --git a/lib/dns/tests/rbt_test.c b/lib/dns/tests/rbt_test.c index d74c502e0ce..0fef45897b7 100644 --- a/lib/dns/tests/rbt_test.c +++ b/lib/dns/tests/rbt_test.c @@ -107,7 +107,7 @@ delete_data(void *data, void *arg) { static isc_result_t write_data(FILE *file, unsigned char *datap, isc_uint32_t serial, - isc_sha1_t *sha1) { + isc_uint64_t *crc) { size_t ret = 0; data_holder_t *data = (data_holder_t *)datap; data_holder_t temp; @@ -115,7 +115,7 @@ write_data(FILE *file, unsigned char *datap, isc_uint32_t serial, UNUSED(serial); - REQUIRE(sha1 != NULL); + REQUIRE(crc != NULL); REQUIRE(data != NULL); REQUIRE((data->len == 0 && data->data == NULL) || (data->len != 0 && data->data != NULL)); @@ -125,12 +125,12 @@ write_data(FILE *file, unsigned char *datap, isc_uint32_t serial, ? NULL : (char *)(where + sizeof(data_holder_t))); - isc_sha1_update(sha1, (void *)&temp, sizeof(temp)); + isc_crc64_update(crc, (void *)&temp, sizeof(temp)); ret = fwrite(&temp, sizeof(data_holder_t), 1, file); if (ret != 1) return (ISC_R_FAILURE); if (data->len > 0) { - isc_sha1_update(sha1, (const void *)data->data, data->len); + isc_crc64_update(crc, (const void *)data->data, data->len); ret = fwrite(data->data, data->len, 1, file); if (ret != 1) return (ISC_R_FAILURE); @@ -140,14 +140,14 @@ write_data(FILE *file, unsigned char *datap, isc_uint32_t serial, } static isc_result_t -fix_data(dns_rbtnode_t *p, void *base, size_t max, isc_sha1_t *sha1) { +fix_data(dns_rbtnode_t *p, void *base, size_t max, isc_uint64_t *crc) { data_holder_t *data = p->data; size_t size; UNUSED(base); UNUSED(max); - REQUIRE(sha1 != NULL); + REQUIRE(crc != NULL); REQUIRE(p != NULL); @@ -168,14 +168,14 @@ fix_data(dns_rbtnode_t *p, void *base, size_t max, isc_sha1_t *sha1) { return (ISC_R_INVALIDFILE); } - isc_sha1_update(sha1, (void *)data, sizeof(*data)); + isc_crc64_update(crc, (void *)data, sizeof(*data)); data->data = (data->len == 0) ? NULL : (char *)data + sizeof(data_holder_t); if (data->len > 0) - isc_sha1_update(sha1, (const void *)data->data, data->len); + isc_crc64_update(crc, (const void *)data->data, data->len); return (ISC_R_SUCCESS); } diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index b6b206f2163..7dff06cc7d0 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -53,7 +53,7 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ OBJS = @ISC_EXTRA_OBJS@ \ assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \ bind9.@O@ bitstring.@O@ buffer.@O@ bufferlist.@O@ \ - commandline.@O@ error.@O@ event.@O@ \ + commandline.@O@ crc64.@O@ error.@O@ event.@O@ \ hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \ lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \ @@ -70,7 +70,7 @@ SYMTBLOBJS = backtrace-emptytbl.@O@ # Alphabetically SRCS = @ISC_EXTRA_SRCS@ \ assertions.c backtrace.c base32.c base64.c bind9.c \ - bitstring.c buffer.c bufferlist.c commandline.c \ + bitstring.c buffer.c bufferlist.c commandline.c crc64.c \ error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \ httpd.c inet_aton.c iterated_hash.c \ lex.c lfsr.c lib.c log.c \ diff --git a/lib/isc/crc64.c b/lib/isc/crc64.c new file mode 100644 index 00000000000..e83cdc02a46 --- /dev/null +++ b/lib/isc/crc64.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +/*%< + * ECMA-182 CRC64 polynomial. + */ +static const isc_uint64_t crc64_table[256] = { + 0x0000000000000000ULL, 0x42F0E1EBA9EA3693ULL, 0x85E1C3D753D46D26ULL, + 0xC711223CFA3E5BB5ULL, 0x493366450E42ECDFULL, 0x0BC387AEA7A8DA4CULL, + 0xCCD2A5925D9681F9ULL, 0x8E224479F47CB76AULL, 0x9266CC8A1C85D9BEULL, + 0xD0962D61B56FEF2DULL, 0x17870F5D4F51B498ULL, 0x5577EEB6E6BB820BULL, + 0xDB55AACF12C73561ULL, 0x99A54B24BB2D03F2ULL, 0x5EB4691841135847ULL, + 0x1C4488F3E8F96ED4ULL, 0x663D78FF90E185EFULL, 0x24CD9914390BB37CULL, + 0xE3DCBB28C335E8C9ULL, 0xA12C5AC36ADFDE5AULL, 0x2F0E1EBA9EA36930ULL, + 0x6DFEFF5137495FA3ULL, 0xAAEFDD6DCD770416ULL, 0xE81F3C86649D3285ULL, + 0xF45BB4758C645C51ULL, 0xB6AB559E258E6AC2ULL, 0x71BA77A2DFB03177ULL, + 0x334A9649765A07E4ULL, 0xBD68D2308226B08EULL, 0xFF9833DB2BCC861DULL, + 0x388911E7D1F2DDA8ULL, 0x7A79F00C7818EB3BULL, 0xCC7AF1FF21C30BDEULL, + 0x8E8A101488293D4DULL, 0x499B3228721766F8ULL, 0x0B6BD3C3DBFD506BULL, + 0x854997BA2F81E701ULL, 0xC7B97651866BD192ULL, 0x00A8546D7C558A27ULL, + 0x4258B586D5BFBCB4ULL, 0x5E1C3D753D46D260ULL, 0x1CECDC9E94ACE4F3ULL, + 0xDBFDFEA26E92BF46ULL, 0x990D1F49C77889D5ULL, 0x172F5B3033043EBFULL, + 0x55DFBADB9AEE082CULL, 0x92CE98E760D05399ULL, 0xD03E790CC93A650AULL, + 0xAA478900B1228E31ULL, 0xE8B768EB18C8B8A2ULL, 0x2FA64AD7E2F6E317ULL, + 0x6D56AB3C4B1CD584ULL, 0xE374EF45BF6062EEULL, 0xA1840EAE168A547DULL, + 0x66952C92ECB40FC8ULL, 0x2465CD79455E395BULL, 0x3821458AADA7578FULL, + 0x7AD1A461044D611CULL, 0xBDC0865DFE733AA9ULL, 0xFF3067B657990C3AULL, + 0x711223CFA3E5BB50ULL, 0x33E2C2240A0F8DC3ULL, 0xF4F3E018F031D676ULL, + 0xB60301F359DBE0E5ULL, 0xDA050215EA6C212FULL, 0x98F5E3FE438617BCULL, + 0x5FE4C1C2B9B84C09ULL, 0x1D14202910527A9AULL, 0x93366450E42ECDF0ULL, + 0xD1C685BB4DC4FB63ULL, 0x16D7A787B7FAA0D6ULL, 0x5427466C1E109645ULL, + 0x4863CE9FF6E9F891ULL, 0x0A932F745F03CE02ULL, 0xCD820D48A53D95B7ULL, + 0x8F72ECA30CD7A324ULL, 0x0150A8DAF8AB144EULL, 0x43A04931514122DDULL, + 0x84B16B0DAB7F7968ULL, 0xC6418AE602954FFBULL, 0xBC387AEA7A8DA4C0ULL, + 0xFEC89B01D3679253ULL, 0x39D9B93D2959C9E6ULL, 0x7B2958D680B3FF75ULL, + 0xF50B1CAF74CF481FULL, 0xB7FBFD44DD257E8CULL, 0x70EADF78271B2539ULL, + 0x321A3E938EF113AAULL, 0x2E5EB66066087D7EULL, 0x6CAE578BCFE24BEDULL, + 0xABBF75B735DC1058ULL, 0xE94F945C9C3626CBULL, 0x676DD025684A91A1ULL, + 0x259D31CEC1A0A732ULL, 0xE28C13F23B9EFC87ULL, 0xA07CF2199274CA14ULL, + 0x167FF3EACBAF2AF1ULL, 0x548F120162451C62ULL, 0x939E303D987B47D7ULL, + 0xD16ED1D631917144ULL, 0x5F4C95AFC5EDC62EULL, 0x1DBC74446C07F0BDULL, + 0xDAAD56789639AB08ULL, 0x985DB7933FD39D9BULL, 0x84193F60D72AF34FULL, + 0xC6E9DE8B7EC0C5DCULL, 0x01F8FCB784FE9E69ULL, 0x43081D5C2D14A8FAULL, + 0xCD2A5925D9681F90ULL, 0x8FDAB8CE70822903ULL, 0x48CB9AF28ABC72B6ULL, + 0x0A3B7B1923564425ULL, 0x70428B155B4EAF1EULL, 0x32B26AFEF2A4998DULL, + 0xF5A348C2089AC238ULL, 0xB753A929A170F4ABULL, 0x3971ED50550C43C1ULL, + 0x7B810CBBFCE67552ULL, 0xBC902E8706D82EE7ULL, 0xFE60CF6CAF321874ULL, + 0xE224479F47CB76A0ULL, 0xA0D4A674EE214033ULL, 0x67C58448141F1B86ULL, + 0x253565A3BDF52D15ULL, 0xAB1721DA49899A7FULL, 0xE9E7C031E063ACECULL, + 0x2EF6E20D1A5DF759ULL, 0x6C0603E6B3B7C1CAULL, 0xF6FAE5C07D3274CDULL, + 0xB40A042BD4D8425EULL, 0x731B26172EE619EBULL, 0x31EBC7FC870C2F78ULL, + 0xBFC9838573709812ULL, 0xFD39626EDA9AAE81ULL, 0x3A28405220A4F534ULL, + 0x78D8A1B9894EC3A7ULL, 0x649C294A61B7AD73ULL, 0x266CC8A1C85D9BE0ULL, + 0xE17DEA9D3263C055ULL, 0xA38D0B769B89F6C6ULL, 0x2DAF4F0F6FF541ACULL, + 0x6F5FAEE4C61F773FULL, 0xA84E8CD83C212C8AULL, 0xEABE6D3395CB1A19ULL, + 0x90C79D3FEDD3F122ULL, 0xD2377CD44439C7B1ULL, 0x15265EE8BE079C04ULL, + 0x57D6BF0317EDAA97ULL, 0xD9F4FB7AE3911DFDULL, 0x9B041A914A7B2B6EULL, + 0x5C1538ADB04570DBULL, 0x1EE5D94619AF4648ULL, 0x02A151B5F156289CULL, + 0x4051B05E58BC1E0FULL, 0x87409262A28245BAULL, 0xC5B073890B687329ULL, + 0x4B9237F0FF14C443ULL, 0x0962D61B56FEF2D0ULL, 0xCE73F427ACC0A965ULL, + 0x8C8315CC052A9FF6ULL, 0x3A80143F5CF17F13ULL, 0x7870F5D4F51B4980ULL, + 0xBF61D7E80F251235ULL, 0xFD913603A6CF24A6ULL, 0x73B3727A52B393CCULL, + 0x31439391FB59A55FULL, 0xF652B1AD0167FEEAULL, 0xB4A25046A88DC879ULL, + 0xA8E6D8B54074A6ADULL, 0xEA16395EE99E903EULL, 0x2D071B6213A0CB8BULL, + 0x6FF7FA89BA4AFD18ULL, 0xE1D5BEF04E364A72ULL, 0xA3255F1BE7DC7CE1ULL, + 0x64347D271DE22754ULL, 0x26C49CCCB40811C7ULL, 0x5CBD6CC0CC10FAFCULL, + 0x1E4D8D2B65FACC6FULL, 0xD95CAF179FC497DAULL, 0x9BAC4EFC362EA149ULL, + 0x158E0A85C2521623ULL, 0x577EEB6E6BB820B0ULL, 0x906FC95291867B05ULL, + 0xD29F28B9386C4D96ULL, 0xCEDBA04AD0952342ULL, 0x8C2B41A1797F15D1ULL, + 0x4B3A639D83414E64ULL, 0x09CA82762AAB78F7ULL, 0x87E8C60FDED7CF9DULL, + 0xC51827E4773DF90EULL, 0x020905D88D03A2BBULL, 0x40F9E43324E99428ULL, + 0x2CFFE7D5975E55E2ULL, 0x6E0F063E3EB46371ULL, 0xA91E2402C48A38C4ULL, + 0xEBEEC5E96D600E57ULL, 0x65CC8190991CB93DULL, 0x273C607B30F68FAEULL, + 0xE02D4247CAC8D41BULL, 0xA2DDA3AC6322E288ULL, 0xBE992B5F8BDB8C5CULL, + 0xFC69CAB42231BACFULL, 0x3B78E888D80FE17AULL, 0x7988096371E5D7E9ULL, + 0xF7AA4D1A85996083ULL, 0xB55AACF12C735610ULL, 0x724B8ECDD64D0DA5ULL, + 0x30BB6F267FA73B36ULL, 0x4AC29F2A07BFD00DULL, 0x08327EC1AE55E69EULL, + 0xCF235CFD546BBD2BULL, 0x8DD3BD16FD818BB8ULL, 0x03F1F96F09FD3CD2ULL, + 0x41011884A0170A41ULL, 0x86103AB85A2951F4ULL, 0xC4E0DB53F3C36767ULL, + 0xD8A453A01B3A09B3ULL, 0x9A54B24BB2D03F20ULL, 0x5D45907748EE6495ULL, + 0x1FB5719CE1045206ULL, 0x919735E51578E56CULL, 0xD367D40EBC92D3FFULL, + 0x1476F63246AC884AULL, 0x568617D9EF46BED9ULL, 0xE085162AB69D5E3CULL, + 0xA275F7C11F7768AFULL, 0x6564D5FDE549331AULL, 0x279434164CA30589ULL, + 0xA9B6706FB8DFB2E3ULL, 0xEB46918411358470ULL, 0x2C57B3B8EB0BDFC5ULL, + 0x6EA7525342E1E956ULL, 0x72E3DAA0AA188782ULL, 0x30133B4B03F2B111ULL, + 0xF7021977F9CCEAA4ULL, 0xB5F2F89C5026DC37ULL, 0x3BD0BCE5A45A6B5DULL, + 0x79205D0E0DB05DCEULL, 0xBE317F32F78E067BULL, 0xFCC19ED95E6430E8ULL, + 0x86B86ED5267CDBD3ULL, 0xC4488F3E8F96ED40ULL, 0x0359AD0275A8B6F5ULL, + 0x41A94CE9DC428066ULL, 0xCF8B0890283E370CULL, 0x8D7BE97B81D4019FULL, + 0x4A6ACB477BEA5A2AULL, 0x089A2AACD2006CB9ULL, 0x14DEA25F3AF9026DULL, + 0x562E43B4931334FEULL, 0x913F6188692D6F4BULL, 0xD3CF8063C0C759D8ULL, + 0x5DEDC41A34BBEEB2ULL, 0x1F1D25F19D51D821ULL, + 0xD80C07CD676F8394ULL, 0x9AFCE626CE85B507ULL +}; + +void +isc_crc64_init(isc_uint64_t *crc) { + REQUIRE(crc != NULL); + + *crc = 0xffffffffffffffffULL; +} + +void +isc_crc64_update(isc_uint64_t *crc, const isc_uint8_t *data, size_t len) { + unsigned char *p = data; + int i; + + REQUIRE(crc != NULL); + REQUIRE(data != NULL); + + while (len-- > 0) { + i = ((int) (*crc >> 56) ^ *p++) & 0xff; + *crc = crc64_table[i] ^ (*crc << 8); + } +} + + +void +isc_crc64_final(isc_uint64_t *crc) { + REQUIRE(crc != NULL); + + *crc ^= 0xffffffffffffffffULL; +} diff --git a/lib/isc/include/isc/crc64.h b/lib/isc/include/isc/crc64.h new file mode 100644 index 00000000000..0403fec08e6 --- /dev/null +++ b/lib/isc/include/isc/crc64.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef ISC_CRC64_H +#define ISC_CRC64_H 1 + +/*! \file isc/crc64.h + * \brief CRC64 in C + */ + +#include +#include + +ISC_LANG_BEGINDECLS + +void +isc_crc64_init(isc_uint64_t *crc); +/*% + * Initialize a new CRC. + * + * Requires: + * * 'crc' is not NULL. + */ + +void +isc_crc64_update(isc_uint64_t *crc, const isc_uint8_t *data, size_t len); +/*% + * Add data to the CRC. + * + * Requires: + * * 'crc' is not NULL. + * * 'data' is not NULL. + */ + +void +isc_crc64_final(isc_uint64_t *crc); +/*% + * Finalize the CRC. + * + * Requires: + * * 'crc' is not NULL. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_CRC64_H */ diff --git a/lib/isc/tests/hash_test.c b/lib/isc/tests/hash_test.c index 836d7b67abc..b3dc1d2d501 100644 --- a/lib/isc/tests/hash_test.c +++ b/lib/isc/tests/hash_test.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -1784,6 +1785,67 @@ ATF_TC_BODY(isc_hmacmd5, tc) { } } +/* CRC64 Test */ +ATF_TC(isc_crc64); +ATF_TC_HEAD(isc_crc64, tc) { + atf_tc_set_md_var(tc, "descr", "64-bit cyclic redundancy check"); +} +ATF_TC_BODY(isc_crc64, tc) { + isc_uint64_t crc; + + UNUSED(tc); + + hash_testcase_t testcases[] = { + { + TEST_INPUT(""), + "0x0000000000000000", 1 + }, + { + TEST_INPUT("a"), + "0x9AA9C0AC27F473CE", 1 + }, + { + TEST_INPUT("abc"), + "0x0297F4F93A818B04", 1 + }, + { + TEST_INPUT("message digest"), + "0xF47B357AEAF97352", 1 + }, + { + TEST_INPUT("abcdefghijklmnopqrstuvwxyz"), + "0xA1AA8B21F979F059", 1 + }, + { + TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm" + "nopqrstuvwxyz0123456789"), + "0xFBB6781EF7A86DA3", 1 + }, + { + TEST_INPUT("123456789012345678901234567890123456789" + "01234567890123456789012345678901234567890"), + "0x4A87E7C873EBE581", 1 + }, + { NULL, 0, NULL, 1 } + }; + + hash_testcase_t *testcase = testcases; + + while (testcase->input != NULL && testcase->result != NULL) { + isc_crc64_init(&crc); + for(i = 0; i < testcase->repeats; i++) { + isc_crc64_update(&crc, + (const isc_uint8_t *) testcase->input, + testcase->input_len); + } + isc_crc64_final(&crc); + tohexstr((unsigned char *) &crc, sizeof(crc), str); + ATF_CHECK_STREQ(str, testcase->result); + + testcase++; + } +} + /* * Main */ @@ -1800,6 +1862,7 @@ ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, isc_sha256); ATF_TP_ADD_TC(tp, isc_sha384); ATF_TP_ADD_TC(tp, isc_sha512); + ATF_TP_ADD_TC(tp, isc_crc64); return (atf_no_error()); } diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def index 8a0b1f3d74c..5b383634a3f 100644 --- a/lib/isc/win32/libisc.def +++ b/lib/isc/win32/libisc.def @@ -192,6 +192,9 @@ isc_condition_init isc_condition_signal isc_condition_wait isc_condition_waituntil +isc_crc64_init +isc_crc64_update +isc_crc64_final isc_dir_chdir isc_dir_chroot isc_dir_close diff --git a/lib/isc/win32/libisc.dsp b/lib/isc/win32/libisc.dsp index 13fc7f13224..33519ae4d8c 100644 --- a/lib/isc/win32/libisc.dsp +++ b/lib/isc/win32/libisc.dsp @@ -103,6 +103,10 @@ SOURCE=.\condition.c # End Source File # Begin Source File +SOURCE=.\crc64.c +# End Source File +# Begin Source File + SOURCE=.\dir.c # End Source File # Begin Source File @@ -259,6 +263,10 @@ SOURCE=..\..\..\config.h # End Source File # Begin Source File +SOURCE=.\include\isc\crc64.h +# End Source File +# Begin Source File + SOURCE=.\include\isc\dir.h # End Source File # Begin Source File diff --git a/lib/isc/win32/libisc.mak b/lib/isc/win32/libisc.mak index 4e0766c08fc..714723699df 100644 --- a/lib/isc/win32/libisc.mak +++ b/lib/isc/win32/libisc.mak @@ -125,6 +125,7 @@ CLEAN : -@erase "$(INTDIR)\bufferlist.obj" -@erase "$(INTDIR)\commandline.obj" -@erase "$(INTDIR)\condition.obj" + -@erase "$(INTDIR)\crc64.obj" -@erase "$(INTDIR)\dir.obj" -@erase "$(INTDIR)\DLLMain.obj" -@erase "$(INTDIR)\entropy.obj" @@ -215,6 +216,7 @@ DEF_FILE= \ LINK32_OBJS= \ "$(INTDIR)\app.obj" \ "$(INTDIR)\condition.obj" \ + "$(INTDIR)\crc64.obj" \ "$(INTDIR)\dir.obj" \ "$(INTDIR)\DLLMain.obj" \ "$(INTDIR)\entropy.obj" \ @@ -333,6 +335,8 @@ CLEAN : -@erase "$(INTDIR)\commandline.sbr" -@erase "$(INTDIR)\condition.obj" -@erase "$(INTDIR)\condition.sbr" + -@erase "$(INTDIR)\crc64.obj" + -@erase "$(INTDIR)\crc64.sbr" -@erase "$(INTDIR)\dir.obj" -@erase "$(INTDIR)\dir.sbr" -@erase "$(INTDIR)\DLLMain.obj" @@ -490,6 +494,7 @@ BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisc.bsc" BSC32_SBRS= \ "$(INTDIR)\app.sbr" \ "$(INTDIR)\condition.sbr" \ + "$(INTDIR)\crc64.sbr" \ "$(INTDIR)\dir.sbr" \ "$(INTDIR)\DLLMain.sbr" \ "$(INTDIR)\entropy.sbr" \ @@ -580,6 +585,7 @@ DEF_FILE= \ LINK32_OBJS= \ "$(INTDIR)\app.obj" \ "$(INTDIR)\condition.obj" \ + "$(INTDIR)\crc64.obj" \ "$(INTDIR)\dir.obj" \ "$(INTDIR)\DLLMain.obj" \ "$(INTDIR)\entropy.obj" \ @@ -737,6 +743,22 @@ SOURCE=.\condition.c "$(INTDIR)\condition.obj" "$(INTDIR)\condition.sbr" : $(SOURCE) "$(INTDIR)" +!ENDIF + +SOURCE=.\crc64.c + +!IF "$(CFG)" == "libisc - Win32 Release" + + +"$(INTDIR)\crc64.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - Win32 Debug" + + +"$(INTDIR)\crc64.obj" "$(INTDIR)\crc64.sbr" : $(SOURCE) "$(INTDIR)" + + !ENDIF SOURCE=.\dir.c