From a1259eaf16090626d0a6c49b03c0e6b55b24e53c Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 14 Oct 2021 00:17:01 +0100 Subject: [PATCH] Add native Fletcher-32. --- Aaru6.Checksums/FletcherContext.cs | 95 ++++++++++++++++++++++++--- AaruBenchmark/Checksums/Aaru6.cs | 2 + AaruBenchmark/Checksums/AaruNative.cs | 46 +++---------- 3 files changed, 96 insertions(+), 47 deletions(-) diff --git a/Aaru6.Checksums/FletcherContext.cs b/Aaru6.Checksums/FletcherContext.cs index f0a26f8..c44e021 100644 --- a/Aaru6.Checksums/FletcherContext.cs +++ b/Aaru6.Checksums/FletcherContext.cs @@ -44,22 +44,30 @@ namespace Aaru6.Checksums /// Implements the Fletcher-32 algorithm public sealed class Fletcher32Context : IChecksum { - const ushort FLETCHER_MODULE = 0xFFFF; - const uint NMAX = 5552; - ushort _sum1, _sum2; + const ushort FLETCHER_MODULE = 0xFFFF; + const uint NMAX = 5552; + readonly IntPtr _nativeContext; + ushort _sum1, _sum2; + readonly bool _useNative; /// Initializes the Fletcher-32 sums public Fletcher32Context() { _sum1 = 0xFFFF; _sum2 = 0xFFFF; + + if(!Native.IsSupported) + return; + + _nativeContext = fletcher32_init(); + _useNative = _nativeContext != IntPtr.Zero; } /// /// Updates the hash with data. /// Data buffer. /// Length of buffer to hash. - public void Update(byte[] data, uint len) => Step(ref _sum1, ref _sum2, data, len); + public void Update(byte[] data, uint len) => Step(ref _sum1, ref _sum2, data, len, _useNative, _nativeContext); /// /// Updates the hash with data. @@ -72,6 +80,12 @@ namespace Aaru6.Checksums { uint finalSum = (uint)((_sum2 << 16) | _sum1); + if(!_useNative) + return BigEndianBitConverter.GetBytes(finalSum); + + fletcher32_final(_nativeContext, ref finalSum); + fletcher32_free(_nativeContext); + return BigEndianBitConverter.GetBytes(finalSum); } @@ -79,8 +93,15 @@ namespace Aaru6.Checksums /// Returns a hexadecimal representation of the hash value. public string End() { - uint finalSum = (uint)((_sum2 << 16) | _sum1); - var fletcherOutput = new StringBuilder(); + uint finalSum = (uint)((_sum2 << 16) | _sum1); + + if(_useNative) + { + fletcher32_final(_nativeContext, ref finalSum); + fletcher32_free(_nativeContext); + } + + var fletcherOutput = new StringBuilder(); for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); @@ -88,8 +109,28 @@ namespace Aaru6.Checksums return fletcherOutput.ToString(); } - static void Step(ref ushort previousSum1, ref ushort previousSum2, byte[] data, uint len) + [DllImport("libAaru.Checksums.Native", SetLastError = true)] + static extern IntPtr fletcher32_init(); + + [DllImport("libAaru.Checksums.Native", SetLastError = true)] + static extern int fletcher32_update(IntPtr ctx, byte[] data, uint len); + + [DllImport("libAaru.Checksums.Native", SetLastError = true)] + static extern int fletcher32_final(IntPtr ctx, ref uint crc); + + [DllImport("libAaru.Checksums.Native", SetLastError = true)] + static extern void fletcher32_free(IntPtr ctx); + + static void Step(ref ushort previousSum1, ref ushort previousSum2, byte[] data, uint len, bool useNative, + IntPtr nativeContext) { + if(useNative) + { + fletcher32_update(nativeContext, data, len); + + return; + } + uint sum1 = previousSum1; uint sum2 = previousSum2; uint n; @@ -253,6 +294,17 @@ namespace Aaru6.Checksums /// Byte array of the hash value. public static string File(string filename, out byte[] hash) { + bool useNative = Native.IsSupported; + IntPtr nativeContext = IntPtr.Zero; + + if(useNative) + { + nativeContext = fletcher32_init(); + + if(nativeContext == IntPtr.Zero) + useNative = false; + } + var fileStream = new FileStream(filename, FileMode.Open); ushort localSum1 = 0xFFFF; @@ -263,13 +315,19 @@ namespace Aaru6.Checksums while(read > 0) { - Step(ref localSum1, ref localSum2, buffer, (uint)read); + Step(ref localSum1, ref localSum2, buffer, (uint)read, useNative, nativeContext); read = fileStream.Read(buffer, 0, 65536); } uint finalSum = (uint)((localSum2 << 16) | localSum1); + if(useNative) + { + fletcher32_final(nativeContext, ref finalSum); + fletcher32_free(nativeContext); + } + hash = BigEndianBitConverter.GetBytes(finalSum); var fletcherOutput = new StringBuilder(); @@ -288,13 +346,30 @@ namespace Aaru6.Checksums /// Byte array of the hash value. public static string Data(byte[] data, uint len, out byte[] hash) { + bool useNative = Native.IsSupported; + IntPtr nativeContext = IntPtr.Zero; + + if(useNative) + { + nativeContext = fletcher32_init(); + + if(nativeContext == IntPtr.Zero) + useNative = false; + } + ushort localSum1 = 0xFFFF; ushort localSum2 = 0xFFFF; - Step(ref localSum1, ref localSum2, data, len); + Step(ref localSum1, ref localSum2, data, len, useNative, nativeContext); uint finalSum = (uint)((localSum2 << 16) | localSum1); + if(useNative) + { + fletcher32_final(nativeContext, ref finalSum); + fletcher32_free(nativeContext); + } + hash = BigEndianBitConverter.GetBytes(finalSum); var adlerOutput = new StringBuilder(); @@ -319,8 +394,8 @@ namespace Aaru6.Checksums const byte NMAX = 22; readonly IntPtr _nativeContext; - byte _sum1, _sum2; readonly bool _useNative; + byte _sum1, _sum2; /// Initializes the Fletcher-16 sums public Fletcher16Context() diff --git a/AaruBenchmark/Checksums/Aaru6.cs b/AaruBenchmark/Checksums/Aaru6.cs index 7a40034..81a97eb 100644 --- a/AaruBenchmark/Checksums/Aaru6.cs +++ b/AaruBenchmark/Checksums/Aaru6.cs @@ -99,6 +99,8 @@ namespace AaruBenchmark.Checksums public static void Fletcher32() { + Native.ForceManaged = true; + byte[] data = new byte[1048576]; var fs = new FileStream(Path.Combine(Program.Folder, "random"), FileMode.Open, FileAccess.Read); diff --git a/AaruBenchmark/Checksums/AaruNative.cs b/AaruBenchmark/Checksums/AaruNative.cs index c4a8f42..d07a33f 100644 --- a/AaruBenchmark/Checksums/AaruNative.cs +++ b/AaruBenchmark/Checksums/AaruNative.cs @@ -76,18 +76,6 @@ namespace AaruBenchmark.Checksums 0xb5, 0xf2, 0x8c, 0xbb, 0x4a, 0xa5, 0x1b, 0x40, 0x7c, 0xb6 }; - [DllImport("libAaru.Checksums.Native", SetLastError = true)] - static extern IntPtr fletcher32_init(); - - [DllImport("libAaru.Checksums.Native", SetLastError = true)] - static extern int fletcher32_update(IntPtr ctx, byte[] data, uint len); - - [DllImport("libAaru.Checksums.Native", SetLastError = true)] - static extern int fletcher32_final(IntPtr ctx, ref uint crc); - - [DllImport("libAaru.Checksums.Native", SetLastError = true)] - static extern void fletcher32_free(IntPtr ctx); - [DllImport("libAaru.Checksums.Native", SetLastError = true)] static extern IntPtr spamsum_init(); @@ -124,39 +112,23 @@ namespace AaruBenchmark.Checksums public static void Fletcher32() { - byte[] data = new byte[1048576]; - uint fletcher32 = 0; - byte[] hash; + Native.ForceManaged = false; + + byte[] data = new byte[1048576]; var fs = new FileStream(Path.Combine(Program.Folder, "random"), FileMode.Open, FileAccess.Read); fs.Read(data, 0, 1048576); fs.Close(); fs.Dispose(); + IChecksum ctx = new Fletcher32Context(); + ctx.Update(data); + byte[] result = ctx.Final(); - IntPtr ctx = fletcher32_init(); + if(result?.Length != _expectedRandomFletcher32.Length) + throw new Exception("Invalid hash length"); - if(ctx == IntPtr.Zero) - throw new Exception("Could not initialize digest"); - - int ret = fletcher32_update(ctx, data, (uint)data.Length); - - if(ret != 0) - throw new Exception("Could not digest block"); - - ret = fletcher32_final(ctx, ref fletcher32); - - if(ret != 0) - throw new Exception("Could not finalize hash"); - - fletcher32_free(ctx); - - fletcher32 = ((fletcher32 << 8) & 0xFF00FF00) | ((fletcher32 >> 8) & 0xFF00FF); - fletcher32 = (fletcher32 << 16) | (fletcher32 >> 16); - - hash = BitConverter.GetBytes(fletcher32); - - if(hash.Where((t, i) => t != _expectedRandomFletcher32[i]).Any()) + if(result.Where((t, i) => t != _expectedRandomFletcher32[i]).Any()) throw new Exception("Invalid hash value"); }