diff --git a/CMakeLists.txt b/CMakeLists.txt index fbd812c..d8ad7c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,6 @@ set(CMAKE_C_STANDARD 99) add_compile_definitions(__STDC_FORMAT_MACROS=1) add_library(libdicformat SHARED include/dicformat/consts.h include/dicformat/enums.h include/dic.h include/dicformat.h - include/dicformat/decls.h include/dicformat/structs.h src/identify.c src/open.c include/dicformat/context.h src/close.c include/dicformat/errors.h src/read.c) + include/dicformat/decls.h include/dicformat/structs.h src/identify.c src/open.c include/dicformat/context.h src/close.c include/dicformat/errors.h src/read.c src/crc64.c) include_directories(include include/dicformat) \ No newline at end of file diff --git a/include/dicformat/consts.h b/include/dicformat/consts.h index f254cce..28d024c 100644 --- a/include/dicformat/consts.h +++ b/include/dicformat/consts.h @@ -56,6 +56,9 @@ /** This mask is to check for position in CompactDisc suffix/prefix deduplicated block */ #define CD_DFIX_MASK 0x00FFFFFF +#define CRC64_ECMA_POLY 0xC96C5795D7870F42 +#define CRC64_ECMA_SEED 0xFFFFFFFFFFFFFFFF + #endif //LIBDICFORMAT_CONSTS_H #pragma clang diagnostic pop \ No newline at end of file diff --git a/include/dicformat/decls.h b/include/dicformat/decls.h index a414cf8..ae02976 100644 --- a/include/dicformat/decls.h +++ b/include/dicformat/decls.h @@ -46,5 +46,16 @@ int close(void *context); uint8_t *read_media_tag(void *context, int tag); +void *crc64_init(uint64_t polynomial, uint64_t seed); + +void *crc64_init_ecma(void); + +void crc64_update(void *context, const char *data, size_t len); + +uint64_t crc64_final(void *context); + +uint64_t crc64_data(const char *data, size_t len, uint64_t polynomial, uint64_t seed); + +uint64_t crc64_data_ecma(const char *data, size_t len); #endif //LIBDICFORMAT_DECLS_H diff --git a/include/dicformat/structs.h b/include/dicformat/structs.h index d7087bd..4db007c 100644 --- a/include/dicformat/structs.h +++ b/include/dicformat/structs.h @@ -302,6 +302,12 @@ typedef struct ChecksumEntry uint32_t length; } ChecksumEntry; +typedef struct Crc64Context +{ + uint64_t finalSeed; + uint64_t table[256]; + uint64_t hashInt; +} Crc64Context; #pragma pack(pop) diff --git a/src/crc64.c b/src/crc64.c new file mode 100644 index 0000000..275f16a --- /dev/null +++ b/src/crc64.c @@ -0,0 +1,115 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : crc64.c +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements a CRC64 algorithm. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2019 Natalia Portillo +// ****************************************************************************/ + +#include +#include +#include +#include + +void *crc64_init(uint64_t polynomial, uint64_t seed) +{ + Crc64Context *ctx; + + ctx = malloc(sizeof(Crc64Context)); + + if(ctx == NULL) + return NULL; + + memset(ctx, 1, sizeof(Crc64Context)); + + ctx->finalSeed = seed; + ctx->hashInt = seed; + + for(int i = 0; i < 256; i++) + { + uint64_t entry = (uint64_t)i; + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry = entry >> 1; + + ctx->table[i] = entry; + } + + return ctx; +} + +void *crc64_init_ecma(void) +{ + return crc64_init(CRC64_ECMA_POLY, CRC64_ECMA_SEED); +} + + +void crc64_update(void *context, const char *data, size_t len) +{ + Crc64Context *ctx = context; + + for(size_t i = 0; i < len; i++) + ctx->hashInt = (ctx->hashInt >> 8) ^ ctx->table[data[i] ^ (ctx->hashInt & 0xFF)]; +} + +uint64_t crc64_final(void *context) +{ + Crc64Context *ctx = context; + + return ctx->hashInt ^ ctx->finalSeed; +} + +uint64_t crc64_data(const char *data, size_t len, uint64_t polynomial, uint64_t seed) +{ + uint64_t table[256]; + uint64_t hashInt = seed; + + for(int i = 0; i < 256; i++) + { + uint64_t entry = (uint64_t)i; + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry = entry >> 1; + + table[i] = entry; + } + + for(size_t i = 0; i < len; i++) + hashInt = (hashInt >> 8) ^ table[data[i] ^ (hashInt & 0xFF)]; + + return hashInt ^ seed; +} + +uint64_t crc64_data_ecma(const char *data, size_t len) +{ + return crc64_data(data, len, CRC64_ECMA_POLY, CRC64_ECMA_SEED); +} +