diff -uNr a/vtools/Makefile b/vtools/Makefile --- a/vtools/Makefile 30959920906cdf36872b949334b762f96f0349ece83b040d67c1d551e4deb436aec54afe6767b1ef1e721d99550c72e3d2a5cc83537dc622d50ca93d9261e19d +++ b/vtools/Makefile 257066f00b2af8569e4b24cdf06fa376a6312d8f0568eecc83e6f4624d7c5109a51906fd5b2bc4f55840577939d86aa4173c0dd70160916998d528cff0f6a67b @@ -1,37 +1,7 @@ -CC:=gcc -LDFLAGS:=-static - -SOURCES=lib/cmpbuf.c \ - lib/dirname.c \ - lib/error.c \ - lib/filenamecat.c \ - lib/filetype.c \ - lib/hash.c \ - lib/progname.c \ - lib/xalloc.c \ - src/analyze.c \ - src/context.c \ - src/diff.c \ - src/dir.c \ - src/io.c \ - src/util.c -HEADERS=lib/cmpbuf.h \ - lib/diffseq.h \ - lib/dirname.h \ - lib/error.h \ - lib/filenamecat.h \ - lib/filetype.h \ - lib/hash.h \ - lib/progname.h \ - lib/xalloc.h \ - src/diff.h \ - src/system.h -OBJECTS=$(SRCS:.c=.o) - -vdiff: $(SOURCES) $(HEADERS) - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -std=c99 -pedantic -Ilib/ -Isrc/ -o $@ $(SOURCES) +vdiff: + gprbuild -Pvdiff.gpr clean: - @rm -f vdiff + gprclean -Pvdiff.gpr diff -uNr a/vtools/manifest b/vtools/manifest --- a/vtools/manifest 43da758a157603a39688c97d06334e49f948feab5856d837687030fca779c9e00a3d54cbdaf1b72561d72bc92dea5a15b0d28b2aab9d6e4f854f83d825cdbb48 +++ b/vtools/manifest 7896d8cc732aef7cbaae1c872dd824f51c5f6d1d23e42bb57ce03cf7b84664cc2140d4dbb9c70b72e14a1f82a59acdda3b7432e90423f0a8e93cf4fe5abf2e7f @@ -1,3 +1,4 @@ 510300 phf vtools_genesis Initial release of vtools. Genesis contains stripped down version of diffutils 3.6, with most of functionality not relevant to vpatch removed. 511300 phf vdiff_fixes_newline_gcc Fixes for C99 compatability, support for "No newline at end of file" directive. 511300 phf keccak Included diana_coman's keccak implementation. +511300 phf vdiff_keccak Vdiff hashing and output using Keccak instead of SHA512. diff -uNr a/vtools/obj/readme b/vtools/obj/readme --- a/vtools/obj/readme false +++ b/vtools/obj/readme a3e4d3d9afdbdf6c9b1d506a430b34e087290c3136ba1b459224be8a21ae926b4513a1e0eb44262908c3e5e93fc86ff8e80859d8632861d4b2367d68d21c76e1 @@ -0,0 +1 @@ +objs diff -uNr a/vtools/src/analyze.c b/vtools/src/analyze.c --- a/vtools/src/analyze.c 0626cff1e1871b60ebe1843368954151aa16905f5a26a3bc9a0e9df97eab432042377a5e85928ae3144f88800c8691fa7d6aa362529fa37ea789252c540fd520 +++ b/vtools/src/analyze.c 6111a6463c2500d9715fd7affd174d0ec942844ca2741c411573490b6d765b1f7fa90a7593cc98bb0a259da694dbc652979fc1f7a10d188838a0f2b473b18797 @@ -428,6 +428,8 @@ struct change *script; int changes; + cmp->file[0].hash_context = keccak_begin(); + cmp->file[1].hash_context = keccak_begin(); /* If we have detected that either file is binary, compare the two files as binary. This can happen only when the first chunk is diff -uNr a/vtools/src/context.c b/vtools/src/context.c --- a/vtools/src/context.c f5b3e5c736be0c6c4e4fdcc50e2a436c17d3e84fe47e6125dd0fa775c9cffcc625a98fe7091a036593e21cdafa1e533fd8a04640649cd6ed89da499c94333668 +++ b/vtools/src/context.c 6ed67d33234b4cc45910fc9d69c40c8dd7d205aeb7a5532eb83f5e889ea81556147b0d6689d46df52b9c58f82c56a1a4b255bf7d09095bcfa170a27ae8203a93 @@ -5,6 +5,18 @@ /* Print a label for a context diff, with a file name and date or a label. */ +const char bb_hexdigits_upcase[] = "0123456789ABCDEF"; +char *bin2hex(char *p, const char *cp, int count) { + while (count) { + unsigned char c = *cp++; + /* put lowercase hex digits */ + *p++ = 0x20 | bb_hexdigits_upcase[c >> 4]; + *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf]; + count--; + } + return p; +} + static void print_context_label(char const *mark, struct file_data *inf, @@ -13,7 +25,13 @@ if (label) fprintf(outfile, "%s %s\n", mark, label); else { - fprintf(outfile, "%s %s false\n", mark, name); + if (inf->desc >= 0) { + char buf[(64 * 2) + 1] = {0}; + bin2hex(buf, (char*) inf->hash, 64); + fprintf(outfile, "%s %s %s\n", mark, name, buf); + } else { + fprintf(outfile, "%s %s false\n", mark, name); + } } } diff -uNr a/vtools/src/diff.c b/vtools/src/diff.c --- a/vtools/src/diff.c 908272f9a1c8a15cac809a9c6dbf96f7cd60b40bc3ebad0f1df368f6d5dfa10da38e7e6f8cd09dc994e2291b95334c7768d885633536302e3c47181452a2b839 +++ b/vtools/src/diff.c cce12bcfaf2c0c0b5140fc73bfd82c84edab99ee848b7166d26fb22e564013af74f3a9638949b176767b3ff50c0149c9992337610d6a03dc826f083b2ec1ef31 @@ -69,6 +69,7 @@ uintmax_t numval; char *numend; set_program_name(argv[0]); + adainit(); /* Decode the options. */ @@ -195,6 +196,7 @@ } } + adafinal(); check_stdout(); exit(exit_status); return exit_status; diff -uNr a/vtools/src/diff.h b/vtools/src/diff.h --- a/vtools/src/diff.h 8389679f305c168b019adb6ae495f60c1b71efc35052d94b6672829b437e0607e77d66d457c81128110b6ecefcfc41adb55efab8af91e9b7c76daf5597ef08f6 +++ b/vtools/src/diff.h 44c9fe46bbb893b8d2a808922ac56c999d6f61d79f0831293894d17ea9b26332fcc525d41a42a1273ee336bb5fc6bffcff9dbf339195d75999de019b799d891a @@ -2,6 +2,7 @@ #include #include #include +#include "keccak.h" /* What kind of changes a hunk contains. */ enum changes { @@ -158,6 +159,10 @@ /* 1 more than the maximum equivalence value used for this or its sibling file. */ lin equiv_max; + + /* keccak context */ + void *hash_context; + uint64_t hash[8]; }; /* The file buffer, considered as an array of bytes rather than as an diff -uNr a/vtools/src/io.c b/vtools/src/io.c --- a/vtools/src/io.c 7106411c84c6bc2d4ea1027d66b6b1a6278106c5fc2d9c4f990d8d4d762eddeda8eac3441bf3b40129167750b56d210228c2a0e437a707e89fe32de1a4237e99 +++ b/vtools/src/io.c 2fc0ab62ce34c963d194931a5f1f9d769d494c29597ea003a768bc0be4a1d511536a6bdecf4e6a87cf73d73f9287af617b016212d0f034089a5745cd1dd6fe72 @@ -57,8 +57,16 @@ if (s == SIZE_MAX) pfatal_with_name(current->name); + if (s) + keccak_hash(current->hash_context, + FILE_BUFFER(current) + current->buffered, s); + current->buffered += s; current->eof = s < size; + if(current->eof) { + keccak_end(current->hash_context, (char*)current->hash, 64); + keccak_free(¤t->hash_context); + } } } diff -uNr a/vtools/src/keccak.h b/vtools/src/keccak.h --- a/vtools/src/keccak.h false +++ b/vtools/src/keccak.h 4fc3f63ba6556d1076287e210bd3a9943d9d0a1a3b17e59f4832517845414b153d05204c4235cfe73560d07b785be69ff496fcad35f742e2e8a49798c065f5b5 @@ -0,0 +1,16 @@ +#ifndef KECCAK_H_ +#define KECCAK_H_ + +#include +#include +#include + +extern void *keccak_begin(); +extern void keccak_get_ctx_byte_size(size_t *size); +extern void keccak_hash(void *ctx, char *array, size_t size); +extern void keccak_end(void *ctx, char *out, size_t size); +extern void keccak_free(void **ctx); +extern void adainit(); +extern void adafinal(); + +#endif diff -uNr a/vtools/src/keccak_c.adb b/vtools/src/keccak_c.adb --- a/vtools/src/keccak_c.adb false +++ b/vtools/src/keccak_c.adb 680efb9458a976f700a689a6b0678510172945e94d35207f07bea280bb87b30edc889968fbf6c922c8cc5c79b9193986ab66037cc36f47d52b49e91826c22fe4 @@ -0,0 +1,89 @@ +package body Keccak_C is + -- helper functions + procedure ToBitstream(S: in String; B: out Bitstream ) is + V : Unsigned_8; + Pos : Natural; + begin + Pos := B'First; + for C of S loop + V := Character'Pos( C ); + B( Pos ) := Bit( V and 1 ); + B( Pos + 1 ) := Bit( Shift_Right( V, 1 ) and 1 ); + B( Pos + 2 ) := Bit( Shift_Right( V, 2 ) and 1 ); + B( Pos + 3 ) := Bit( Shift_Right( V, 3 ) and 1 ); + B( Pos + 4 ) := Bit( Shift_Right( V, 4 ) and 1 ); + B( Pos + 5 ) := Bit( Shift_Right( V, 5 ) and 1 ); + B( Pos + 6 ) := Bit( Shift_Right( V, 6 ) and 1 ); + B( Pos + 7 ) := Bit( Shift_Right( V, 7 ) and 1 ); + Pos := Pos + 8; + end loop; + end ToBitstream; + + procedure ToString(B: in Bitstream; S: out String ) is + N : Natural; + Pos : Natural; + begin + Pos := B'First; + for I in S'Range loop + N := Natural( B( Pos ) ) + + Natural( B( Pos + 1 ) ) * 2 + + Natural( B( Pos + 2 ) ) * 4 + + Natural( B( Pos + 3 ) ) * 8 + + Natural( B( Pos + 4 ) ) * 16 + + Natural( B( Pos + 5 ) ) * 32 + + Natural( B( Pos + 6 ) ) * 64 + + Natural( B( Pos + 7 ) ) * 128; + Pos := Pos + 8; + S( I ) := Character'Val( N ); + end loop; + end ToString; + + -- C interface + + procedure C_Get_Size(Size: out Interfaces.C.size_t) is + begin + Size := C_Context'Size / 8; + end C_Get_Size; + + function C_Begin return C_Context_Access is + Result : C_Context_Access; + begin + Result := new C_Context; + KeccakBegin(Result.all); + return Result; + end C_Begin; + + procedure C_Hash(Ctx: in C_Context_Access; + Input: Interfaces.C.Char_Array; + Len: Interfaces.C.Size_T) is + L: Natural := Natural(Len); + S: String(1..L); + B: Bitstream(1..S'Length*8); + begin + Interfaces.C.To_Ada(Input, S, L, Trim_Nul => False); + ToBitstream(S, B); + KeccakHash(Ctx.all, B); + end C_Hash; + + procedure C_End(Ctx: C_Context_Access; + Output: out Interfaces.C.Char_Array; + Len: Interfaces.C.Size_T) is + L: Natural := Natural(Len); + S: String(1..L); + B: Bitstream(1..S'Length*8); + Count: Interfaces.C.Size_T; + begin + KeccakEnd(Ctx.all, B); + ToString(B, S); + Interfaces.C.To_C(S, Output(0..Len), Count, Append_Nul => False); + -- Len = Count + end C_End; + + procedure C_Context_Deallocate is new Ada.Unchecked_Deallocation + (C_Context, C_Context_Access); + + procedure C_Deallocate(Ctx: in out C_Context_Access) is + begin + C_Context_Deallocate(Ctx); + end C_Deallocate; +end Keccak_C; diff -uNr a/vtools/src/keccak_c.ads b/vtools/src/keccak_c.ads --- a/vtools/src/keccak_c.ads false +++ b/vtools/src/keccak_c.ads 33d0a8bfac503d941796252636419dfbc9917d9d67c2e15e13e85083afb8ed46cde57452b61ef275ccfde07b7891d510467b49868882248a5836bce52ef7a7d0 @@ -0,0 +1,22 @@ +with Interfaces; use Interfaces; +with Interfaces.C; use Interfaces.C; +with Ada.Unchecked_Deallocation; +with SMG_Keccak; use SMG_Keccak; +package Keccak_C is + subtype C_Context is Keccak_Context(Block_Len=>Default_Bitrate); + type C_Context_Access is access C_Context; + procedure C_Get_Size(Size: out Interfaces.C.size_t); + pragma Export (C, C_Get_Size, "keccak_get_ctx_byte_size"); + function C_Begin return C_Context_Access; + pragma Export (C, C_Begin, "keccak_begin"); + procedure C_Hash(Ctx: C_Context_Access; + Input: Interfaces.C.Char_Array; + Len: Interfaces.C.Size_T); + pragma Export (C, C_Hash, "keccak_hash"); + procedure C_End(Ctx: C_Context_Access; + Output: out Interfaces.C.Char_Array; + Len: Interfaces.C.Size_T); + pragma Export (C, C_End, "keccak_end"); + procedure C_Deallocate(Ctx: in out C_Context_Access); + pragma Export (C, C_Deallocate, "keccak_free"); +end Keccak_C; diff -uNr a/vtools/src/smg_keccak.adb b/vtools/src/smg_keccak.adb --- a/vtools/src/smg_keccak.adb 88e40423c88ba2ac7d44225b388794d61719746b02412e2dae4684bcfa72399978d599f9301b4a2be101b41769d3c5b20de6ff94e76a01ff767edc00746b8b96 +++ b/vtools/src/smg_keccak.adb 8f038c226bd823b585a5081adbdbbf6a394c552875346ab9474c3a7679a8f7636704eb3230f0588fb250fb3a45d584e68a1de7fe92ee209c91d2cdaa0fe3e217 @@ -64,6 +64,75 @@ end; -- end squeeze stage end Sponge; + -- public interface, state based Sponge + procedure KeccakBegin(Ctx : in out Keccak_Context) is + begin + Ctx.Internal := (others => (others => 0)); + Ctx.Block := (others => 0); + Ctx.Pos := Ctx.Block'First; + end; + + procedure KeccakHash(Ctx : in out Keccak_Context; + Input : Bitstream) is + I0 : Natural; + I1 : Natural; + B0 : Natural; + B1 : Natural; + begin + I0 := Input'First; + <> + I1 := Input'Last; + B0 := Ctx.Pos; + B1 := B0 + (I1-I0); + + if B1>Ctx.Block'Last then + B1 := Ctx.Block'Last; + I1 := I0 + (B1-B0); + end if; + Ctx.Block(B0..B1) := Input(I0..I1); + Ctx.Pos := B1 + 1; + -- we've filled up the buffer + if Ctx.Pos > Ctx.Block'Last then + AbsorbBlock(Ctx.Block, Ctx.Internal); + Ctx.Internal := Keccak_Function(Ctx.Internal); + Ctx.Pos := Ctx.Block'First; + end if; + -- we haven't processed entire input block, loop + if I1 < Input'Last then + I0 := I1 + 1; + goto Block_Process_Loop; + end if; + end; + + procedure KeccakEnd(Ctx : in out Keccak_Context; + Output : out Bitstream) is + BlocksPerOutput : constant Natural := Output'Length / Ctx.Block_Len; + StrayPerOutput : constant Natural := Output'Length mod Ctx.Block_Len; + Block : Bitstream(1 .. Ctx.Block_Len); + Need : Natural; + begin + if Ctx.Pos /= 0 then -- needs padding + Block := (others => 0); + Need := Ctx.Block'Last - Ctx.Pos; + Block(Block'First) := 1; + Block(Block'First+Need) := 1; + KeccakHash(Ctx, Block(1..Need+1)); + end if; + + -- squeez bits + for I in 0 .. BlocksPerOutput - 1 loop + SqueezeBlock(Block, Ctx.Internal); + Output(Output'First + I * Ctx.Block_Len .. + Output'First + (I + 1) * Ctx.Block_Len -1) := Block; + Ctx.Internal := Keccak_Function(Ctx.Internal); + end loop; + if StrayPerOutput > 0 then + SqueezeBlock(Block, Ctx.Internal); + Output(Output'Last - StrayPerOutput + 1 .. Output'Last) := + Block(Block'First .. Block'First + StrayPerOutput - 1); + end if; + end; + -- convert from a bitstream of ZWord size to an actual ZWord number function BitsToWord( BWord: in Bitword ) return ZWord is W : ZWord; diff -uNr a/vtools/src/smg_keccak.ads b/vtools/src/smg_keccak.ads --- a/vtools/src/smg_keccak.ads 7503d06b8f87f1cd8a4246a7baf27ba9431646e65f07fea64173f24852be71dc493c3e866d5c16f6723f80c6e6ed1479a46fac9dea5fdf02b0387724bdb99e08 +++ b/vtools/src/smg_keccak.ads 71bca4b94ae6ea691d3a1faf6c84ae5d17b803d11607e786c34e2711cabeb6921789aae27a3a14b9b5cf5216a133ec2e8bd3b06eb1f2b88923f7e65297c2f5f4 @@ -59,6 +59,20 @@ Output : out Bitstream; Block_Len : in Keccak_Rate := Default_Bitrate ); + -- state based Sponge + type Keccak_Context (Block_Len: Keccak_Rate := Default_Bitrate) is + record + Internal: State := (others => (others => 0)); + Block: Bitstream(1..Block_Len) := (others => 0); + Pos: Natural; + end record; + + procedure KeccakBegin(Ctx: in out Keccak_Context); + procedure KeccakHash(Ctx: in out Keccak_Context; + Input: Bitstream); + procedure KeccakEnd(Ctx: in out Keccak_Context; + Output: out Bitstream); + private -- these are internals of the keccak implementation, not meant to be directly -- accessed/used diff -uNr a/vtools/vdiff.gpr b/vtools/vdiff.gpr --- a/vtools/vdiff.gpr false +++ b/vtools/vdiff.gpr 145a4c9bdc6da1fae51c1c4f8da23f73db1d7baddd59b5e4d630e1df2c8ac6e7fc00a37529a1f679ff68f57e60e495ac4360a7cb90c02a35093ed8a3d66fe696 @@ -0,0 +1,10 @@ +project Vdiff is + for Languages use ("Ada", "C"); + for Source_Dirs use ("src", "lib"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Main use ("diff.c"); + package Builder is + for Executable ("diff.c") use "vdiff"; + end Builder; +end Vdiff;