diff --git a/src/MiningCore.Tests/Crypto/HashingTests.cs b/src/MiningCore.Tests/Crypto/HashingTests.cs index 064624311..0f6d3d634 100644 --- a/src/MiningCore.Tests/Crypto/HashingTests.cs +++ b/src/MiningCore.Tests/Crypto/HashingTests.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Linq; using MiningCore.Crypto.Hashing.Algorithms; using MiningCore.Crypto.Hashing.Equihash; @@ -13,6 +14,9 @@ public class HashingTests : TestBase { private static readonly byte[] testValue = Enumerable.Repeat((byte) 0x80, 32).ToArray(); + // some algos need 80 byte input buffers + private static readonly byte[] testValue2 = Enumerable.Repeat((byte)0x80, 80).ToArray(); + [Fact] public void Blake_Hash_Should_Match() { @@ -77,6 +81,22 @@ public void Scrypt_Hash_Should_Throw_On_Null_Input() Assert.Throws(() => hasher.Digest(null)); } + [Fact] + public void NeoScrypt_Hash_Should_Match() + { + var hasher = new NeoScrypt(0); + var result = hasher.Digest(testValue2).ToHexString(); + + Assert.Equal("7915d56de262bf23b1fb9104cf5d2a13fcbed2f6b4b9b657309c222b09f54bc0", result); + } + + [Fact] + public void NeoScrypt_Hash_Should_Throw_On_Null_Input() + { + var hasher = new NeoScrypt(0); + Assert.Throws(() => hasher.Digest(null)); + } + [Fact] public void ScryptN_Hash_Should_Match() { @@ -166,6 +186,22 @@ public void X11_Hash_Should_Throw_On_Null_Input() Assert.Throws(() => hasher.Digest(null)); } + [Fact] + public void X17_Hash_Should_Match() + { + var hasher = new X17(); + var result = hasher.Digest(testValue).ToHexString(); + + Assert.Equal("6a9a4f558168e60241e46fe44365021c4d7e7344144ab1739d6fb0125ac4c592", result); + } + + [Fact] + public void X17_Hash_Should_Throw_On_Null_Input() + { + var hasher = new Sha256S(); + Assert.Throws(() => hasher.Digest(null)); + } + [Fact] public void Skein_Hash_Should_Match() { diff --git a/src/MiningCore/Api/ApiServer.cs b/src/MiningCore/Api/ApiServer.cs index a0efde744..bc347181d 100644 --- a/src/MiningCore/Api/ApiServer.cs +++ b/src/MiningCore/Api/ApiServer.cs @@ -227,6 +227,7 @@ private async Task GetPoolInfosAsync(HttpContext context, Match m) var result = config.ToPoolInfo(mapper, stats); // enrich + result.TotalPaid = cf.Run(con => statsRepo.GetTotalPoolPayments(con, config.Id)); #if DEBUG var from = new DateTime(2018, 1, 6, 16, 0, 0); #else @@ -256,9 +257,10 @@ private async Task GetPoolInfoAsync(HttpContext context, Match m) var response = new GetPoolResponse { Pool = pool.ToPoolInfo(mapper, stats) - }; - + }; + // enrich + response.Pool.TotalPaid = cf.Run(con => statsRepo.GetTotalPoolPayments(con, pool.Id)); #if DEBUG var from = new DateTime(2018, 1, 7, 16, 0, 0); #else @@ -380,7 +382,7 @@ private async Task PagePoolPaymentsAsync(HttpContext context, Match m) .ToArray(); // enrich payments - CoinMetaData.PaymentInfoLinks.TryGetValue(pool.Coin.Type, out var txInfobaseUrl); + CoinMetaData.TxInfoLinks.TryGetValue(pool.Coin.Type, out var txInfobaseUrl); CoinMetaData.AddressInfoLinks.TryGetValue(pool.Coin.Type, out var addressInfobaseUrl); foreach (var payment in payments) @@ -426,7 +428,7 @@ private async Task GetMinerInfoAsync(HttpContext context, Match m) stats.LastPayment = statsResult.LastPayment.Created; // Compute info link - if (CoinMetaData.PaymentInfoLinks.TryGetValue(pool.Coin.Type, out var baseUrl)) + if (CoinMetaData.TxInfoLinks.TryGetValue(pool.Coin.Type, out var baseUrl)) stats.LastPaymentLink = string.Format(baseUrl, statsResult.LastPayment.TransactionConfirmationData); } @@ -464,7 +466,7 @@ private async Task PageMinerPaymentsAsync(HttpContext context, Match m) .ToArray(); // enrich payments - CoinMetaData.PaymentInfoLinks.TryGetValue(pool.Coin.Type, out var txInfobaseUrl); + CoinMetaData.TxInfoLinks.TryGetValue(pool.Coin.Type, out var txInfobaseUrl); CoinMetaData.AddressInfoLinks.TryGetValue(pool.Coin.Type, out var addressInfobaseUrl); foreach (var payment in payments) diff --git a/src/MiningCore/Api/Extensions/MiningPoolExtensions.cs b/src/MiningCore/Api/Extensions/MiningPoolExtensions.cs index 9bb5ca2cd..96dacf9ad 100644 --- a/src/MiningCore/Api/Extensions/MiningPoolExtensions.cs +++ b/src/MiningCore/Api/Extensions/MiningPoolExtensions.cs @@ -2,7 +2,9 @@ using AutoMapper; using MiningCore.Api.Responses; using MiningCore.Blockchain; +using MiningCore.Blockchain.Ethereum.Configuration; using MiningCore.Configuration; +using MiningCore.Extensions; using MiningCore.Mining; namespace MiningCore.Api.Extensions @@ -13,6 +15,9 @@ public static PoolInfo ToPoolInfo(this PoolConfig pool, IMapper mapper, Persiste { var poolInfo = mapper.Map(pool); + // enrich with basic information + poolInfo.Coin.Algorithm = GetPoolAlgorithm(pool); + poolInfo.PoolStats = mapper.Map(stats); poolInfo.NetworkStats = mapper.Map(stats); @@ -24,7 +29,32 @@ public static PoolInfo ToPoolInfo(this PoolConfig pool, IMapper mapper, Persiste // pool fees poolInfo.PoolFeePercent = (float)pool.RewardRecipients.Sum(x => x.Percentage); + // strip security critical stuff + if (poolInfo.PaymentProcessing.Extra != null) + { + var extra = poolInfo.PaymentProcessing.Extra; + + extra.StripValue(nameof(EthereumPoolPaymentProcessingConfigExtra.CoinbasePassword)); + } + return poolInfo; } + + private static string GetPoolAlgorithm(PoolConfig pool) + { + var result = pool.Coin.Algorithm; + + if (string.IsNullOrEmpty(result)) + { + if (CoinMetaData.CoinAlgorithm.TryGetValue(pool.Coin.Type, out var getter)) + result = getter(pool.Coin.Type); + } + + // Capitalize + if (!string.IsNullOrEmpty(result) && result.Length > 1) + result = result.Substring(0, 1).ToUpper() + result.Substring(1); + + return result; + } } } \ No newline at end of file diff --git a/src/MiningCore/Api/Responses/GetPoolsResponse.cs b/src/MiningCore/Api/Responses/GetPoolsResponse.cs index 992e20813..6642e30ba 100644 --- a/src/MiningCore/Api/Responses/GetPoolsResponse.cs +++ b/src/MiningCore/Api/Responses/GetPoolsResponse.cs @@ -30,6 +30,7 @@ namespace MiningCore.Api.Responses public class ApiCoinConfig { public string Type { get; set; } + public string Algorithm { get; set; } } public class ApiPoolPaymentProcessingConfig @@ -63,6 +64,7 @@ public partial class PoolInfo public PoolStats PoolStats { get; set; } public BlockchainStats NetworkStats { get; set; } public MinerPerformanceStats[] TopMiners { get; set; } + public decimal TotalPaid { get; set; } } public class GetPoolsResponse diff --git a/src/MiningCore/Blockchain/Bitcoin/BitcoinConstants.cs b/src/MiningCore/Blockchain/Bitcoin/BitcoinConstants.cs index 13fe0b9c1..ea30b2ab5 100644 --- a/src/MiningCore/Blockchain/Bitcoin/BitcoinConstants.cs +++ b/src/MiningCore/Blockchain/Bitcoin/BitcoinConstants.cs @@ -80,6 +80,7 @@ public class KnownAddresses public static readonly Dictionary DevFeeAddresses = new Dictionary { {CoinType.BTC, "17QnVor1B6oK1rWnVVBrdX9gFzVkZZbhDm"}, + {CoinType.BCH, "1LJGTzNDTuTvkHpTxNSdmAEBAXAnEHDVqQ"}, {CoinType.LTC, "LTK6CWastkmBzGxgQhTTtCUjkjDA14kxzC"}, {CoinType.DOGE, "DGDuKRhBewGP1kbUz4hszNd2p6dDzWYy9Q"}, {CoinType.NMC, "NDSLDpFEcTbuRVcWHdJyiRZThVAcb5Z79o"}, @@ -92,9 +93,13 @@ public class KnownAddresses {CoinType.MONA, "MBbkeAM3VQKg474bgxJEXrtcnMg8cjHY3S"}, {CoinType.VTC, "VfCAvPVrksYvwcpU7E44e51HxfvVhcxMXf"}, {CoinType.ZEC, "t1YHZHz2DGVMJiggD2P4fBQ2TAPgtLSUwZ7"}, - {CoinType.ZCL, "t1Ysa2CHdpMu8T2zjYXQNQxPgGh8ehe9QYo"}, + {CoinType.ZCL, "t1MFU1vD3YKgsK6Uh8hW7UTY8mKAV2xVqBr"}, + {CoinType.ZEN, "znigQacfTvRiwD2TRhwkBHLNchQ2AZisD94"}, {CoinType.BTG, "GQb77ZuMCyJGZFyxpzqNfm7GB1rQreP4n6"}, - {CoinType.XMR, "475YVJbPHPedudkhrcNp1wDcLMTGYusGPF5fqE7XjnragVLPdqbCHBdZg3dF4dN9hXMjjvGbykS6a77dTAQvGrpiQqHp2eH"} + {CoinType.MOON, "2QvpGimMYLyqKsczQXZjv56h6me3M8orwj" }, + {CoinType.XVG, "D5xPoHLM6HPkwWSqAweECTSQirJBmRjS8i" }, + {CoinType.XMR, "475YVJbPHPedudkhrcNp1wDcLMTGYusGPF5fqE7XjnragVLPdqbCHBdZg3dF4dN9hXMjjvGbykS6a77dTAQvGrpiQqHp2eH"}, + {CoinType.ETN, "etnkQJwBCjmR1MfkU8D355ZWxxLMhs8miPrtKHWN4U3uUowq9ugeKccVBoEG3n13n74us5AkT8tEoTog46w4HBgn8sMuBRhm9h"}, }; } diff --git a/src/MiningCore/Blockchain/Bitcoin/BitcoinJob.cs b/src/MiningCore/Blockchain/Bitcoin/BitcoinJob.cs index 72da03f57..2d555fc80 100644 --- a/src/MiningCore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/MiningCore/Blockchain/Bitcoin/BitcoinJob.cs @@ -23,7 +23,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System.Globalization; using System.IO; using System.Linq; -using System.Numerics; using System.Text; using MiningCore.Blockchain.Bitcoin.DaemonResponses; using MiningCore.Configuration; @@ -333,16 +332,19 @@ protected virtual BitcoinShare ProcessShareInternal(StratumClient worker, string var result = new BitcoinShare { BlockHeight = BlockTemplate.Height, - IsBlockCandidate = isBlockCandidate + BlockReward = rewardToPool.ToDecimal(MoneyUnit.BTC), + NetworkDifficulty = Difficulty * shareMultiplier, + Difficulty = stratumDifficulty, }; var blockBytes = SerializeBlock(headerBytes, coinbase); - result.BlockHex = blockBytes.ToHexString(); - result.BlockHash = blockHasher.Digest(headerBytes, nTime).ToHexString(); - result.BlockHeight = BlockTemplate.Height; - result.BlockReward = rewardToPool.ToDecimal(MoneyUnit.BTC); - result.NetworkDifficulty = Difficulty * shareMultiplier; - result.Difficulty = stratumDifficulty; + + if (isBlockCandidate) + { + result.IsBlockCandidate = true; + result.BlockHex = blockBytes.ToHexString(); + result.BlockHash = blockHasher.Digest(headerBytes, nTime).ToHexString(); + } return result; } diff --git a/src/MiningCore/Blockchain/Bitcoin/BitcoinJobManager.cs b/src/MiningCore/Blockchain/Bitcoin/BitcoinJobManager.cs index f13e945df..9c3a84d2b 100644 --- a/src/MiningCore/Blockchain/Bitcoin/BitcoinJobManager.cs +++ b/src/MiningCore/Blockchain/Bitcoin/BitcoinJobManager.cs @@ -20,13 +20,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Net; -using System.Reactive.Disposables; using System.Reactive.Linq; -using System.Text; -using System.Threading; using System.Threading.Tasks; using Autofac; using MiningCore.Blockchain.Bitcoin.Configuration; @@ -38,14 +34,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using MiningCore.Crypto.Hashing.Special; using MiningCore.DaemonInterface; using MiningCore.Extensions; -using MiningCore.Mining; using MiningCore.Notifications; using MiningCore.Stratum; using MiningCore.Time; using MiningCore.Util; using NBitcoin; -using NetMQ; -using NetMQ.Sockets; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NLog; @@ -76,12 +69,12 @@ public BitcoinJobManager( protected readonly NotificationService notificationService; protected readonly IMasterClock clock; protected DaemonClient daemon; - protected BitcoinPoolConfigExtra extraPoolConfig; protected readonly IExtraNonceProvider extraNonceProvider; protected const int ExtranonceBytes = 4; protected readonly IHashAlgorithm sha256d = new Sha256D(); protected readonly IHashAlgorithm sha256dReverse = new DigestReverser(new Sha256D()); - protected const int MaxActiveJobs = 4; + protected int maxActiveJobs = 4; + protected BitcoinPoolConfigExtra extraPoolConfig; protected readonly IHashAlgorithm sha256s = new Sha256S(); protected readonly List validJobs = new List(); protected IHashAlgorithm blockHasher; @@ -112,60 +105,21 @@ protected virtual void SetupJobUpdates() var sources = new List>(); var cancelTimeout = new List>(); - // block updates via ZMQ pub/sub - var zmqPublisherSocket = extraPoolConfig?.ZmqBlockNotifySocket?.Trim(); + // collect ports + var zmq = poolConfig.Daemons + .Where(x => !string.IsNullOrEmpty(x.Extra.SafeExtensionDataAs()?.ZmqBlockNotifySocket)) + .ToDictionary(x => x, x => x.Extra.SafeExtensionDataAs().ZmqBlockNotifySocket); - if (!string.IsNullOrEmpty(zmqPublisherSocket)) + if (zmq.Count > 0) { - var newJobsPubSub = Observable.Defer(()=> Observable.Create(obs => - { - var tcs = new CancellationTokenSource(); - - Task.Factory.StartNew(() => - { - while (!tcs.IsCancellationRequested) - { - try - { - using (var subSocket = new SubscriberSocket()) - { - //subSocket.Options.ReceiveHighWatermark = 1000; - subSocket.Connect(zmqPublisherSocket); - subSocket.Subscribe(BitcoinConstants.ZmqPublisherTopicBlockHash); - - logger.Info($"Subscribed to {zmqPublisherSocket}/{BitcoinConstants.ZmqPublisherTopicBlockHash} for ZMQ pub/sub block updates"); - - while (true) - { - subSocket.ReceiveMultipartMessage(2); - //var msg = subSocket.ReceiveMultipartMessage(2); - //var topic = msg.First().ConvertToString(Encoding.UTF8); - //var body = msg.Last().ConvertToString(Encoding.UTF8); - - obs.OnNext(true); - } - } - } - - catch (Exception ex) - { - logger.Error(ex); - } - - // do not consume all CPU cycles in case of a long lasting error condition - Thread.Sleep(1000); - } - }, tcs.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + logger.Info(() => $"[{LogCat}] Subscribing to ZMQ push-updates from {string.Join(", ", zmq.Values)}"); - return Disposable.Create(() => - { - tcs.Cancel(); - }); - })) - .Select(_ => Observable.FromAsync(() => UpdateJob(false, "ZMQ pub/sub"))) - .Concat() - .Publish() - .RefCount(); + var newJobsPubSub = daemon.ZmqSubscribe(zmq, BitcoinConstants.ZmqPublisherTopicBlockHash, 2) + .Do(x=> x.Dispose()) // we don't care about the contents + .Select(_ => Observable.FromAsync(() => UpdateJob(false, "ZMQ pub/sub"))) + .Concat() + .Publish() + .RefCount(); sources.Add(newJobsPubSub); cancelTimeout.Add(newJobsPubSub); @@ -475,6 +429,9 @@ public override void Configure(PoolConfig poolConfig, ClusterConfig clusterConfi { extraPoolConfig = poolConfig.Extra.SafeExtensionDataAs(); + if (extraPoolConfig?.MaxActiveJobs.HasValue == true) + maxActiveJobs = extraPoolConfig.MaxActiveJobs.Value; + base.Configure(poolConfig, clusterConfig); } @@ -657,8 +614,9 @@ protected virtual async Task UpdateJob(bool forceUpdate, string via = null var job = currentJob; var isNew = job == null || - job.BlockTemplate?.PreviousBlockhash != blockTemplate.PreviousBlockhash || - job.BlockTemplate?.Height < blockTemplate.Height; + (blockTemplate != null && + job.BlockTemplate?.PreviousBlockhash != blockTemplate.PreviousBlockhash && + blockTemplate.Height > job.BlockTemplate?.Height); if (isNew || forceUpdate) { @@ -685,7 +643,7 @@ protected virtual async Task UpdateJob(bool forceUpdate, string via = null validJobs.Add(job); // trim active jobs - while (validJobs.Count > MaxActiveJobs) + while (validJobs.Count > maxActiveJobs) validJobs.RemoveAt(0); } diff --git a/src/MiningCore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs b/src/MiningCore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs index af0fa4a7e..8c7b6e88b 100644 --- a/src/MiningCore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs +++ b/src/MiningCore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs @@ -46,9 +46,9 @@ namespace MiningCore.Blockchain.Bitcoin [CoinMetadata( CoinType.BTC, CoinType.BCH, CoinType.NMC, CoinType.PPC, CoinType.LTC, CoinType.DOGE, CoinType.DGB, CoinType.VIA, - CoinType.GRS, CoinType.MONA, CoinType.VTC, - CoinType.BTG, CoinType.GLT, CoinType.STAK, - CoinType.MOON)] + CoinType.GRS, CoinType.MONA, CoinType.VTC, CoinType.BTG, + CoinType.GLT, CoinType.STAK, CoinType.MOON, CoinType.XVG, + CoinType.GBX, CoinType.CRC)] public class BitcoinPayoutHandler : PayoutHandlerBase, IPayoutHandler { @@ -74,7 +74,7 @@ public BitcoinPayoutHandler( protected readonly IComponentContext ctx; protected DaemonClient daemon; protected BitcoinCoinProperties coinProperties; - protected BitcoinPoolConfigExtra extraPoolConfig; + protected BitcoinDaemonEndpointConfigExtra extraPoolConfig; protected BitcoinPoolPaymentProcessingConfigExtra extraPoolPaymentProcessingConfig; protected override string LogCategory => "Bitcoin Payout Handler"; @@ -88,7 +88,7 @@ public virtual Task ConfigureAsync(ClusterConfig clusterConfig, PoolConfig poolC this.poolConfig = poolConfig; this.clusterConfig = clusterConfig; - extraPoolConfig = poolConfig.Extra.SafeExtensionDataAs(); + extraPoolConfig = poolConfig.Extra.SafeExtensionDataAs(); extraPoolPaymentProcessingConfig = poolConfig.PaymentProcessing.Extra.SafeExtensionDataAs(); coinProperties = BitcoinProperties.GetCoinProperties(poolConfig.Coin.Type, poolConfig.Coin.Algorithm); diff --git a/src/MiningCore/Blockchain/Bitcoin/BitcoinPool.cs b/src/MiningCore/Blockchain/Bitcoin/BitcoinPool.cs index 29438ebb1..a9525f54c 100644 --- a/src/MiningCore/Blockchain/Bitcoin/BitcoinPool.cs +++ b/src/MiningCore/Blockchain/Bitcoin/BitcoinPool.cs @@ -34,7 +34,7 @@ namespace MiningCore.Blockchain.Bitcoin CoinType.BTC, CoinType.BCH, CoinType.NMC, CoinType.PPC, CoinType.LTC, CoinType.DOGE, CoinType.DGB, CoinType.VIA, CoinType.GRS, CoinType.MONA, CoinType.VTC, CoinType.GLT, - CoinType.MOON)] + CoinType.MOON, CoinType.XVG, CoinType.GBX, CoinType.CRC)] public class BitcoinPool : BitcoinPoolBase, BlockTemplate> { public BitcoinPool(IComponentContext ctx, diff --git a/src/MiningCore/Blockchain/Bitcoin/BitcoinProperties.cs b/src/MiningCore/Blockchain/Bitcoin/BitcoinProperties.cs index 701b1b3d3..80036d849 100644 --- a/src/MiningCore/Blockchain/Bitcoin/BitcoinProperties.cs +++ b/src/MiningCore/Blockchain/Bitcoin/BitcoinProperties.cs @@ -11,13 +11,14 @@ namespace MiningCore.Blockchain.Bitcoin public class BitcoinCoinProperties { public BitcoinCoinProperties(double shareMultiplier, IHashAlgorithm coinbaseHasher, IHashAlgorithm headerHasher, - IHashAlgorithm blockHasher, IHashAlgorithm posblockHasher = null) + IHashAlgorithm blockHasher, string algorithm, IHashAlgorithm posblockHasher = null) { ShareMultiplier = shareMultiplier; CoinbaseHasher = coinbaseHasher; HeaderHasher = headerHasher; BlockHasher = blockHasher; PoSBlockHasher = posblockHasher; + Algorithm = algorithm; } public double ShareMultiplier { get; } @@ -25,6 +26,7 @@ public BitcoinCoinProperties(double shareMultiplier, IHashAlgorithm coinbaseHash public IHashAlgorithm HeaderHasher { get; } public IHashAlgorithm BlockHasher { get; } public IHashAlgorithm PoSBlockHasher { get; } + public string Algorithm { get; } } public class BitcoinProperties @@ -33,42 +35,50 @@ public class BitcoinProperties private static readonly IHashAlgorithm sha256D = new Sha256D(); private static readonly IHashAlgorithm sha256DReverse = new DigestReverser(sha256D); private static readonly IHashAlgorithm x11 = new X11(); + private static readonly IHashAlgorithm x17 = new X17(); private static readonly IHashAlgorithm groestl = new Groestl(); private static readonly IHashAlgorithm lyra2Rev2 = new Lyra2Rev2(); private static readonly IHashAlgorithm scrypt_1024_1 = new Scrypt(1024, 1); private static readonly IHashAlgorithm skein = new Skein(); private static readonly IHashAlgorithm qubit = new Qubit(); private static readonly IHashAlgorithm groestlMyriad = new GroestlMyriad(); + private static readonly IHashAlgorithm neoScryptProfile1 = new NeoScrypt(0x80000620); private static readonly BitcoinCoinProperties sha256Coin = - new BitcoinCoinProperties(1, sha256D, sha256D, sha256DReverse); + new BitcoinCoinProperties(1, sha256D, sha256D, sha256DReverse, "Sha256"); private static readonly BitcoinCoinProperties scryptCoin = - new BitcoinCoinProperties(Math.Pow(2, 16), sha256D, scrypt_1024_1, sha256DReverse, new DigestReverser(scrypt_1024_1)); + new BitcoinCoinProperties(Math.Pow(2, 16), sha256D, scrypt_1024_1, sha256DReverse, "Scrypt", new DigestReverser(scrypt_1024_1)); private static readonly BitcoinCoinProperties groestlCoin = - new BitcoinCoinProperties(Math.Pow(2, 8), sha256S, groestl, new DigestReverser(groestl)); + new BitcoinCoinProperties(Math.Pow(2, 8), sha256S, groestl, new DigestReverser(groestl), "Groestl"); private static readonly BitcoinCoinProperties lyra2Rev2CoinVariantA = - new BitcoinCoinProperties(Math.Pow(2, 8), sha256D, lyra2Rev2, sha256DReverse); + new BitcoinCoinProperties(Math.Pow(2, 8), sha256D, lyra2Rev2, sha256DReverse, "Lyra2re2"); private static readonly BitcoinCoinProperties lyra2Rev2CoinVariantB = - new BitcoinCoinProperties(Math.Pow(2, 8), sha256D, lyra2Rev2, new DigestReverser(lyra2Rev2)); + new BitcoinCoinProperties(Math.Pow(2, 8), sha256D, lyra2Rev2, new DigestReverser(lyra2Rev2), "Lyra2re2"); private static readonly BitcoinCoinProperties x11Coin = - new BitcoinCoinProperties(1, sha256D, x11, new DigestReverser(x11)); + new BitcoinCoinProperties(1, sha256D, x11, new DigestReverser(x11), "X11"); private static readonly BitcoinCoinProperties skeinCoin = - new BitcoinCoinProperties(1, sha256D, skein, sha256DReverse); + new BitcoinCoinProperties(1, sha256D, skein, sha256DReverse, "Skein"); private static readonly BitcoinCoinProperties qubitCoin = - new BitcoinCoinProperties(1, sha256D, qubit, sha256DReverse); + new BitcoinCoinProperties(1, sha256D, qubit, sha256DReverse, "Qubit"); private static readonly BitcoinCoinProperties groestlMyriadCoin = - new BitcoinCoinProperties(Math.Pow(2, 8), sha256S, groestlMyriad, sha256DReverse); + new BitcoinCoinProperties(Math.Pow(2, 8), sha256S, groestlMyriad, sha256DReverse, "Groestl-Myriad"); private static readonly BitcoinCoinProperties equihashCoin = - new BitcoinCoinProperties(1, new DummyHasher(), sha256D, sha256DReverse); + new BitcoinCoinProperties(1, new DummyHasher(), sha256D, sha256DReverse, "Equihash"); + + private static readonly BitcoinCoinProperties neoScryptCoin = + new BitcoinCoinProperties(Math.Pow(2, 16), sha256D, neoScryptProfile1, sha256DReverse, "Neoscrypt"); + + private static readonly BitcoinCoinProperties x17Coin = + new BitcoinCoinProperties(1, sha256D, x17, new DigestReverser(x17), "X17"); private static readonly Dictionary coinProperties = new Dictionary { @@ -102,12 +112,19 @@ public class BitcoinProperties { CoinType.ZEC, equihashCoin }, { CoinType.BTG, equihashCoin }, { CoinType.ZCL, equihashCoin }, + { CoinType.ZEN, equihashCoin }, + + // Neoscrypt + { CoinType.GBX, neoScryptCoin }, + { CoinType.CRC, neoScryptCoin }, }; public static BitcoinCoinProperties GetCoinProperties(CoinType coin, string algorithm = null) { if (coin == CoinType.DGB) return GetDigiByteProperties(algorithm); + else if (coin == CoinType.XVG) + return GetVergeProperties(algorithm); coinProperties.TryGetValue(coin, out var props); return props; @@ -117,7 +134,7 @@ private static BitcoinCoinProperties GetDigiByteProperties(string algorithm) { Contract.Requires(!string.IsNullOrEmpty(algorithm), $"{nameof(algorithm)} must not be empty"); - switch(algorithm) + switch(algorithm.ToLower()) { case "sha256d": return sha256Coin; @@ -136,5 +153,36 @@ private static BitcoinCoinProperties GetDigiByteProperties(string algorithm) return scryptCoin; } } + + private static BitcoinCoinProperties GetVergeProperties(string algorithm) + { + Contract.Requires(!string.IsNullOrEmpty(algorithm), $"{nameof(algorithm)} must not be empty"); + + switch (algorithm.ToLower()) + { + case "lyra2rev2": + return lyra2Rev2CoinVariantA; + + case "groestl-myriad": + return groestlMyriadCoin; + + case "x17": + return x17Coin; + + case "blake2s": + throw new NotSupportedException($"algorithm {algorithm} not yet supported"); + + default: // scrypt + return scryptCoin; + } + } + + public static string GetAlgorithm(CoinType coin) + { + if (coinProperties.TryGetValue(coin, out var props)) + return props.Algorithm; + + return string.Empty; + } } } diff --git a/src/MiningCore/Blockchain/Bitcoin/Configuration/BitcoinDaemonEndpointConfigExtra.cs b/src/MiningCore/Blockchain/Bitcoin/Configuration/BitcoinDaemonEndpointConfigExtra.cs new file mode 100644 index 000000000..394fee48f --- /dev/null +++ b/src/MiningCore/Blockchain/Bitcoin/Configuration/BitcoinDaemonEndpointConfigExtra.cs @@ -0,0 +1,33 @@ +/* +Copyright 2017 Coin Foundry (coinfoundry.org) +Authors: Oliver Weichhold (oliver@weichhold.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +namespace MiningCore.Blockchain.Bitcoin.Configuration +{ + public class BitcoinDaemonEndpointConfigExtra + { + public int? MinimumConfirmations { get; set; } + + /// + /// Address of ZeroMQ block notify socket + /// Should match the value of -zmqpubhashblock daemon start parameter + /// + public string ZmqBlockNotifySocket { get; set; } + } +} diff --git a/src/MiningCore/Blockchain/Bitcoin/Configuration/BitcoinPoolConfigExtra.cs b/src/MiningCore/Blockchain/Bitcoin/Configuration/BitcoinPoolConfigExtra.cs index 7f5acf8b6..56607d93c 100644 --- a/src/MiningCore/Blockchain/Bitcoin/Configuration/BitcoinPoolConfigExtra.cs +++ b/src/MiningCore/Blockchain/Bitcoin/Configuration/BitcoinPoolConfigExtra.cs @@ -22,12 +22,6 @@ namespace MiningCore.Blockchain.Bitcoin.Configuration { public class BitcoinPoolConfigExtra { - public int? MinimumConfirmations { get; set; } - - /// - /// Address of ZeroMQ block notify socket - /// Should match the value of -zmqpubhashblock daemon start parameter - /// - public string ZmqBlockNotifySocket { get; set; } + public int? MaxActiveJobs { get; set; } } } diff --git a/src/MiningCore/Blockchain/CoinMetaData.cs b/src/MiningCore/Blockchain/CoinMetaData.cs index 264d83eaf..85892af61 100644 --- a/src/MiningCore/Blockchain/CoinMetaData.cs +++ b/src/MiningCore/Blockchain/CoinMetaData.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using MiningCore.Blockchain.Bitcoin; using MiningCore.Blockchain.Ethereum; using MiningCore.Configuration; @@ -22,13 +24,14 @@ public static class CoinMetaData { CoinType.XMR, new Dictionary { { string.Empty, "https://chainradar.com/xmr/block/{0}" }}}, { CoinType.ETN, new Dictionary { { string.Empty, "https://blockexplorer.electroneum.com/block/{0}" } }}, - { CoinType.LTC, new Dictionary { { string.Empty, "http://explorer.litecoin.net/block/{0}" }}}, + { CoinType.LTC, new Dictionary { { string.Empty, "https://chainz.cryptoid.info/ltc/block.dws?{0}.htm" } }}, { CoinType.BCH, new Dictionary { { string.Empty, "https://www.blocktrail.com/BCC/block/{0}" }}}, { CoinType.DASH, new Dictionary { { string.Empty, "https://chainz.cryptoid.info/dash/block.dws?{0}.htm" }}}, { CoinType.BTC, new Dictionary { { string.Empty, "https://blockchain.info/block/{0}" }}}, { CoinType.DOGE, new Dictionary { { string.Empty, "https://dogechain.info/block/{0}" }}}, { CoinType.ZEC, new Dictionary { { string.Empty, "https://explorer.zcha.in/blocks/{0}" }}}, { CoinType.ZCL, new Dictionary { { string.Empty, "http://explorer.zclmine.pro/blocks/{0}" }}}, + { CoinType.ZEN, new Dictionary { { string.Empty, "http://explorer.zensystem.io/blocks/{0}" } }}, { CoinType.DGB, new Dictionary { { string.Empty, "https://digiexplorer.info/block/{0}" }}}, { CoinType.NMC, new Dictionary { { string.Empty, "https://explorer.namecoin.info/b/{0}" }}}, { CoinType.GRS, new Dictionary { { string.Empty, "https://groestlsight.groestlcoin.org/block/{0}" }}}, @@ -40,22 +43,24 @@ public static class CoinMetaData { CoinType.EXP, new Dictionary { { string.Empty, "http://www.gander.tech/blocks/{0}" }}}, { CoinType.AEON, new Dictionary { { string.Empty, "https://chainradar.com/aeon/block/{0}" }}}, { CoinType.STAK, new Dictionary { { string.Empty, "https://straks.info/block/{0}" }}}, - { CoinType.MOON, new Dictionary { { string.Empty, " https://chainz.cryptoid.info/moon/block.dws?{0}.htm" }}}, + { CoinType.MOON, new Dictionary { { string.Empty, "https://chainz.cryptoid.info/moon/block.dws?{0}.htm" }}}, + { CoinType.XVG, new Dictionary { { string.Empty, "https://verge-blockchain.info/block/{0}" } }}, }; - public static readonly Dictionary PaymentInfoLinks = new Dictionary + public static readonly Dictionary TxInfoLinks = new Dictionary { { CoinType.XMR, "https://chainradar.com/xmr/transaction/{0}" }, { CoinType.ETN, "https://blockexplorer.electroneum.com/tx/{0}" }, { CoinType.ETH, "https://etherscan.io/tx/{0}" }, { CoinType.ETC, "https://gastracker.io/tx/{0}" }, - { CoinType.LTC, "http://explorer.litecoin.net/tx/{0}" }, + { CoinType.LTC, "https://chainz.cryptoid.info/ltc/tx.dws?{0}.htm" }, { CoinType.BCH, "https://www.blocktrail.com/BCC/tx/{0}" }, { CoinType.DASH, "https://chainz.cryptoid.info/dash/tx.dws?{0}.htm" }, { CoinType.BTC, "https://blockchain.info/tx/{0}" }, { CoinType.DOGE, "https://dogechain.info/tx/{0}" }, { CoinType.ZEC, "https://explorer.zcha.in/transactions/{0}" }, { CoinType.ZCL, "http://explorer.zclmine.pro/transactions/{0}" }, + { CoinType.ZEN, "http://explorer.zensystem.io/transactions/{0}" }, { CoinType.DGB, "https://digiexplorer.info/tx/{0}" }, { CoinType.NMC, "https://explorer.namecoin.info/tx/{0}" }, { CoinType.GRS, "https://groestlsight.groestlcoin.org/tx/{0}" }, @@ -68,19 +73,23 @@ public static class CoinMetaData { CoinType.EXP, "http://www.gander.tech/tx/{0}" }, { CoinType.AEON, "https://chainradar.com/aeon/transaction/{0}" }, { CoinType.MOON, "https://chainz.cryptoid.info/moon/tx.dws?{0}.htm" }, + { CoinType.XVG, "https://verge-blockchain.info/tx/{0}" }, + { CoinType.GBX, "http://gobyte.ezmine.io/tx/{0}" }, + { CoinType.CRC, "http://explorer.cryptopros.us/tx/{0}" }, }; - + public static readonly Dictionary AddressInfoLinks = new Dictionary { { CoinType.ETH, "https://etherscan.io/address/{0}" }, { CoinType.ETC, "https://gastracker.io/addr/{0}" }, - { CoinType.LTC, "http://explorer.litecoin.net/address/{0}" }, + { CoinType.LTC, "https://chainz.cryptoid.info/ltc/address.dws?{0}.htm" }, { CoinType.BCH, "https://www.blocktrail.com/BCC/address/{0}" }, { CoinType.DASH, "https://chainz.cryptoid.info/dash/address.dws?{0}.htm" }, { CoinType.BTC, "https://blockchain.info/address/{0}" }, { CoinType.DOGE, "https://dogechain.info/address/{0}" }, { CoinType.ZEC, "https://explorer.zcha.in/accounts/{0}" }, { CoinType.ZCL, "http://explorer.zclmine.pro/accounts/{0}" }, + { CoinType.ZEN, "http://explorer.zensystem.io/accounts/{0}" }, { CoinType.DGB, "https://digiexplorer.info/address/{0}" }, { CoinType.NMC, "https://explorer.namecoin.info/a/{0}" }, { CoinType.GRS, "https://groestlsight.groestlcoin.org/address/{0}" }, @@ -92,6 +101,44 @@ public static class CoinMetaData { CoinType.ELLA, "https://explorer.ellaism.org/addr/{0}" }, { CoinType.EXP, "http://www.gander.tech/address/{0}" }, { CoinType.MOON, "https://chainz.cryptoid.info/moon/address.dws?{0}.htm" }, + { CoinType.XVG, "https://verge-blockchain.info/address/{0}" }, + { CoinType.GBX, "http://gobyte.ezmine.io/address/{0}" }, + { CoinType.CRC, "http://explorer.cryptopros.us/address/{0}" }, + }; + + private const string Ethash = "Dagger-Hashimoto"; + private const string Cryptonight = "Cryptonight"; + private const string CryptonightLight = "Cryptonight-Light"; + + public static readonly Dictionary> CoinAlgorithm = new Dictionary> + { + { CoinType.ETH, (coin)=> Ethash }, + { CoinType.ETC, (coin)=> Ethash }, + { CoinType.LTC, BitcoinProperties.GetAlgorithm }, + { CoinType.BCH, BitcoinProperties.GetAlgorithm }, + { CoinType.DASH, BitcoinProperties.GetAlgorithm }, + { CoinType.BTC, BitcoinProperties.GetAlgorithm }, + { CoinType.DOGE, BitcoinProperties.GetAlgorithm }, + { CoinType.ZEC, BitcoinProperties.GetAlgorithm }, + { CoinType.ZCL, BitcoinProperties.GetAlgorithm }, + { CoinType.ZEN, BitcoinProperties.GetAlgorithm }, + { CoinType.DGB, BitcoinProperties.GetAlgorithm }, + { CoinType.NMC, BitcoinProperties.GetAlgorithm }, + { CoinType.GRS, BitcoinProperties.GetAlgorithm }, + { CoinType.MONA, BitcoinProperties.GetAlgorithm }, + { CoinType.STAK, BitcoinProperties.GetAlgorithm }, + { CoinType.GLT, BitcoinProperties.GetAlgorithm }, + { CoinType.VTC, BitcoinProperties.GetAlgorithm }, + { CoinType.BTG, BitcoinProperties.GetAlgorithm }, + { CoinType.ELLA, (coin)=> Ethash }, + { CoinType.EXP, (coin)=> Ethash }, + { CoinType.MOON, BitcoinProperties.GetAlgorithm }, + { CoinType.XVG, BitcoinProperties.GetAlgorithm }, + { CoinType.XMR, (coin)=> Cryptonight }, + { CoinType.ETN, (coin)=> Cryptonight }, + { CoinType.AEON, (coin)=> CryptonightLight }, + { CoinType.GBX, BitcoinProperties.GetAlgorithm }, + { CoinType.CRC, BitcoinProperties.GetAlgorithm }, }; } } diff --git a/src/MiningCore/Blockchain/JobManagerBase.cs b/src/MiningCore/Blockchain/JobManagerBase.cs index 7535c2ec0..fa683e422 100644 --- a/src/MiningCore/Blockchain/JobManagerBase.cs +++ b/src/MiningCore/Blockchain/JobManagerBase.cs @@ -1,20 +1,20 @@ -/* +/* Copyright 2017 Coin Foundry (coinfoundry.org) Authors: Oliver Weichhold (oliver@weichhold.com) -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ @@ -24,6 +24,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System.Threading.Tasks; using Autofac; using MiningCore.Configuration; +using MiningCore.Extensions; using MiningCore.Util; using NLog; using Contract = MiningCore.Contracts.Contract; @@ -43,7 +44,7 @@ protected JobManagerBase(IComponentContext ctx) protected ClusterConfig clusterConfig; protected TJob currentJob; - private long jobId; + private int jobId; protected object jobLock = new object(); protected ILogger logger; protected PoolConfig poolConfig; @@ -73,12 +74,13 @@ protected virtual async Task StartDaemonAsync() protected string NextJobId(string format = null) { - var value = Interlocked.Increment(ref jobId); + Interlocked.Increment(ref jobId); + var value = Interlocked.CompareExchange(ref jobId, 0, Int32.MinValue); if (format != null) return value.ToString(format); - return value.ToString(CultureInfo.InvariantCulture); + return value.ToStringHex8(); } protected abstract Task AreDaemonsHealthy(); diff --git a/src/MiningCore/Blockchain/Monero/MoneroPayoutHandler.cs b/src/MiningCore/Blockchain/Monero/MoneroPayoutHandler.cs index a7fa0d590..6ad8b2efc 100644 --- a/src/MiningCore/Blockchain/Monero/MoneroPayoutHandler.cs +++ b/src/MiningCore/Blockchain/Monero/MoneroPayoutHandler.cs @@ -163,62 +163,21 @@ private async Task PayoutBatch(Balance[] balances) var transferResponse = await walletDaemon.ExecuteCmdSingleAsync(MWC.Transfer, request); // gracefully handle error -4 (transaction would be too large. try /transfer_split) - if (transferResponse.Error?.Code == -4) + if (transferResponse.Error?.Code == -4 && walletSupportsTransferSplit) { - if (walletSupportsTransferSplit) - { - logger.Info(() => $"[{LogCategory}] Retrying transfer using {MWC.TransferSplit}"); - - var transferSplitResponse = await walletDaemon.ExecuteCmdSingleAsync(MWC.TransferSplit, request); - - // gracefully handle error -4 (transaction would be too large. try /transfer_split) - if (transferResponse.Error?.Code != -4) - { - HandleTransferResponse(transferSplitResponse, balances); - return; - } - } - - // retry paged - logger.Info(() => $"[{LogCategory}] Retrying paged"); + logger.Info(() => $"[{LogCategory}] Retrying transfer using {MWC.TransferSplit}"); - var validBalances = balances.Where(x => x.Amount > 0).ToArray(); - var pageSize = 10; - var pageCount = (int)Math.Ceiling((double)validBalances.Length / pageSize); + var transferSplitResponse = await walletDaemon.ExecuteCmdSingleAsync(MWC.TransferSplit, request); - for (var i = 0; i < pageCount; i++) + // gracefully handle error -4 (transaction would be too large. try /transfer_split) + if (transferResponse.Error?.Code != -4) { - var page = validBalances - .Skip(i * pageSize) - .Take(pageSize) - .ToArray(); - - // update request - request.Destinations = page - .Where(x => x.Amount > 0) - .Select(x => - { - ExtractAddressAndPaymentId(x.Address, out var address, out var paymentId); - - return new TransferDestination - { - Address = address, - Amount = (ulong) Math.Floor(x.Amount * MoneroConstants.SmallestUnit[poolConfig.Coin.Type]) - }; - }).ToArray(); - - logger.Info(() => $"[{LogCategory}] Page {i + 1}: Paying out {FormatAmount(page.Sum(x => x.Amount))} to {page.Length} addresses"); - - transferResponse = await walletDaemon.ExecuteCmdSingleAsync(MWC.Transfer, request); - HandleTransferResponse(transferResponse, page); - - if (transferResponse.Error != null) - break; + HandleTransferResponse(transferSplitResponse, balances); + return; } } - else - HandleTransferResponse(transferResponse, balances); + HandleTransferResponse(transferResponse, balances); } private void ExtractAddressAndPaymentId(string input, out string address, out string paymentId) diff --git a/src/MiningCore/Blockchain/ZCash/ZCashConstants.cs b/src/MiningCore/Blockchain/ZCash/ZCashConstants.cs index fd94ae50f..e8ac8fe22 100644 --- a/src/MiningCore/Blockchain/ZCash/ZCashConstants.cs +++ b/src/MiningCore/Blockchain/ZCash/ZCashConstants.cs @@ -29,14 +29,14 @@ namespace MiningCore.Blockchain.ZCash public class ZCashCoinbaseTxConfig { public bool PayFoundersReward { get; set; } - public int PercentFoundersReward { get; set; } + public decimal PercentFoundersReward { get; set; } public string[] FoundersRewardAddresses { get; set; } public ulong FoundersRewardSubsidySlowStartInterval { get; set; } public ulong FoundersRewardSubsidyHalvingInterval { get; set; } public ulong FoundersRewardSubsidySlowStartShift => FoundersRewardSubsidySlowStartInterval / 2; public ulong LastFoundersRewardBlockHeight => FoundersRewardSubsidyHalvingInterval + FoundersRewardSubsidySlowStartShift - 1; - public int PercentTreasuryReward { get; set; } + public decimal PercentTreasuryReward { get; set; } public ulong TreasuryRewardStartBlockHeight { get; set; } public string[] TreasuryRewardAddresses { get; set; } public double TreasuryRewardAddressChangeInterval { get; set; } @@ -119,7 +119,7 @@ public class ZCashConstants } }, }; - + private static readonly Dictionary ZCLCoinbaseTxConfig = new Dictionary { { @@ -166,11 +166,116 @@ public class ZCashConstants }, }; + private static readonly Dictionary ZencashCoinbaseTxConfig = new Dictionary + { + { + BitcoinNetworkType.Main, new ZCashCoinbaseTxConfig + { + PayFoundersReward = true, + PercentFoundersReward = 8.5m, + FoundersRewardSubsidyHalvingInterval = 840000, + FoundersRewardSubsidySlowStartInterval = 2, + + FoundersRewardAddresses = new[] + { + "zssEdGnZCQ9G86LZFtbynMn1hYTVhn6eYCL", "zsrCsXXmUf8k59NLasEKfxA7us3iNvaPATz", "zsnLPsWMXW2s4w9EmFSwtSLRxL2LhPcfdby", + "zshdovbcPfUAfkPeEE2qLbKnoue9RsbVokU", "zsqmq97JAKCCBFRGvxgv6FiJgQLCZBDp62S", "zskyFVFA7VRYX8EGdXmYN75WaBB25FmiL3g", + "zsmncLmwEUdVmAGPUrUnNKmPGXyej7mbmdM", "zsfa9VVJCEdjfPbku4XrFcRR8kTDm2T64rz", "zsjdMnfWuFi46VeN2HSXVQWEGsnGHgVxayY", + "zseb8wRQ8rZ722oLX5B8rx7qwZiBRb9mdig", "zsjxkovhqiMVggoW7jvSRi3NTSD3a6b6qfd", "zsokCCSU3wvZrS2G6mEDpJ5cH49E7sDyNr1", + "zt12EsFgkABHLMRXA7JNnpMqLrxsgCLnVEV", "zt39mvuG9gDTHX8A8Qk45rbk3dSdQoJ8ZAv", "zssTQZs5YxDGijKC86dvcDxzWogWcK7n5AK", + "zsywuMoQK7Bved2nrXs56AEtWBhpb88rMzS", "zsxVS2w7h1fHFX2nQtGm4372pd4DSHzq9ee", "zsupGi7ro3uC8CEVwm9r7vrdVUZaXQnHF6T", + "zshVZvW47dA5AB3Sqk1h7ytwWJeUJUJxxaE", "zsubBCjvDx252MKFsL4Dcf5rJU9Z9Upqr1N", "zsweaST3NcU4hfgkVULfCsfEq41pjgMDgcW", + "zswz6Rxb1S33fUpftETZwtGiVSeYxNKq2xc", "zswnpHtiBbrvYDzbhPQshkgvLSfYhDMRJ4S", "zsjSYAWaEYj35Ht7aXrRJUGY6Dc8qCmgYqu", + "zsvMv8fGroWR8epbSiGDCJHmfe6ec2uFQrt", "zsujxCT56BExQDAwKwktBjtnopYnw8BiKbg", "zsxeXc2FTAzmUmeZmqVsKVdwTMSvzyns4rT", + "zsuLqgABNudD8bVPbVGeUjGqapuoXp68i7F", "zsoc39J1dCFK1U8kckZznvQkv8As7sajYLz", "zt21NFdu1KRPJ7VRKtrWugM2Jqe5ePNmU4T", + "zsp15qbVcbx9ifcjKe6XZEJTvzsFUZ2BHLT", "zso2KvqH6yxLQEYggHdmfL3Tcd5V6E9tqhp", "zsnFG2W5ZHRYh3QucNze4mp31tBkemtfxdj", + "zsex2CGJtxHyHbpLXm7kESBmp3vWRqUkJMy", "zsvtFv96nrgrXKUbtNe2BpCt8aQEp5oJ7F8", "zsk5KitThmhK9KBa1KDybPgEmGSFTHzhMVA", + "zsuy4n48c4NsJyaCZEzwdAKULM1FqbB6Y4z", "zsgtQVMpX2zNMLvHHG2NDwfqKoaebvVectJ", "zszQqXRSPGdqsWw4iaMTNN6aJz4JjEzSdCF", + "zst6dBLrTtaMQBX7BLMNjKLTGcP11PBmgTV", "zshD9r6Eb6dZGdzYW2HCb9CzkMokCT1NGJR", "zswUaj1TboEGmvSfF7fdoxWyH3RMx7MBHHo", + "zsv8s4Poi5GxCsbBrRJ97Vsvazp84nrz5AN", "zsmmxrKU6dqWFwUKow1iyovg3gxrgXpEivr", "zskh1221aRC9WEfb5a59WxffeW34McmZZsw", + "zssAhuj57NnVm4yNFT6o8muRctABkUaBu3L", "zsi5Yr4Z8HwBvdBqQE8gk7ahExDu95J4oqZ", "zsy6ryEaxfk8emJ8bGVB7tmwRwBL8cfSqBW", + }, + + PercentTreasuryReward = 12, + TreasuryRewardAddressChangeInterval = 50000, + TreasuryRewardStartBlockHeight = 139200, + + TreasuryRewardAddresses = new[] + { + "zsyF68hcYYNLPj5i4PfQJ1kUY6nsFnZkc82", "zsfULrmbX7xbhqhAFRffVqCw9RyGv2hqNNG", + "zsoemTfqjicem2QVU8cgBHquKb1o9JR5p4Z", "zt339oiGL6tTgc9Q71f5g1sFTZf6QiXrRUr" + } + } + }, + { + BitcoinNetworkType.Test, new ZCashCoinbaseTxConfig + { + PayFoundersReward = true, + PercentFoundersReward = 8.5m, + FoundersRewardSubsidyHalvingInterval = 840000, + FoundersRewardSubsidySlowStartInterval = 2, + + FoundersRewardAddresses = new[] + { + "zrH8KT8KUcpKKNBu3fjH4hA84jZBCawErqn", "zrGsMC4ou1r5Vxy7Dnxg4PfKpansx83BM8g", "zr6sB2Az36D8CqzeZNavB11WbovsGtJSAZG", + "zrBAG3pXCTDq14nivNK9mW8SfwMNcdmMQpb", "zrRLwpYRYky4wsvwLVrDp8fs89EBTRhNMB1", "zrLozMfptTmE3zLP5SrTLyB8TXqH84Agjrr", + "zrMckkaLtVTEUvxj4ouU7BPDGa8xmdTZSVE", "zrFc897wJXmF7BcEdbvi2mS1bLrcuWYK6hm", "zrHEnni486u9SNcLWacroSgcdyMA33tfM92", + "zrJ3ymPV3R8Xk4N3BdNb898xvZvARm5K7mq", "zrDj3P6trx73291krxU51U9QnfkbGxkyJ6E", "zrJs3vMGFJi9pQCireeSLckJonamBnwTSrY", + "zrKFdXQoAkkycy52EFoWARyzZWx6Kat2Som", "zrEXbSe79FXA9KRMnJTZUWZdZhNnjcnAdrq", "zr7iAwfNgJsMpSCmijK3TuVDuNvSmLr1rUz", + "zrDEK7K6cftqSjeyVUH1WqJtBUkXN7GidxH", "zrRennuq75hyBVU4JymtZk8UcQ1vRPKpmpj", "zr9HRTL79pKmn5R8fvkC9kucZ4u1bQruLTD", + "zrML8KXpJsa1NVnbJuawX86ZvAn543tWdTT", "zrLBAkQoxpEtnztSUEcdxnEvuwtgxyAMGX7", "zr6kPnVzFBYmcBDsWoTrPHRuBxLq21o4zvT", + "zrMY3vdvqs9KSvx9TawvcyuVurt1Jj6GPVo", "zr9WB1qBpM4nwi1mudUFfjtMNmqzaBQDsXn", "zrAHbtHDPAqmzWJMQqSYzGyFnDWN3oELZRs", + "zrH1f5K3z7EQ6RWWZ7StCDWHTZwFChBVA2W", "zrNTacAid9LS4kAqzM4sw1YcF7gLFrzVM7U", "zrFyZpMVKMeDqbn6A2uUiL9mZmgxuR1pUBg", + "zrD1cqGFGzBcPogFHJvnN4XegvvmbTjA43t", "zr5A1D7czWkB4pAWfGC5Pux5Ek7anYybdPK", "zr8yTAxCy6jAdsc6qPvmVEQHbYo25AJKhy9", + "zrFW2YjQw4cABim5kEDwapbSqTz3wW7cWkk", "zr9nJvNbsrvUTZD41fhqAQeUcgMfqZmAweN", "zrCx4dXZd5b2tD483Ds4diHpo1QxBMJ76Jr", + "zr6eVeRwU6Puob3K1RfWtva1R458oj8pzkL", "zr7B92iHtQcobZjGCXo3DAqMQjsn7ka31wE", "zr8bcemLWAjYuphXSVqtqZWEnJipCB9F5oC", + "zrFzsuPXb7HsFd3srBqtVqnC9GQ94DQubV2", "zr4yiBobiHjHnCYi75NmYtyoqCV4A3kpHDL", "zrGVdR4K4F8MfmWxhUiTypK7PTsvHi8uTAh", + "zr7WiCDqCMvUdH1xmMu8YrBMFb2x2E6BX3z", "zrEFrGWLX4hPHuHRUD3TPbMAJyeSpMSctUc", "zr5c3f8PTnW8qBFX1GvK2LhyLBBCb1WDdGG", + "zrGkAZkZLqC9QKJR3XomgxNizCpNuAupTeg", "zrM7muDowiun9tCHhu5K9vcDGfUptuYorfZ", "zrCsWfwKotWnQmFviqAHAPAJ2jXqZYW966P", + "zrLLB3JB3jozUoMGFEGhjqyVXTpngVQ8c4T", "zrAEa8YjJ2f3m2VsM1Xa9EwibZxEnRoSLUx", "zrAdJgp7Cx35xTvB7ABWP8YLTNDArMjP1s3" + }, + + PercentTreasuryReward = 12, + TreasuryRewardAddressChangeInterval = 10000, + TreasuryRewardStartBlockHeight = 85500, + + TreasuryRewardAddresses = new[] + { + "zrRBQ5heytPMN5nY3ssPf3cG4jocXeD8fm1" + } + } + }, + { + BitcoinNetworkType.RegTest, new ZCashCoinbaseTxConfig + { + PayFoundersReward = true, + PercentFoundersReward = 8.5m, + FoundersRewardSubsidyHalvingInterval = 2000, + FoundersRewardSubsidySlowStartInterval = 0, + + FoundersRewardAddresses = new[] + { + "zrKmSdqZKZjnARd5e8FfRg4v1m74X7twxGa", + }, + + PercentTreasuryReward = 12, + TreasuryRewardAddressChangeInterval = 100, + TreasuryRewardStartBlockHeight = 139200, + + TreasuryRewardAddresses = new[] + { + "zrKmSdqZKZjnARd5e8FfRg4v1m74X7twxGa" + } + } + }, + }; + public static Dictionary> CoinbaseTxConfig = new Dictionary> { { CoinType.ZEC, ZCashCoinbaseTxConfig }, - { CoinType.ZCL, ZCLCoinbaseTxConfig } + { CoinType.ZCL, ZCLCoinbaseTxConfig }, + { CoinType.ZEN, ZencashCoinbaseTxConfig } }; } diff --git a/src/MiningCore/Blockchain/ZCash/ZCashPayoutHandler.cs b/src/MiningCore/Blockchain/ZCash/ZCashPayoutHandler.cs index b707341f7..40543b7a8 100644 --- a/src/MiningCore/Blockchain/ZCash/ZCashPayoutHandler.cs +++ b/src/MiningCore/Blockchain/ZCash/ZCashPayoutHandler.cs @@ -39,7 +39,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. namespace MiningCore.Blockchain.ZCash { - [CoinMetadata(CoinType.ZEC, CoinType.ZCL)] + [CoinMetadata(CoinType.ZEC, CoinType.ZCL, CoinType.ZEN)] public class ZCashPayoutHandler : BitcoinPayoutHandler { public ZCashPayoutHandler( diff --git a/src/MiningCore/Blockchain/ZCash/ZCashPool.cs b/src/MiningCore/Blockchain/ZCash/ZCashPool.cs index 1cf2ca629..571078eb9 100644 --- a/src/MiningCore/Blockchain/ZCash/ZCashPool.cs +++ b/src/MiningCore/Blockchain/ZCash/ZCashPool.cs @@ -32,7 +32,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. namespace MiningCore.Blockchain.ZCash { - [CoinMetadata(CoinType.ZEC, CoinType.ZCL)] + [CoinMetadata(CoinType.ZEC, CoinType.ZCL, CoinType.ZEN)] public class ZCashPool : ZCashPoolBase { public ZCashPool(IComponentContext ctx, diff --git a/src/MiningCore/Configuration/ClusterConfig.cs b/src/MiningCore/Configuration/ClusterConfig.cs index 359245535..69c15ed49 100644 --- a/src/MiningCore/Configuration/ClusterConfig.cs +++ b/src/MiningCore/Configuration/ClusterConfig.cs @@ -38,7 +38,8 @@ public enum CoinType VIA, // Viacoin PPC, // Peercoin ZEC, // ZCash - ZCL, // Zcassic + ZCL, // ZClassic + ZEN, // Zencash ETH, // Ethereum ETC, // Ethereum Classic EXP, // Expanse @@ -51,7 +52,10 @@ public enum CoinType AEON, // AEON STAK, // Straks ETN, // Electroneum - MOON //MoonCoin + MOON, // MoonCoin + XVG, // Verge + GBX, // GoByte + CRC, // CrowdCoin } public class CoinConfig diff --git a/src/MiningCore/Crypto/Hashing/Algorithms/NeoScrypt.cs b/src/MiningCore/Crypto/Hashing/Algorithms/NeoScrypt.cs new file mode 100644 index 000000000..39e207f0e --- /dev/null +++ b/src/MiningCore/Crypto/Hashing/Algorithms/NeoScrypt.cs @@ -0,0 +1,54 @@ +/* +Copyright 2017 Coin Foundry (coinfoundry.org) +Authors: Oliver Weichhold (oliver@weichhold.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +using System; +using MiningCore.Contracts; +using MiningCore.Native; + +namespace MiningCore.Crypto.Hashing.Algorithms +{ + public unsafe class NeoScrypt : IHashAlgorithm + { + public NeoScrypt(uint profile) + { + this.profile = profile; + } + + private readonly uint profile; + + public byte[] Digest(byte[] data, params object[] extra) + { + Contract.RequiresNonNull(data, nameof(data)); + Contract.Requires(data.Length == 80, $"{nameof(data)} length must be exactly 80 bytes"); + + var result = new byte[32]; + + fixed (byte* input = data) + { + fixed (byte* output = result) + { + LibMultihash.neoscrypt(input, output, (uint)data.Length, profile); + } + } + + return result; + } + } +} diff --git a/src/MiningCore/Crypto/Hashing/Algorithms/Scrypt.cs b/src/MiningCore/Crypto/Hashing/Algorithms/Scrypt.cs index 096fed4be..5af65b48f 100644 --- a/src/MiningCore/Crypto/Hashing/Algorithms/Scrypt.cs +++ b/src/MiningCore/Crypto/Hashing/Algorithms/Scrypt.cs @@ -1,20 +1,20 @@ -/* +/* Copyright 2017 Coin Foundry (coinfoundry.org) Authors: Oliver Weichhold (oliver@weichhold.com) -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ @@ -40,11 +40,11 @@ public byte[] Digest(byte[] data, params object[] extra) var result = new byte[32]; - fixed(byte* input = data) + fixed (byte* input = data) { - fixed(byte* output = result) + fixed (byte* output = result) { - LibMultihash.scrypt(input, output, n, r, (uint) data.Length); + LibMultihash.scrypt(input, output, n, r, (uint)data.Length); } } diff --git a/src/MiningCore/Crypto/Hashing/Algorithms/X17.cs b/src/MiningCore/Crypto/Hashing/Algorithms/X17.cs new file mode 100644 index 000000000..114179d8f --- /dev/null +++ b/src/MiningCore/Crypto/Hashing/Algorithms/X17.cs @@ -0,0 +1,45 @@ +/* +Copyright 2017 Coin Foundry (coinfoundry.org) +Authors: Oliver Weichhold (oliver@weichhold.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +using MiningCore.Contracts; +using MiningCore.Native; + +namespace MiningCore.Crypto.Hashing.Algorithms +{ + public unsafe class X17 : IHashAlgorithm + { + public byte[] Digest(byte[] data, params object[] extra) + { + Contract.RequiresNonNull(data, nameof(data)); + + var result = new byte[32]; + + fixed(byte* input = data) + { + fixed(byte* output = result) + { + LibMultihash.x17(input, output, (uint) data.Length); + } + } + + return result; + } + } +} diff --git a/src/MiningCore/DaemonInterface/DaemonClient.cs b/src/MiningCore/DaemonInterface/DaemonClient.cs index b1d1ec00d..5f3a7b902 100644 --- a/src/MiningCore/DaemonInterface/DaemonClient.cs +++ b/src/MiningCore/DaemonInterface/DaemonClient.cs @@ -28,17 +28,21 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System.Net.Http; using System.Net.Http.Headers; using System.Net.WebSockets; +using System.Reactive; using System.Reactive.Disposables; using System.Reactive.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using MiningCore.Blockchain.Bitcoin; using MiningCore.Buffers; using MiningCore.Configuration; using MiningCore.Extensions; using MiningCore.JsonRpc; using MiningCore.Stratum; using MiningCore.Util; +using NetMQ; +using NetMQ.Sockets; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NLog; @@ -229,6 +233,18 @@ public IObservable> WebsocketSubscribe(Dictionary[]> ZmqSubscribe(Dictionary portMap, string topic, int numMsgSegments = 2) + { + Contract.Requires(!string.IsNullOrEmpty(topic), $"{nameof(topic)} must not be empty"); + + logger.LogInvoke(new[] { topic }); + + return Observable.Merge(portMap.Keys + .Select(endPoint => ZmqSubscribeEndpoint(endPoint, portMap[endPoint], topic, numMsgSegments))) + .Publish() + .RefCount(); + } + #endregion // API-Surface private async Task BuildRequestTask(DaemonEndpointConfig endPoint, string method, object payload, @@ -471,5 +487,62 @@ private IObservable> WebsocketSubscribeEndpoint(DaemonE }); })); } + + private IObservable[]> ZmqSubscribeEndpoint(DaemonEndpointConfig endPoint, string url, string topic, int numMsgSegments = 2) + { + return Observable.Defer(() => Observable.Create[]>(obs => + { + var tcs = new CancellationTokenSource(); + + Task.Factory.StartNew(() => + { + using (tcs) + { + while (!tcs.IsCancellationRequested) + { + try + { + using (var subSocket = new SubscriberSocket()) + { + //subSocket.Options.ReceiveHighWatermark = 1000; + subSocket.Connect(url); + subSocket.Subscribe(topic); + + logger.Debug($"Subscribed to {url}/{BitcoinConstants.ZmqPublisherTopicBlockHash}"); + + while (!tcs.IsCancellationRequested) + { + var msg = subSocket.ReceiveMultipartMessage(numMsgSegments); + + // Export all frame data as array of PooledArraySegments + var result = msg.Select(x => + { + var buf = ArrayPool.Shared.Rent(x.BufferSize); + Array.Copy(x.ToByteArray(), buf, x.BufferSize); + return new PooledArraySegment(buf, 0, x.BufferSize); + }).ToArray(); + + obs.OnNext(result); + } + } + } + + catch (Exception ex) + { + logger.Error(ex); + } + + // do not consume all CPU cycles in case of a long lasting error condition + Thread.Sleep(1000); + } + } + }, tcs.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + + return Disposable.Create(() => + { + tcs.Cancel(); + }); + })); + } } } diff --git a/src/MiningCore/Extensions/DictionaryExtensions.cs b/src/MiningCore/Extensions/DictionaryExtensions.cs new file mode 100644 index 000000000..e938e19e5 --- /dev/null +++ b/src/MiningCore/Extensions/DictionaryExtensions.cs @@ -0,0 +1,45 @@ +/* +Copyright 2017 Coin Foundry (coinfoundry.org) +Authors: Oliver Weichhold (oliver@weichhold.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; + +namespace MiningCore.Extensions +{ + public static class DictionaryExtensions + { + public static void StripValue(this IDictionary dict, string key) + { + key = key.ToLower(CultureInfo.InvariantCulture); + + var keyActual = dict.Keys.FirstOrDefault(x => x.ToLower(CultureInfo.InvariantCulture) == key); + + if (keyActual != null) + { + var result = dict.Remove(keyActual); + Debug.Assert(result); + } + } + } +} diff --git a/src/MiningCore/Extensions/PoolingExtensions.cs b/src/MiningCore/Extensions/PoolingExtensions.cs new file mode 100644 index 000000000..ad384063a --- /dev/null +++ b/src/MiningCore/Extensions/PoolingExtensions.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MiningCore.Buffers; + +namespace MiningCore.Extensions +{ + public static class PoolingExtensions + { + public static void Dispose(this IEnumerable> col) + { + foreach(var seg in col) + seg.Dispose(); + } + } +} diff --git a/src/MiningCore/Extensions/StringExtensions.cs b/src/MiningCore/Extensions/StringExtensions.cs index 89d996c2a..d15735cbe 100644 --- a/src/MiningCore/Extensions/StringExtensions.cs +++ b/src/MiningCore/Extensions/StringExtensions.cs @@ -25,7 +25,6 @@ namespace MiningCore.Extensions { public static class StringExtensions { - /// /// Converts a str string to byte array. /// @@ -55,6 +54,11 @@ public static string ToStringHex8(this uint value) return value.ToString("x8", CultureInfo.InvariantCulture); } + public static string ToStringHex8(this int value) + { + return value.ToString("x8", CultureInfo.InvariantCulture); + } + public static string ToStringHexWithPrefix(this ulong value) { if (value == 0) diff --git a/src/MiningCore/Native/LibMultihash.cs b/src/MiningCore/Native/LibMultihash.cs index c53ca8c7f..2a44cf53c 100644 --- a/src/MiningCore/Native/LibMultihash.cs +++ b/src/MiningCore/Native/LibMultihash.cs @@ -1,20 +1,20 @@ -/* +/* Copyright 2017 Coin Foundry (coinfoundry.org) Authors: Oliver Weichhold (oliver@weichhold.com) -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ @@ -37,8 +37,11 @@ public static unsafe class LibMultihash [DllImport("libmultihash", EntryPoint = "x15_export", CallingConvention = CallingConvention.Cdecl)] public static extern int x15(byte* input, byte* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "x17_export", CallingConvention = CallingConvention.Cdecl)] + public static extern int x17(byte* input, byte* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "neoscrypt_export", CallingConvention = CallingConvention.Cdecl)] - public static extern int neoscrypt(byte* input, byte* output, uint inputLength, int profile); + public static extern int neoscrypt(byte* input, byte* output, uint inputLength, uint profile); [DllImport("libmultihash", EntryPoint = "scryptn_export", CallingConvention = CallingConvention.Cdecl)] public static extern int scryptn(byte* input, byte* output, uint nFactor, uint inputLength); diff --git a/src/MiningCore/Notifications/NotificationService.cs b/src/MiningCore/Notifications/NotificationService.cs index 6bf241f8e..32f605453 100644 --- a/src/MiningCore/Notifications/NotificationService.cs +++ b/src/MiningCore/Notifications/NotificationService.cs @@ -99,7 +99,7 @@ public void NotifyPaymentSuccess(string poolId, decimal amount, int recpientsCou Category = NotificationCategory.PaymentSuccess, PoolId = poolId, Subject = "Payout Success Notification", - Msg = $"Paid out {FormatAmount(amount, poolId)} from pool {poolId} to {recpientsCount} recipients in Transaction(s) {txInfo}." + Msg = $"Paid {FormatAmount(amount, poolId)} from pool {poolId} to {recpientsCount} recipients in Transaction(s) {txInfo}." }); } diff --git a/src/MiningCore/Payments/PayoutHandlerBase.cs b/src/MiningCore/Payments/PayoutHandlerBase.cs index 2d758c985..0fc2d0062 100644 --- a/src/MiningCore/Payments/PayoutHandlerBase.cs +++ b/src/MiningCore/Payments/PayoutHandlerBase.cs @@ -157,7 +157,7 @@ protected virtual void NotifyPayoutSuccess(string poolId, Balance[] balances, st // prepare tx link var txInfo = string.Join(", ", txHashes); - if (CoinMetaData.PaymentInfoLinks.TryGetValue(poolConfig.Coin.Type, out var baseUrl)) + if (CoinMetaData.TxInfoLinks.TryGetValue(poolConfig.Coin.Type, out var baseUrl)) txInfo = string.Join(", ", txHashes.Select(txHash => $"{txHash}")); notificationService.NotifyPaymentSuccess(poolId, balances.Sum(x => x.Amount), balances.Length, txInfo, txFee); diff --git a/src/MiningCore/Persistence/Postgres/Repositories/StatsRepository.cs b/src/MiningCore/Persistence/Postgres/Repositories/StatsRepository.cs index 0b0cb87d2..c7de52c9d 100644 --- a/src/MiningCore/Persistence/Postgres/Repositories/StatsRepository.cs +++ b/src/MiningCore/Persistence/Postgres/Repositories/StatsRepository.cs @@ -84,6 +84,16 @@ public PoolStats GetLastPoolStats(IDbConnection con, string poolId) return mapper.Map(entity); } + public decimal GetTotalPoolPayments(IDbConnection con, string poolId) + { + logger.LogInvoke(); + + var query = "SELECT sum(amount) FROM payments WHERE poolid = @poolId"; + + var result = con.ExecuteScalar(query, new { poolId }); + return result; + } + public PoolStats[] GetPoolPerformanceBetweenHourly(IDbConnection con, string poolId, DateTime start, DateTime end) { logger.LogInvoke(new []{ poolId }); diff --git a/src/MiningCore/Persistence/Repositories/IStatsRepository.cs b/src/MiningCore/Persistence/Repositories/IStatsRepository.cs index 2bc58a450..e6e4c8829 100644 --- a/src/MiningCore/Persistence/Repositories/IStatsRepository.cs +++ b/src/MiningCore/Persistence/Repositories/IStatsRepository.cs @@ -31,6 +31,7 @@ public interface IStatsRepository void InsertPoolStats(IDbConnection con, IDbTransaction tx, PoolStats stats); void InsertMinerWorkerPerformanceStats(IDbConnection con, IDbTransaction tx, MinerWorkerPerformanceStats stats); PoolStats GetLastPoolStats(IDbConnection con, string poolId); + decimal GetTotalPoolPayments(IDbConnection con, string poolId); PoolStats[] GetPoolPerformanceBetweenHourly(IDbConnection con, string poolId, DateTime start, DateTime end); MinerStats GetMinerStats(IDbConnection con, IDbTransaction tx, string poolId, string miner); MinerWorkerPerformanceStats[] PagePoolMinersByHashrate(IDbConnection con, string poolId, DateTime from, int page, int pageSize); diff --git a/src/MiningCore/Program.cs b/src/MiningCore/Program.cs index f18e61fdb..eb438a599 100644 --- a/src/MiningCore/Program.cs +++ b/src/MiningCore/Program.cs @@ -505,7 +505,7 @@ private static void ConfigurePostgres(DatabaseConfig pgConfig, ContainerBuilder logger.ThrowLogPoolStartupException("Postgres configuration: invalid or missing 'user'"); // build connection string - var connectionString = $"Server={pgConfig.Host};Port={pgConfig.Port};Database={pgConfig.Database};User Id={pgConfig.User};Password={pgConfig.Password};CommandTimeout=90;"; + var connectionString = $"Server={pgConfig.Host};Port={pgConfig.Port};Database={pgConfig.Database};User Id={pgConfig.User};Password={pgConfig.Password};CommandTimeout=300;"; // register connection factory builder.RegisterInstance(new ConnectionFactory(connectionString)) diff --git a/src/MiningCore/runtimes/win-x64/native/libmultihash.dll b/src/MiningCore/runtimes/win-x64/native/libmultihash.dll index d5b8a193b..ee0b76888 100644 Binary files a/src/MiningCore/runtimes/win-x64/native/libmultihash.dll and b/src/MiningCore/runtimes/win-x64/native/libmultihash.dll differ diff --git a/src/MiningCore/runtimes/win-x86/native/libmultihash.dll b/src/MiningCore/runtimes/win-x86/native/libmultihash.dll index 9caa71ac6..db45fc4d2 100644 Binary files a/src/MiningCore/runtimes/win-x86/native/libmultihash.dll and b/src/MiningCore/runtimes/win-x86/native/libmultihash.dll differ diff --git a/src/Native/libmultihash/Makefile b/src/Native/libmultihash/Makefile index f74270fe1..8bd23a1bd 100644 --- a/src/Native/libmultihash/Makefile +++ b/src/Native/libmultihash/Makefile @@ -10,7 +10,8 @@ OBJECTS = bcrypt.o blake.o c11.o dcrypt.o fresh.o \ sha3/aes_helper.o sha3/hamsi.o sha3/hamsi_helper.o sha3/sph_blake.o sha3/sph_bmw.o sha3/sph_cubehash.o \ sha3/sph_echo.o sha3/sph_fugue.o sha3/sph_groestl.o sha3/sph_hefty1.o sha3/sph_jh.o sha3/sph_keccak.o \ sha3/sph_luffa.o sha3/sph_shabal.o sha3/sph_shavite.o sha3/sph_simd.o sha3/sph_skein.o sha3/sph_whirlpool.o \ - shavite3.o skein.o x11.o x15.o \ + sha3/sph_haval.o sha3/sph_sha2.o sha3/sph_sha2big.o \ + shavite3.o skein.o x11.o x15.o x17.o \ Lyra2.o Lyra2RE.o Sponge.o \ equi/endian.o equi/equi.o \ libethash/internal.o libethash/io.o libethash/io_posix.o libethash/sha3.o diff --git a/src/Native/libmultihash/exports.cpp b/src/Native/libmultihash/exports.cpp index ade36801b..4c2be0c56 100644 --- a/src/Native/libmultihash/exports.cpp +++ b/src/Native/libmultihash/exports.cpp @@ -34,6 +34,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "x14.h" #include "nist5.h" #include "x15.h" +#include "x17.h" #include "fresh.h" #include "dcrypt.h" #include "jh.h" @@ -68,12 +69,17 @@ extern "C" MODULE_API void x11_export(const char* input, char* output, uint32_t x11_hash(input, output, input_len); } +extern "C" MODULE_API void x17_export(const char* input, char* output, uint32_t input_len) +{ + x17_hash(input, output, input_len); +} + extern "C" MODULE_API void x15_export(const char* input, char* output, uint32_t input_len) { x15_hash(input, output, input_len); } -extern "C" MODULE_API void neoscrypt_export(const char* input, char* output, uint32_t profile) +extern "C" MODULE_API void neoscrypt_export(const unsigned char* input, unsigned char* output, uint32_t profile) { neoscrypt(input, output, profile); } diff --git a/src/Native/libmultihash/libmultihash.vcxproj b/src/Native/libmultihash/libmultihash.vcxproj index 347583c2d..a12686db6 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj +++ b/src/Native/libmultihash/libmultihash.vcxproj @@ -202,10 +202,12 @@ + + @@ -222,6 +224,7 @@ + @@ -254,17 +257,19 @@ - + + + @@ -278,6 +283,7 @@ + diff --git a/src/Native/libmultihash/libmultihash.vcxproj.filters b/src/Native/libmultihash/libmultihash.vcxproj.filters index 5dcfc1bf9..96053bcf3 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj.filters +++ b/src/Native/libmultihash/libmultihash.vcxproj.filters @@ -191,6 +191,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + @@ -271,9 +280,6 @@ Source Files - - Source Files - Source Files @@ -355,6 +361,18 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + diff --git a/src/Native/libmultihash/neoscrypt.c b/src/Native/libmultihash/neoscrypt.c index 0811cee81..228c57bb5 100644 --- a/src/Native/libmultihash/neoscrypt.c +++ b/src/Native/libmultihash/neoscrypt.c @@ -2,7 +2,7 @@ * Copyright (c) 2009 Colin Percival, 2011 ArtForz * Copyright (c) 2012 Andrew Moon (floodyberry) * Copyright (c) 2012 Samuel Neves - * Copyright (c) 2014 John Doering + * Copyright (c) 2014-2016 John Doering * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,38 +34,24 @@ #include "neoscrypt.h" -#if (_MSC_VER) -#include -#endif - -#if (WINDOWS) -/* sizeof(unsigned long) = 4 for MinGW64 */ -typedef unsigned long long ulong; -#else -typedef unsigned long ulong; -#endif -typedef unsigned int uint; -typedef unsigned char uchar; -typedef unsigned int bool; +#ifdef _WIN32 +#include +#define alloca(x) _alloca(x) +#endif - -#define MIN(a, b) ((a) < (b) ? a : b) -#define MAX(a, b) ((a) > (b) ? a : b) - - -#if (NEOSCRYPT_SHA256) +#ifdef SHA256 /* SHA-256 */ -static const uint32_t sha256_constants[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +static const uint sha256_constants[64] = { + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 }; #define Ch(x,y,z) (z ^ (x & (y ^ z))) @@ -88,18 +74,15 @@ static const uint32_t sha256_constants[64] = { r[1] = r[0]; \ r[0] = t0 + t1; - typedef struct sha256_hash_state_t { - uint32_t H[8]; - uint64_t T; - uint32_t leftover; - uint8_t buffer[SCRYPT_HASH_BLOCK_SIZE]; + uint H[8]; + ullong T; + uint leftover; + uchar buffer[BLOCK_SIZE]; } sha256_hash_state; - -static void sha256_blocks(sha256_hash_state *S, const uint8_t *in, size_t blocks) { - uint32_t r[8], w[64], t0, t1; - size_t i; +static void sha256_blocks(sha256_hash_state *S, const uchar *in, uint blocks) { + uint r[8], w[64], t0, t1, i; for(i = 0; i < 8; i++) r[i] = S->H[i]; @@ -118,34 +101,34 @@ static void sha256_blocks(sha256_hash_state *S, const uint8_t *in, size_t blocks r[i] += S->H[i]; S->H[i] = r[i]; } - S->T += SCRYPT_HASH_BLOCK_SIZE * 8; - in += SCRYPT_HASH_BLOCK_SIZE; + S->T += BLOCK_SIZE * 8; + in += BLOCK_SIZE; } } static void neoscrypt_hash_init_sha256(sha256_hash_state *S) { - S->H[0] = 0x6a09e667; - S->H[1] = 0xbb67ae85; - S->H[2] = 0x3c6ef372; - S->H[3] = 0xa54ff53a; - S->H[4] = 0x510e527f; - S->H[5] = 0x9b05688c; - S->H[6] = 0x1f83d9ab; - S->H[7] = 0x5be0cd19; + S->H[0] = 0x6A09E667; + S->H[1] = 0xBB67AE85; + S->H[2] = 0x3C6EF372; + S->H[3] = 0xA54FF53A; + S->H[4] = 0x510E527F; + S->H[5] = 0x9B05688C; + S->H[6] = 0x1F83D9AB; + S->H[7] = 0x5BE0CD19; S->T = 0; S->leftover = 0; } -static void neoscrypt_hash_update_sha256(sha256_hash_state *S, const uint8_t *in, size_t inlen) { - size_t blocks, want; +static void neoscrypt_hash_update_sha256(sha256_hash_state *S, const uchar *in, uint inlen) { + uint blocks, want; /* handle the previous data */ if(S->leftover) { - want = (SCRYPT_HASH_BLOCK_SIZE - S->leftover); + want = (BLOCK_SIZE - S->leftover); want = (want < inlen) ? want : inlen; - memcpy(S->buffer + S->leftover, in, want); - S->leftover += (uint32_t)want; - if(S->leftover < SCRYPT_HASH_BLOCK_SIZE) + neoscrypt_copy(S->buffer + S->leftover, in, want); + S->leftover += (uint)want; + if(S->leftover < BLOCK_SIZE) return; in += want; inlen -= want; @@ -153,28 +136,28 @@ static void neoscrypt_hash_update_sha256(sha256_hash_state *S, const uint8_t *in } /* handle the current data */ - blocks = (inlen & ~(SCRYPT_HASH_BLOCK_SIZE - 1)); - S->leftover = (uint32_t)(inlen - blocks); + blocks = (inlen & ~(BLOCK_SIZE - 1)); + S->leftover = (uint)(inlen - blocks); if(blocks) { - sha256_blocks(S, in, blocks / SCRYPT_HASH_BLOCK_SIZE); + sha256_blocks(S, in, blocks / BLOCK_SIZE); in += blocks; } /* handle leftover data */ if(S->leftover) - memcpy(S->buffer, in, S->leftover); + neoscrypt_copy(S->buffer, in, S->leftover); } -static void neoscrypt_hash_finish_sha256(sha256_hash_state *S, uint8_t *hash) { - uint64_t t = S->T + (S->leftover * 8); +static void neoscrypt_hash_finish_sha256(sha256_hash_state *S, uchar *hash) { + ullong t = S->T + (S->leftover * 8); S->buffer[S->leftover] = 0x80; if(S->leftover <= 55) { - memset(S->buffer + S->leftover + 1, 0, 55 - S->leftover); + neoscrypt_erase(S->buffer + S->leftover + 1, 55 - S->leftover); } else { - memset(S->buffer + S->leftover + 1, 0, 63 - S->leftover); + neoscrypt_erase(S->buffer + S->leftover + 1, 63 - S->leftover); sha256_blocks(S, S->buffer, 1); - memset(S->buffer, 0, 56); + neoscrypt_erase(S->buffer, 56); } U64TO8_BE(S->buffer + 56, t); @@ -190,13 +173,6 @@ static void neoscrypt_hash_finish_sha256(sha256_hash_state *S, uint8_t *hash) { U32TO8_BE(&hash[28], S->H[7]); } -static void neoscrypt_hash_sha256(hash_digest hash, const uint8_t *m, size_t mlen) { - sha256_hash_state st; - neoscrypt_hash_init_sha256(&st); - neoscrypt_hash_update_sha256(&st, m, mlen); - neoscrypt_hash_finish_sha256(&st, hash); -} - /* HMAC for SHA-256 */ @@ -204,40 +180,49 @@ typedef struct sha256_hmac_state_t { sha256_hash_state inner, outer; } sha256_hmac_state; -static void neoscrypt_hmac_init_sha256(sha256_hmac_state *st, const uint8_t *key, size_t keylen) { - uint8_t pad[SCRYPT_HASH_BLOCK_SIZE] = {0}; - size_t i; +static inline void neoscrypt_hmac_init_sha256(sha256_hmac_state *st, + const uchar *key, uint keylen) { + uchar pad[BLOCK_SIZE + DIGEST_SIZE]; + uint *P = (uint *) pad; + uint i; - neoscrypt_hash_init_sha256(&st->inner); - neoscrypt_hash_init_sha256(&st->outer); + /* The pad initialisation for the inner loop */ + for(i = 0; i < (BLOCK_SIZE >> 2); i++) + P[i] = 0x36363636; - if(keylen <= SCRYPT_HASH_BLOCK_SIZE) { - /* use the key directly if it's <= blocksize bytes */ - memcpy(pad, key, keylen); + if(keylen <= BLOCK_SIZE) { + /* XOR the key into the pad */ + neoscrypt_xor(pad, key, keylen); } else { - /* if it's > blocksize bytes, hash it */ - neoscrypt_hash_sha256(pad, key, keylen); + /* Hash the key and XOR into the pad */ + sha256_hash_state st0; + neoscrypt_hash_init_sha256(&st0); + neoscrypt_hash_update_sha256(&st0, key, keylen); + neoscrypt_hash_finish_sha256(&st0, &pad[BLOCK_SIZE]); + neoscrypt_xor(&pad[0], &pad[BLOCK_SIZE], DIGEST_SIZE); } - /* inner = (key ^ 0x36) */ - /* h(inner || ...) */ - for(i = 0; i < SCRYPT_HASH_BLOCK_SIZE; i++) - pad[i] ^= 0x36; - neoscrypt_hash_update_sha256(&st->inner, pad, SCRYPT_HASH_BLOCK_SIZE); - - /* outer = (key ^ 0x5c) */ - /* h(outer || ...) */ - for(i = 0; i < SCRYPT_HASH_BLOCK_SIZE; i++) - pad[i] ^= (0x5c ^ 0x36); - neoscrypt_hash_update_sha256(&st->outer, pad, SCRYPT_HASH_BLOCK_SIZE); + neoscrypt_hash_init_sha256(&st->inner); + /* h(inner || pad) */ + neoscrypt_hash_update_sha256(&st->inner, pad, BLOCK_SIZE); + + /* The pad re-initialisation for the outer loop */ + for(i = 0; i < (BLOCK_SIZE >> 2); i++) + P[i] ^= (0x36363636 ^ 0x5C5C5C5C); + + neoscrypt_hash_init_sha256(&st->outer); + /* h(outer || pad) */ + neoscrypt_hash_update_sha256(&st->outer, pad, BLOCK_SIZE); } -static void neoscrypt_hmac_update_sha256(sha256_hmac_state *st, const uint8_t *m, size_t mlen) { +static inline void neoscrypt_hmac_update_sha256(sha256_hmac_state *st, + const uchar *m, uint mlen) { /* h(inner || m...) */ neoscrypt_hash_update_sha256(&st->inner, m, mlen); } -static void neoscrypt_hmac_finish_sha256(sha256_hmac_state *st, hash_digest mac) { +static inline void neoscrypt_hmac_finish_sha256(sha256_hmac_state *st, + hash_digest mac) { /* h(inner || m) */ hash_digest innerhash; neoscrypt_hash_finish_sha256(&st->inner, innerhash); @@ -250,14 +235,14 @@ static void neoscrypt_hmac_finish_sha256(sha256_hmac_state *st, hash_digest mac) /* PBKDF2 for SHA-256 */ -static void neoscrypt_pbkdf2_sha256(const uint8_t *password, size_t password_len, - const uint8_t *salt, size_t salt_len, uint64_t N, uint8_t *output, size_t output_len) { +void neoscrypt_pbkdf2_sha256(const uchar *password, uint password_len, + const uchar *salt, uint salt_len, uint N, uchar *output, uint output_len) { sha256_hmac_state hmac_pw, hmac_pw_salt, work; hash_digest ti, u; - uint8_t be[4]; - uint32_t i, j, k, blocks; + uchar be[4]; + uint i, j, k, blocks; - /* bytes must be <= (0xffffffff - (SCRYPT_HASH_DIGEST_SIZE - 1)), which they will always be under scrypt */ + /* bytes must be <= (0xffffffff - (DIGEST_SIZE - 1)), which they will always be under scrypt */ /* hmac(password, ...) */ neoscrypt_hmac_init_sha256(&hmac_pw, password, password_len); @@ -266,20 +251,20 @@ static void neoscrypt_pbkdf2_sha256(const uint8_t *password, size_t password_len hmac_pw_salt = hmac_pw; neoscrypt_hmac_update_sha256(&hmac_pw_salt, salt, salt_len); - blocks = ((uint32_t)output_len + (SCRYPT_HASH_DIGEST_SIZE - 1)) / SCRYPT_HASH_DIGEST_SIZE; + blocks = ((uint)output_len + (DIGEST_SIZE - 1)) / DIGEST_SIZE; for(i = 1; i <= blocks; i++) { /* U1 = hmac(password, salt || be(i)) */ U32TO8_BE(be, i); work = hmac_pw_salt; neoscrypt_hmac_update_sha256(&work, be, 4); neoscrypt_hmac_finish_sha256(&work, ti); - memcpy(u, ti, sizeof(u)); + neoscrypt_copy(u, ti, sizeof(u)); /* T[i] = U1 ^ U2 ^ U3... */ for(j = 0; j < N - 1; j++) { /* UX = hmac(password, U{X-1}) */ work = hmac_pw; - neoscrypt_hmac_update_sha256(&work, u, SCRYPT_HASH_DIGEST_SIZE); + neoscrypt_hmac_update_sha256(&work, u, DIGEST_SIZE); neoscrypt_hmac_finish_sha256(&work, u); /* T[i] ^= UX */ @@ -287,47 +272,50 @@ static void neoscrypt_pbkdf2_sha256(const uint8_t *password, size_t password_len ti[k] ^= u[k]; } - memcpy(output, ti, (output_len > SCRYPT_HASH_DIGEST_SIZE) ? SCRYPT_HASH_DIGEST_SIZE : output_len); - output += SCRYPT_HASH_DIGEST_SIZE; - output_len -= SCRYPT_HASH_DIGEST_SIZE; + neoscrypt_copy(output, ti, (output_len > DIGEST_SIZE) ? DIGEST_SIZE : output_len); + output += DIGEST_SIZE; + output_len -= DIGEST_SIZE; } } -#endif +#endif /* SHA256 */ -#if (NEOSCRYPT_BLAKE256) +#ifdef BLAKE256 /* BLAKE-256 */ -const uint8_t blake256_sigma[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, - 14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3, - 11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4, - 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8, - 9, 0, 5, 7, 2, 4,10,15,14, 1,11,12, 6, 8, 3,13, - 2,12, 6,10, 0,11, 8, 3, 4,13, 7, 5,15,14, 1, 9, - 12, 5, 1,15,14,13, 4,10, 0, 7, 6, 3, 9, 2, 8,11, - 13,11, 7,14,12, 1, 3, 9, 5, 0,15, 4, 8, 6, 2,10, - 6,15,14, 9,11, 3, 0, 8,12, 2,13, 7, 1, 4,10, 5, - 10, 2, 8, 4, 7, 6, 1, 5,15,11, 9,14, 3,12,13 ,0, +const uchar blake256_sigma[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, + 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, + 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, + 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, + 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, + 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, + 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, + 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, + 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }; -const uint32_t blake256_constants[16] = { - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, - 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917 +const uint blake256_constants[16] = { + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917 }; typedef struct blake256_hash_state_t { - uint32_t H[8], T[2]; - uint32_t leftover; - uint8_t buffer[SCRYPT_HASH_BLOCK_SIZE]; + uint H[8]; + uint T[2]; + uint leftover; + uchar buffer[BLOCK_SIZE]; } blake256_hash_state; -static void blake256_blocks(blake256_hash_state *S, const uint8_t *in, size_t blocks) { - const uint8_t *sigma, *sigma_end = blake256_sigma + (10 * 16); - uint32_t m[16], v[16], h[8], t[2]; - uint32_t i; +static void blake256_blocks(blake256_hash_state *S, const uchar *in, uint blocks) { + const uchar *sigma, *sigma_end = blake256_sigma + (10 * 16); + uint m[16], v[16], h[8], t[2]; + uint i; for(i = 0; i < 8; i++) h[i] = S->H[i]; @@ -343,35 +331,35 @@ static void blake256_blocks(blake256_hash_state *S, const uint8_t *in, size_t bl for(i = 0; i < 4; i++) v[i + 8] = blake256_constants[i]; for(i = 0; i < 2; i++) - v[i + 12] = blake256_constants[i+4] ^ t[0]; + v[i + 12] = blake256_constants[i + 4] ^ t[0]; for(i = 0; i < 2; i++) - v[i + 14] = blake256_constants[i+6] ^ t[1]; + v[i + 14] = blake256_constants[i + 6] ^ t[1]; for(i = 0; i < 16; i++) m[i] = U8TO32_BE(&in[i * 4]); in += 64; -#define G(a,b,c,d,e) \ - v[a] += (m[sigma[e+0]] ^ blake256_constants[sigma[e+1]]) + v[b]; \ - v[d] = ROTR32(v[d] ^ v[a],16); \ +#define G(a, b, c, d, e) \ + v[a] += (m[sigma[e + 0]] ^ blake256_constants[sigma[e + 1]]) + v[b]; \ + v[d] = ROTR32(v[d] ^ v[a], 16); \ v[c] += v[d]; \ - v[b] = ROTR32(v[b] ^ v[c],12); \ - v[a] += (m[sigma[e+1]] ^ blake256_constants[sigma[e+0]]) + v[b]; \ + v[b] = ROTR32(v[b] ^ v[c], 12); \ + v[a] += (m[sigma[e + 1]] ^ blake256_constants[sigma[e + 0]]) + v[b]; \ v[d] = ROTR32(v[d] ^ v[a], 8); \ v[c] += v[d]; \ v[b] = ROTR32(v[b] ^ v[c], 7); for(i = 0, sigma = blake256_sigma; i < 14; i++) { - G(0, 4, 8,12, 0); - G(1, 5, 9,13, 2); - G(2, 6,10,14, 4); - G(3, 7,11,15, 6); + G( 0, 4, 8, 12, 0); + G( 1, 5, 9, 13, 2); + G( 2, 6, 10, 14, 4); + G( 3, 7, 11, 15, 6); - G(0, 5,10,15, 8); - G(1, 6,11,12,10); - G(2, 7, 8,13,12); - G(3, 4, 9,14,14); + G( 0, 5, 10, 15, 8); + G( 1, 6, 11, 12, 10); + G( 2, 7, 8, 13, 12); + G( 3, 4, 9, 14, 14); sigma += 16; if(sigma == sigma_end) @@ -404,16 +392,17 @@ static void neoscrypt_hash_init_blake256(blake256_hash_state *S) { S->leftover = 0; } -static void neoscrypt_hash_update_blake256(blake256_hash_state *S, const uint8_t *in, size_t inlen) { - size_t blocks, want; +static void neoscrypt_hash_update_blake256(blake256_hash_state *S, + const uchar *in, uint inlen) { + uint blocks, want; /* handle the previous data */ if(S->leftover) { - want = (SCRYPT_HASH_BLOCK_SIZE - S->leftover); + want = (BLOCK_SIZE - S->leftover); want = (want < inlen) ? want : inlen; - memcpy(S->buffer + S->leftover, in, want); - S->leftover += (uint32_t)want; - if(S->leftover < SCRYPT_HASH_BLOCK_SIZE) + neoscrypt_copy(S->buffer + S->leftover, in, want); + S->leftover += (uint)want; + if(S->leftover < BLOCK_SIZE) return; in += want; inlen -= want; @@ -421,29 +410,29 @@ static void neoscrypt_hash_update_blake256(blake256_hash_state *S, const uint8_t } /* handle the current data */ - blocks = (inlen & ~(SCRYPT_HASH_BLOCK_SIZE - 1)); - S->leftover = (uint32_t)(inlen - blocks); + blocks = (inlen & ~(BLOCK_SIZE - 1)); + S->leftover = (uint)(inlen - blocks); if(blocks) { - blake256_blocks(S, in, blocks / SCRYPT_HASH_BLOCK_SIZE); + blake256_blocks(S, in, blocks / BLOCK_SIZE); in += blocks; } /* handle leftover data */ if(S->leftover) - memcpy(S->buffer, in, S->leftover); + neoscrypt_copy(S->buffer, in, S->leftover); } -static void neoscrypt_hash_finish_blake256(blake256_hash_state *S, uint8_t *hash) { - uint32_t th, tl, bits; +static void neoscrypt_hash_finish_blake256(blake256_hash_state *S, uchar *hash) { + uint th, tl, bits; bits = (S->leftover << 3); tl = S->T[0] + bits; th = S->T[1]; if(S->leftover == 0) { - S->T[0] = (uint32_t)0 - (uint32_t)512; - S->T[1] = (uint32_t)0 - (uint32_t)1; + S->T[0] = (uint)0 - (uint)512; + S->T[1] = (uint)0 - (uint)1; } else if(S->T[0] == 0) { - S->T[0] = ((uint32_t)0 - (uint32_t)512) + bits; + S->T[0] = ((uint)0 - (uint)512) + bits; S->T[1] = S->T[1] - 1; } else { S->T[0] -= (512 - bits); @@ -451,13 +440,13 @@ static void neoscrypt_hash_finish_blake256(blake256_hash_state *S, uint8_t *hash S->buffer[S->leftover] = 0x80; if(S->leftover <= 55) { - memset(S->buffer + S->leftover + 1, 0, 55 - S->leftover); + neoscrypt_erase(S->buffer + S->leftover + 1, 55 - S->leftover); } else { - memset(S->buffer + S->leftover + 1, 0, 63 - S->leftover); + neoscrypt_erase(S->buffer + S->leftover + 1, 63 - S->leftover); blake256_blocks(S, S->buffer, 1); - S->T[0] = (uint32_t)0 - (uint32_t)512; - S->T[1] = (uint32_t)0 - (uint32_t)1; - memset(S->buffer, 0, 56); + S->T[0] = (uint)0 - (uint)512; + S->T[1] = (uint)0 - (uint)1; + neoscrypt_erase(S->buffer, 56); } S->buffer[55] |= 1; U32TO8_BE(S->buffer + 56, th); @@ -474,54 +463,57 @@ static void neoscrypt_hash_finish_blake256(blake256_hash_state *S, uint8_t *hash U32TO8_BE(&hash[28], S->H[7]); } -static void neoscrypt_hash_blake256(hash_digest hash, const uint8_t *m, size_t mlen) { - blake256_hash_state st; - neoscrypt_hash_init_blake256(&st); - neoscrypt_hash_update_blake256(&st, m, mlen); - neoscrypt_hash_finish_blake256(&st, hash); -} - /* HMAC for BLAKE-256 */ typedef struct blake256_hmac_state_t { - blake256_hash_state inner, outer; + blake256_hash_state inner; + blake256_hash_state outer; } blake256_hmac_state; -static void neoscrypt_hmac_init_blake256(blake256_hmac_state *st, const uint8_t *key, size_t keylen) { - uint8_t pad[SCRYPT_HASH_BLOCK_SIZE] = {0}; - size_t i; +static inline void neoscrypt_hmac_init_blake256(blake256_hmac_state *st, + const uchar *key, uint keylen) { + uchar pad[BLOCK_SIZE + DIGEST_SIZE]; + uint *P = (uint *) pad; + uint i; - neoscrypt_hash_init_blake256(&st->inner); - neoscrypt_hash_init_blake256(&st->outer); + /* The pad initialisation for the inner loop */ + for(i = 0; i < (BLOCK_SIZE >> 2); i++) + P[i] = 0x36363636; - if(keylen <= SCRYPT_HASH_BLOCK_SIZE) { - /* use the key directly if it's <= blocksize bytes */ - memcpy(pad, key, keylen); + if(keylen <= BLOCK_SIZE) { + /* XOR the key into the pad */ + neoscrypt_xor(pad, key, keylen); } else { - /* if it's > blocksize bytes, hash it */ - neoscrypt_hash_blake256(pad, key, keylen); + /* Hash the key and XOR into the pad */ + blake256_hash_state st0; + neoscrypt_hash_init_blake256(&st0); + neoscrypt_hash_update_blake256(&st0, key, keylen); + neoscrypt_hash_finish_blake256(&st0, &pad[BLOCK_SIZE]); + neoscrypt_xor(&pad[0], &pad[BLOCK_SIZE], DIGEST_SIZE); } - /* inner = (key ^ 0x36) */ - /* h(inner || ...) */ - for(i = 0; i < SCRYPT_HASH_BLOCK_SIZE; i++) - pad[i] ^= 0x36; - neoscrypt_hash_update_blake256(&st->inner, pad, SCRYPT_HASH_BLOCK_SIZE); - - /* outer = (key ^ 0x5c) */ - /* h(outer || ...) */ - for(i = 0; i < SCRYPT_HASH_BLOCK_SIZE; i++) - pad[i] ^= (0x5c ^ 0x36); - neoscrypt_hash_update_blake256(&st->outer, pad, SCRYPT_HASH_BLOCK_SIZE); + neoscrypt_hash_init_blake256(&st->inner); + /* h(inner || pad) */ + neoscrypt_hash_update_blake256(&st->inner, pad, BLOCK_SIZE); + + /* The pad re-initialisation for the outer loop */ + for(i = 0; i < (BLOCK_SIZE >> 2); i++) + P[i] ^= (0x36363636 ^ 0x5C5C5C5C); + + neoscrypt_hash_init_blake256(&st->outer); + /* h(outer || pad) */ + neoscrypt_hash_update_blake256(&st->outer, pad, BLOCK_SIZE); } -static void neoscrypt_hmac_update_blake256(blake256_hmac_state *st, const uint8_t *m, size_t mlen) { +static inline void neoscrypt_hmac_update_blake256(blake256_hmac_state *st, + const uchar *m, uint mlen) { /* h(inner || m...) */ neoscrypt_hash_update_blake256(&st->inner, m, mlen); } -static void neoscrypt_hmac_finish_blake256(blake256_hmac_state *st, hash_digest mac) { +static inline void neoscrypt_hmac_finish_blake256(blake256_hmac_state *st, + hash_digest mac) { /* h(inner || m) */ hash_digest innerhash; neoscrypt_hash_finish_blake256(&st->inner, innerhash); @@ -534,14 +526,15 @@ static void neoscrypt_hmac_finish_blake256(blake256_hmac_state *st, hash_digest /* PBKDF2 for BLAKE-256 */ -static void neoscrypt_pbkdf2_blake256(const uint8_t *password, size_t password_len, - const uint8_t *salt, size_t salt_len, uint64_t N, uint8_t *output, size_t output_len) { +static void neoscrypt_pbkdf2_blake256(const uchar *password, + uint password_len, const uchar *salt, uint salt_len, uint N, + uchar *output, uint output_len) { blake256_hmac_state hmac_pw, hmac_pw_salt, work; hash_digest ti, u; - uint8_t be[4]; - uint32_t i, j, k, blocks; + uchar be[4]; + uint i, j, k, blocks; - /* bytes must be <= (0xffffffff - (SCRYPT_HASH_DIGEST_SIZE - 1)), which they will always be under scrypt */ + /* bytes must be <= (0xffffffff - (DIGEST_SIZE - 1)), which they will always be under scrypt */ /* hmac(password, ...) */ neoscrypt_hmac_init_blake256(&hmac_pw, password, password_len); @@ -550,20 +543,20 @@ static void neoscrypt_pbkdf2_blake256(const uint8_t *password, size_t password_l hmac_pw_salt = hmac_pw; neoscrypt_hmac_update_blake256(&hmac_pw_salt, salt, salt_len); - blocks = ((uint32_t)output_len + (SCRYPT_HASH_DIGEST_SIZE - 1)) / SCRYPT_HASH_DIGEST_SIZE; + blocks = ((uint)output_len + (DIGEST_SIZE - 1)) / DIGEST_SIZE; for(i = 1; i <= blocks; i++) { /* U1 = hmac(password, salt || be(i)) */ U32TO8_BE(be, i); work = hmac_pw_salt; neoscrypt_hmac_update_blake256(&work, be, 4); neoscrypt_hmac_finish_blake256(&work, ti); - memcpy(u, ti, sizeof(u)); + neoscrypt_copy(u, ti, sizeof(u)); /* T[i] = U1 ^ U2 ^ U3... */ for(j = 0; j < N - 1; j++) { /* UX = hmac(password, U{X-1}) */ work = hmac_pw; - neoscrypt_hmac_update_blake256(&work, u, SCRYPT_HASH_DIGEST_SIZE); + neoscrypt_hmac_update_blake256(&work, u, DIGEST_SIZE); neoscrypt_hmac_finish_blake256(&work, u); /* T[i] ^= UX */ @@ -571,26 +564,22 @@ static void neoscrypt_pbkdf2_blake256(const uint8_t *password, size_t password_l ti[k] ^= u[k]; } - memcpy(output, ti, (output_len > SCRYPT_HASH_DIGEST_SIZE) ? SCRYPT_HASH_DIGEST_SIZE : output_len); - output += SCRYPT_HASH_DIGEST_SIZE; - output_len -= SCRYPT_HASH_DIGEST_SIZE; + neoscrypt_copy(output, ti, (output_len > DIGEST_SIZE) ? DIGEST_SIZE : output_len); + output += DIGEST_SIZE; + output_len -= DIGEST_SIZE; } } -#endif +#endif /* BLAKE256 */ /* NeoScrypt */ -#if defined(ASM) +#ifdef ASM -extern void neoscrypt_salsa(uint *X, uint rounds); -extern void neoscrypt_salsa_tangle(uint *X, uint count); -extern void neoscrypt_chacha(uint *X, uint rounds); - -extern void neoscrypt_blkcpy(void *dstp, const void *srcp, uint len); -extern void neoscrypt_blkswp(void *blkAp, void *blkBp, uint len); -extern void neoscrypt_blkxor(void *dstp, const void *srcp, uint len); +extern void neoscrypt_copy(void *dstp, const void *srcp, uint len); +extern void neoscrypt_erase(void *dstp, uint len); +extern void neoscrypt_xor(void *dstp, const void *srcp, uint len); #else @@ -662,15 +651,14 @@ static void neoscrypt_chacha(uint *X, uint rounds) { #undef quarter } - /* Fast 32-bit / 64-bit memcpy(); * len must be a multiple of 32 bytes */ static void neoscrypt_blkcpy(void *dstp, const void *srcp, uint len) { - ulong *dst = (ulong *) dstp; - ulong *src = (ulong *) srcp; + size_t *dst = (size_t *) dstp; + size_t *src = (size_t *) srcp; uint i; - for(i = 0; i < (len / sizeof(ulong)); i += 4) { + for(i = 0; i < (len / sizeof(size_t)); i += 4) { dst[i] = src[i]; dst[i + 1] = src[i + 1]; dst[i + 2] = src[i + 2]; @@ -681,12 +669,12 @@ static void neoscrypt_blkcpy(void *dstp, const void *srcp, uint len) { /* Fast 32-bit / 64-bit block swapper; * len must be a multiple of 32 bytes */ static void neoscrypt_blkswp(void *blkAp, void *blkBp, uint len) { - ulong *blkA = (ulong *) blkAp; - ulong *blkB = (ulong *) blkBp; - register ulong t0, t1, t2, t3; + size_t *blkA = (size_t *) blkAp; + size_t *blkB = (size_t *) blkBp; + register size_t t0, t1, t2, t3; uint i; - for(i = 0; i < (len / sizeof(ulong)); i += 4) { + for(i = 0; i < (len / sizeof(size_t)); i += 4) { t0 = blkA[i]; t1 = blkA[i + 1]; t2 = blkA[i + 2]; @@ -705,11 +693,11 @@ static void neoscrypt_blkswp(void *blkAp, void *blkBp, uint len) { /* Fast 32-bit / 64-bit block XOR engine; * len must be a multiple of 32 bytes */ static void neoscrypt_blkxor(void *dstp, const void *srcp, uint len) { - ulong *dst = (ulong *) dstp; - ulong *src = (ulong *) srcp; + size_t *dst = (size_t *) dstp; + size_t *src = (size_t *) srcp; uint i; - for(i = 0; i < (len / sizeof(ulong)); i += 4) { + for(i = 0; i < (len / sizeof(size_t)); i += 4) { dst[i] ^= src[i]; dst[i + 1] ^= src[i + 1]; dst[i + 2] ^= src[i + 2]; @@ -717,18 +705,16 @@ static void neoscrypt_blkxor(void *dstp, const void *srcp, uint len) { } } -#endif - /* 32-bit / 64-bit optimised memcpy() */ -static void neoscrypt_copy(void *dstp, const void *srcp, uint len) { - ulong *dst = (ulong *) dstp; - ulong *src = (ulong *) srcp; +void neoscrypt_copy(void *dstp, const void *srcp, uint len) { + size_t *dst = (size_t *) dstp; + size_t *src = (size_t *) srcp; uint i, tail; - for(i = 0; i < (len / sizeof(ulong)); i++) + for(i = 0; i < (len / sizeof(size_t)); i++) dst[i] = src[i]; - tail = len & (sizeof(ulong) - 1); + tail = len & (sizeof(size_t) - 1); if(tail) { uchar *dstb = (uchar *) dstp; uchar *srcb = (uchar *) srcp; @@ -739,15 +725,15 @@ static void neoscrypt_copy(void *dstp, const void *srcp, uint len) { } /* 32-bit / 64-bit optimised memory erase aka memset() to zero */ -static void neoscrypt_erase(void *dstp, uint len) { - const ulong null = 0; - ulong *dst = (ulong *) dstp; +void neoscrypt_erase(void *dstp, uint len) { + const size_t null = 0; + size_t *dst = (size_t *) dstp; uint i, tail; - for(i = 0; i < (len / sizeof(ulong)); i++) + for(i = 0; i < (len / sizeof(size_t)); i++) dst[i] = null; - tail = len & (sizeof(ulong) - 1); + tail = len & (sizeof(size_t) - 1); if(tail) { uchar *dstb = (uchar *) dstp; @@ -757,15 +743,15 @@ static void neoscrypt_erase(void *dstp, uint len) { } /* 32-bit / 64-bit optimised XOR engine */ -static void neoscrypt_xor(void *dstp, const void *srcp, uint len) { - ulong *dst = (ulong *) dstp; - ulong *src = (ulong *) srcp; +void neoscrypt_xor(void *dstp, const void *srcp, uint len) { + size_t *dst = (size_t *) dstp; + size_t *src = (size_t *) srcp; uint i, tail; - for(i = 0; i < (len / sizeof(ulong)); i++) + for(i = 0; i < (len / sizeof(size_t)); i++) dst[i] ^= src[i]; - tail = len & (sizeof(ulong) - 1); + tail = len & (sizeof(size_t) - 1); if(tail) { uchar *dstb = (uchar *) dstp; uchar *srcb = (uchar *) srcp; @@ -775,12 +761,10 @@ static void neoscrypt_xor(void *dstp, const void *srcp, uint len) { } } +#endif /* ASM */ -/* BLAKE2s */ -#define BLAKE2S_BLOCK_SIZE 64U -#define BLAKE2S_OUT_SIZE 32U -#define BLAKE2S_KEY_SIZE 32U +/* BLAKE2s */ /* Parameter block of 32 bytes */ typedef struct blake2s_param_t { @@ -796,13 +780,15 @@ typedef struct blake2s_param_t { uchar personal[8]; } blake2s_param; -/* State block of 180 bytes */ +/* State block of 256 bytes */ typedef struct blake2s_state_t { uint h[8]; uint t[2]; uint f[2]; - uchar buf[2 * BLAKE2S_BLOCK_SIZE]; + uchar buf[2 * BLOCK_SIZE]; uint buflen; + uint padding[3]; + uchar tempbuf[BLOCK_SIZE]; } blake2s_state; static const uint blake2s_IV[8] = { @@ -810,97 +796,1440 @@ static const uint blake2s_IV[8] = { 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 }; -static const uint8_t blake2s_sigma[10][16] = { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , - { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , - { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , - { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , - { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , - { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , - { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , - { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , - { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , - { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , -}; +#ifdef ASM -static void blake2s_compress(blake2s_state *S, const uint *buf) { - uint i; - uint m[16]; - uint v[16]; +extern void blake2s_compress(blake2s_state *S); - neoscrypt_copy(m, buf, 64); - neoscrypt_copy(v, S, 32); +#else - v[ 8] = blake2s_IV[0]; - v[ 9] = blake2s_IV[1]; +/* Buffer mixer (compressor) */ +static void blake2s_compress(blake2s_state *S) { + uint *v = (uint *) S->tempbuf; + uint *m = (uint *) S->buf; + register uint t0, t1, t2, t3; + + v[0] = S->h[0]; + v[1] = S->h[1]; + v[2] = S->h[2]; + v[3] = S->h[3]; + v[4] = S->h[4]; + v[5] = S->h[5]; + v[6] = S->h[6]; + v[7] = S->h[7]; + v[8] = blake2s_IV[0]; + v[9] = blake2s_IV[1]; v[10] = blake2s_IV[2]; v[11] = blake2s_IV[3]; v[12] = S->t[0] ^ blake2s_IV[4]; v[13] = S->t[1] ^ blake2s_IV[5]; v[14] = S->f[0] ^ blake2s_IV[6]; v[15] = S->f[1] ^ blake2s_IV[7]; -#define G(r,i,a,b,c,d) \ - do { \ - a = a + b + m[blake2s_sigma[r][2*i+0]]; \ - d = ROTR32(d ^ a, 16); \ - c = c + d; \ - b = ROTR32(b ^ c, 12); \ - a = a + b + m[blake2s_sigma[r][2*i+1]]; \ - d = ROTR32(d ^ a, 8); \ - c = c + d; \ - b = ROTR32(b ^ c, 7); \ - } while(0) -#define ROUND(r) \ - do { \ - G(r, 0, v[ 0], v[ 4], v[ 8], v[12]); \ - G(r, 1, v[ 1], v[ 5], v[ 9], v[13]); \ - G(r, 2, v[ 2], v[ 6], v[10], v[14]); \ - G(r, 3, v[ 3], v[ 7], v[11], v[15]); \ - G(r, 4, v[ 0], v[ 5], v[10], v[15]); \ - G(r, 5, v[ 1], v[ 6], v[11], v[12]); \ - G(r, 6, v[ 2], v[ 7], v[ 8], v[13]); \ - G(r, 7, v[ 3], v[ 4], v[ 9], v[14]); \ - } while(0) - ROUND(0); - ROUND(1); - ROUND(2); - ROUND(3); - ROUND(4); - ROUND(5); - ROUND(6); - ROUND(7); - ROUND(8); - ROUND(9); - - for(i = 0; i < 8; i++) - S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; -#undef G -#undef ROUND +/* Round 0 */ + t0 = v[0]; + t1 = v[4]; + t0 = t0 + t1 + m[0]; + t3 = v[12]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[1]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + t0 = v[1]; + t1 = v[5]; + t0 = t0 + t1 + m[2]; + t3 = v[13]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[3]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[2]; + t1 = v[6]; + t0 = t0 + t1 + m[4]; + t3 = v[14]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[5]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[3]; + t1 = v[7]; + t0 = t0 + t1 + m[6]; + t3 = v[15]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[7]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[0]; + t1 = v[5]; + t0 = t0 + t1 + m[8]; + t3 = v[15]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[9]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[1]; + t1 = v[6]; + t0 = t0 + t1 + m[10]; + t3 = v[12]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[11]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[2]; + t1 = v[7]; + t0 = t0 + t1 + m[12]; + t3 = v[13]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[13]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[3]; + t1 = v[4]; + t0 = t0 + t1 + m[14]; + t3 = v[14]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[15]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + +/* Round 1 */ + t0 = v[0]; + t1 = v[4]; + t0 = t0 + t1 + m[14]; + t3 = v[12]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[10]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + t0 = v[1]; + t1 = v[5]; + t0 = t0 + t1 + m[4]; + t3 = v[13]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[8]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[2]; + t1 = v[6]; + t0 = t0 + t1 + m[9]; + t3 = v[14]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[15]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[3]; + t1 = v[7]; + t0 = t0 + t1 + m[13]; + t3 = v[15]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[6]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[0]; + t1 = v[5]; + t0 = t0 + t1 + m[1]; + t3 = v[15]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[12]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[1]; + t1 = v[6]; + t0 = t0 + t1 + m[0]; + t3 = v[12]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[2]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[2]; + t1 = v[7]; + t0 = t0 + t1 + m[11]; + t3 = v[13]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[7]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[3]; + t1 = v[4]; + t0 = t0 + t1 + m[5]; + t3 = v[14]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[3]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + +/* Round 2 */ + t0 = v[0]; + t1 = v[4]; + t0 = t0 + t1 + m[11]; + t3 = v[12]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[8]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + t0 = v[1]; + t1 = v[5]; + t0 = t0 + t1 + m[12]; + t3 = v[13]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[0]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[2]; + t1 = v[6]; + t0 = t0 + t1 + m[5]; + t3 = v[14]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[2]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[3]; + t1 = v[7]; + t0 = t0 + t1 + m[15]; + t3 = v[15]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[13]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[0]; + t1 = v[5]; + t0 = t0 + t1 + m[10]; + t3 = v[15]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[14]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[1]; + t1 = v[6]; + t0 = t0 + t1 + m[3]; + t3 = v[12]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[6]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[2]; + t1 = v[7]; + t0 = t0 + t1 + m[7]; + t3 = v[13]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[1]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[3]; + t1 = v[4]; + t0 = t0 + t1 + m[9]; + t3 = v[14]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[4]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + +/* Round 3 */ + t0 = v[0]; + t1 = v[4]; + t0 = t0 + t1 + m[7]; + t3 = v[12]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[9]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + t0 = v[1]; + t1 = v[5]; + t0 = t0 + t1 + m[3]; + t3 = v[13]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[1]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[2]; + t1 = v[6]; + t0 = t0 + t1 + m[13]; + t3 = v[14]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[12]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[3]; + t1 = v[7]; + t0 = t0 + t1 + m[11]; + t3 = v[15]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[14]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[0]; + t1 = v[5]; + t0 = t0 + t1 + m[2]; + t3 = v[15]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[6]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[1]; + t1 = v[6]; + t0 = t0 + t1 + m[5]; + t3 = v[12]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[10]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[2]; + t1 = v[7]; + t0 = t0 + t1 + m[4]; + t3 = v[13]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[0]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[3]; + t1 = v[4]; + t0 = t0 + t1 + m[15]; + t3 = v[14]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[8]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + +/* Round 4 */ + t0 = v[0]; + t1 = v[4]; + t0 = t0 + t1 + m[9]; + t3 = v[12]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[0]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + t0 = v[1]; + t1 = v[5]; + t0 = t0 + t1 + m[5]; + t3 = v[13]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[7]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[2]; + t1 = v[6]; + t0 = t0 + t1 + m[2]; + t3 = v[14]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[4]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[3]; + t1 = v[7]; + t0 = t0 + t1 + m[10]; + t3 = v[15]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[15]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[0]; + t1 = v[5]; + t0 = t0 + t1 + m[14]; + t3 = v[15]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[1]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[1]; + t1 = v[6]; + t0 = t0 + t1 + m[11]; + t3 = v[12]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[12]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[2]; + t1 = v[7]; + t0 = t0 + t1 + m[6]; + t3 = v[13]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[8]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[3]; + t1 = v[4]; + t0 = t0 + t1 + m[3]; + t3 = v[14]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[13]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + +/* Round 5 */ + t0 = v[0]; + t1 = v[4]; + t0 = t0 + t1 + m[2]; + t3 = v[12]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[12]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + t0 = v[1]; + t1 = v[5]; + t0 = t0 + t1 + m[6]; + t3 = v[13]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[10]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[2]; + t1 = v[6]; + t0 = t0 + t1 + m[0]; + t3 = v[14]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[11]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[3]; + t1 = v[7]; + t0 = t0 + t1 + m[8]; + t3 = v[15]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[3]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[0]; + t1 = v[5]; + t0 = t0 + t1 + m[4]; + t3 = v[15]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[13]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[1]; + t1 = v[6]; + t0 = t0 + t1 + m[7]; + t3 = v[12]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[5]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[2]; + t1 = v[7]; + t0 = t0 + t1 + m[15]; + t3 = v[13]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[14]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[3]; + t1 = v[4]; + t0 = t0 + t1 + m[1]; + t3 = v[14]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[9]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + +/* Round 6 */ + t0 = v[0]; + t1 = v[4]; + t0 = t0 + t1 + m[12]; + t3 = v[12]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[5]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + t0 = v[1]; + t1 = v[5]; + t0 = t0 + t1 + m[1]; + t3 = v[13]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[15]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[2]; + t1 = v[6]; + t0 = t0 + t1 + m[14]; + t3 = v[14]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[13]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[3]; + t1 = v[7]; + t0 = t0 + t1 + m[4]; + t3 = v[15]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[10]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[0]; + t1 = v[5]; + t0 = t0 + t1 + m[0]; + t3 = v[15]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[7]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[1]; + t1 = v[6]; + t0 = t0 + t1 + m[6]; + t3 = v[12]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[3]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[2]; + t1 = v[7]; + t0 = t0 + t1 + m[9]; + t3 = v[13]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[2]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[3]; + t1 = v[4]; + t0 = t0 + t1 + m[8]; + t3 = v[14]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[11]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + +/* Round 7 */ + t0 = v[0]; + t1 = v[4]; + t0 = t0 + t1 + m[13]; + t3 = v[12]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[11]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + t0 = v[1]; + t1 = v[5]; + t0 = t0 + t1 + m[7]; + t3 = v[13]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[14]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[2]; + t1 = v[6]; + t0 = t0 + t1 + m[12]; + t3 = v[14]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[1]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[3]; + t1 = v[7]; + t0 = t0 + t1 + m[3]; + t3 = v[15]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[9]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[0]; + t1 = v[5]; + t0 = t0 + t1 + m[5]; + t3 = v[15]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[0]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[1]; + t1 = v[6]; + t0 = t0 + t1 + m[15]; + t3 = v[12]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[4]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[2]; + t1 = v[7]; + t0 = t0 + t1 + m[8]; + t3 = v[13]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[6]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[3]; + t1 = v[4]; + t0 = t0 + t1 + m[2]; + t3 = v[14]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[10]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + +/* Round 8 */ + t0 = v[0]; + t1 = v[4]; + t0 = t0 + t1 + m[6]; + t3 = v[12]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[15]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + t0 = v[1]; + t1 = v[5]; + t0 = t0 + t1 + m[14]; + t3 = v[13]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[9]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[2]; + t1 = v[6]; + t0 = t0 + t1 + m[11]; + t3 = v[14]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[3]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[3]; + t1 = v[7]; + t0 = t0 + t1 + m[0]; + t3 = v[15]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[8]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[0]; + t1 = v[5]; + t0 = t0 + t1 + m[12]; + t3 = v[15]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[2]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[1]; + t1 = v[6]; + t0 = t0 + t1 + m[13]; + t3 = v[12]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[7]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[2]; + t1 = v[7]; + t0 = t0 + t1 + m[1]; + t3 = v[13]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[4]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[3]; + t1 = v[4]; + t0 = t0 + t1 + m[10]; + t3 = v[14]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[5]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + +/* Round 9 */ + t0 = v[0]; + t1 = v[4]; + t0 = t0 + t1 + m[10]; + t3 = v[12]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[2]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + t0 = v[1]; + t1 = v[5]; + t0 = t0 + t1 + m[8]; + t3 = v[13]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[4]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[2]; + t1 = v[6]; + t0 = t0 + t1 + m[7]; + t3 = v[14]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[6]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[3]; + t1 = v[7]; + t0 = t0 + t1 + m[1]; + t3 = v[15]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[5]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[0]; + t1 = v[5]; + t0 = t0 + t1 + m[15]; + t3 = v[15]; + t2 = v[10]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[11]; + v[0] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[15] = t3; + t2 = t2 + t3; + v[10] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[5] = t1; + + t0 = v[1]; + t1 = v[6]; + t0 = t0 + t1 + m[9]; + t3 = v[12]; + t2 = v[11]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[14]; + v[1] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[12] = t3; + t2 = t2 + t3; + v[11] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[6] = t1; + + t0 = v[2]; + t1 = v[7]; + t0 = t0 + t1 + m[3]; + t3 = v[13]; + t2 = v[8]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[12]; + v[2] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[13] = t3; + t2 = t2 + t3; + v[8] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[7] = t1; + + t0 = v[3]; + t1 = v[4]; + t0 = t0 + t1 + m[13]; + t3 = v[14]; + t2 = v[9]; + t3 = ROTR32(t3 ^ t0, 16); + t2 = t2 + t3; + t1 = ROTR32(t1 ^ t2, 12); + t0 = t0 + t1 + m[0]; + v[3] = t0; + t3 = ROTR32(t3 ^ t0, 8); + v[14] = t3; + t2 = t2 + t3; + v[9] = t2; + t1 = ROTR32(t1 ^ t2, 7); + v[4] = t1; + + S->h[0] ^= v[0] ^ v[8]; + S->h[1] ^= v[1] ^ v[9]; + S->h[2] ^= v[2] ^ v[10]; + S->h[3] ^= v[3] ^ v[11]; + S->h[4] ^= v[4] ^ v[12]; + S->h[5] ^= v[5] ^ v[13]; + S->h[6] ^= v[6] ^ v[14]; + S->h[7] ^= v[7] ^ v[15]; } -static void blake2s_update(blake2s_state *S, const uchar *input, uint input_size) { +#endif /* ASM */ + +static void blake2s_update(blake2s_state *S, const uchar *input, + uint input_size) { uint left, fill; while(input_size > 0) { left = S->buflen; - fill = 2 * BLAKE2S_BLOCK_SIZE - left; + fill = 2 * BLOCK_SIZE - left; if(input_size > fill) { /* Buffer fill */ neoscrypt_copy(S->buf + left, input, fill); S->buflen += fill; /* Counter increment */ - S->t[0] += BLAKE2S_BLOCK_SIZE; + S->t[0] += BLOCK_SIZE; /* Compress */ - blake2s_compress(S, (uint *) S->buf); + blake2s_compress(S); /* Shift buffer left */ - neoscrypt_copy(S->buf, S->buf + BLAKE2S_BLOCK_SIZE, BLAKE2S_BLOCK_SIZE); - S->buflen -= BLAKE2S_BLOCK_SIZE; + neoscrypt_copy(S->buf, S->buf + BLOCK_SIZE, BLOCK_SIZE); + S->buflen -= BLOCK_SIZE; input += fill; input_size -= fill; } else { neoscrypt_copy(S->buf + left, input, input_size); - S->buflen += input_size; + S->buflen += input_size; /* Do not compress */ input += input_size; input_size = 0; @@ -908,9 +2237,9 @@ static void blake2s_update(blake2s_state *S, const uchar *input, uint input_size } } -static void neoscrypt_blake2s(const void *input, const uint input_size, const void *key, const uchar key_size, - void *output, const uchar output_size) { - uchar block[BLAKE2S_BLOCK_SIZE]; +void neoscrypt_blake2s(const void *input, const uint input_size, + const void *key, const uchar key_size, void *output, const uchar output_size) { + uchar block[BLOCK_SIZE]; blake2s_param P[1]; blake2s_state S[1]; @@ -921,52 +2250,60 @@ static void neoscrypt_blake2s(const void *input, const uint input_size, const vo P->fanout = 1; P->depth = 1; - neoscrypt_erase(S, 180); + neoscrypt_erase(S, 256); neoscrypt_copy(S, blake2s_IV, 32); neoscrypt_xor(S, P, 32); - neoscrypt_erase(block, BLAKE2S_BLOCK_SIZE); + neoscrypt_erase(block, BLOCK_SIZE); neoscrypt_copy(block, key, key_size); - blake2s_update(S, (uchar *) block, BLAKE2S_BLOCK_SIZE); + blake2s_update(S, (uchar *) block, BLOCK_SIZE); /* Update */ blake2s_update(S, (uchar *) input, input_size); /* Finish */ - if(S->buflen > BLAKE2S_BLOCK_SIZE) { - S->t[0] += BLAKE2S_BLOCK_SIZE; - blake2s_compress(S, (uint *) S->buf); - S->buflen -= BLAKE2S_BLOCK_SIZE; - neoscrypt_copy(S->buf, S->buf + BLAKE2S_BLOCK_SIZE, S->buflen); + if(S->buflen > BLOCK_SIZE) { + S->t[0] += BLOCK_SIZE; + blake2s_compress(S); + S->buflen -= BLOCK_SIZE; + neoscrypt_copy(S->buf, S->buf + BLOCK_SIZE, S->buflen); } S->t[0] += S->buflen; S->f[0] = ~0U; - neoscrypt_erase(S->buf + S->buflen, 2 * BLAKE2S_BLOCK_SIZE - S->buflen); - blake2s_compress(S, (uint *) S->buf); + neoscrypt_erase(S->buf + S->buflen, 2 * BLOCK_SIZE - S->buflen); + blake2s_compress(S); /* Write back */ neoscrypt_copy(output, S, output_size); } +#ifndef OPT #define FASTKDF_BUFFER_SIZE 256U -#define NEOSCRYPT_FASTKDF_STACK_SIZE 2 * FASTKDF_BUFFER_SIZE + BLAKE2S_BLOCK_SIZE + BLAKE2S_KEY_SIZE + BLAKE2S_OUT_SIZE + 0x40 - /* FastKDF, a fast buffered key derivation function: * FASTKDF_BUFFER_SIZE must be a power of 2; * password_len, salt_len and output_len should not exceed FASTKDF_BUFFER_SIZE; * prf_output_size must be <= prf_key_size; */ -static void neoscrypt_fastkdf(const uchar *password, uint password_len, const uchar *salt, uint salt_len, - uint N, uchar *output, uint output_len) { - const uint stack_align = 0x40, kdf_buf_size = FASTKDF_BUFFER_SIZE, - prf_input_size = BLAKE2S_BLOCK_SIZE, prf_key_size = BLAKE2S_KEY_SIZE, prf_output_size = BLAKE2S_OUT_SIZE; +void neoscrypt_fastkdf(const uchar *password, uint password_len, + const uchar *salt, uint salt_len, uint N, uchar *output, uint output_len) { + const size_t stack_align = 0x40; + const uint kdf_buf_size = FASTKDF_BUFFER_SIZE, + prf_input_size = 64, prf_key_size = 32, prf_output_size = 32; uint bufptr, a, b, i, j; uchar *A, *B, *prf_input, *prf_key, *prf_output; /* Align and set up the buffers in stack */ - uchar stack[NEOSCRYPT_FASTKDF_STACK_SIZE]; - A = &stack[stack_align & ~(stack_align - 1)]; + // No VLAs with VC ;-( +#ifndef _MSC_VER + uchar stack[2 * kdf_buf_size + prf_input_size + prf_key_size + + prf_output_size + stack_align]; +#else + uchar* stack = alloca(2 * kdf_buf_size + prf_input_size + prf_key_size + + prf_output_size + stack_align); +#endif + + A = (uchar *) (((size_t)stack & ~(stack_align - 1)) + stack_align); B = &A[kdf_buf_size + prf_input_size]; prf_output = &A[2 * kdf_buf_size + prf_input_size + prf_key_size]; @@ -1004,7 +2341,8 @@ static void neoscrypt_fastkdf(const uchar *password, uint password_len, const uc prf_key = &B[bufptr]; /* PRF */ - neoscrypt_blake2s(prf_input, prf_input_size, prf_key, prf_key_size, prf_output, prf_output_size); + neoscrypt_blake2s(prf_input, prf_input_size, prf_key, prf_key_size, + prf_output, prf_output_size); /* Calculate the next buffer pointer */ for(j = 0, bufptr = 0; j < prf_output_size; j++) @@ -1016,17 +2354,18 @@ static void neoscrypt_fastkdf(const uchar *password, uint password_len, const uc /* Head modified, tail updated */ if(bufptr < prf_key_size) - neoscrypt_copy(&B[kdf_buf_size + bufptr], &B[bufptr], MIN(prf_output_size, prf_key_size - bufptr)); - + neoscrypt_copy(&B[kdf_buf_size + bufptr], &B[bufptr], + MIN(prf_output_size, prf_key_size - bufptr)); /* Tail modified, head updated */ - if((kdf_buf_size - bufptr) < prf_output_size) - neoscrypt_copy(&B[0], &B[kdf_buf_size], prf_output_size - (kdf_buf_size - bufptr)); + else if((kdf_buf_size - bufptr) < prf_output_size) + neoscrypt_copy(&B[0], &B[kdf_buf_size], + prf_output_size - (kdf_buf_size - bufptr)); } /* Modify and copy into the output buffer */ if(output_len > kdf_buf_size) - output_len = kdf_buf_size; + output_len = kdf_buf_size; a = kdf_buf_size - bufptr; if(a >= output_len) { @@ -1041,6 +2380,111 @@ static void neoscrypt_fastkdf(const uchar *password, uint password_len, const uc } +#else + +#ifdef ASM + +extern void neoscrypt_fastkdf_opt(const uchar *password, const uchar *salt, + uchar *output, uint mode); + +#else + +/* Initialisation vector with a parameter block XOR'ed in */ +static const uint blake2s_IV_P_XOR[8] = { + 0x6B08C647, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 +}; + +/* Performance optimised FastKDF with BLAKE2s integrated */ +void neoscrypt_fastkdf_opt(const uchar *password, const uchar *salt, + uchar *output, uint mode) { + const size_t stack_align = 0x40; + uint bufptr, output_len, i, j; + uchar *A, *B; + uint *S; + + /* Align and set up the buffers in stack */ + uchar stack[864 + stack_align]; + A = (uchar *) (((size_t)stack & ~(stack_align - 1)) + stack_align); + B = &A[320]; + S = (uint *) &A[608]; + + neoscrypt_copy(&A[0], &password[0], 80); + neoscrypt_copy(&A[80], &password[0], 80); + neoscrypt_copy(&A[160], &password[0], 80); + neoscrypt_copy(&A[240], &password[0], 16); + neoscrypt_copy(&A[256], &password[0], 64); + + if(!mode) { + output_len = 256; + neoscrypt_copy(&B[0], &salt[0], 80); + neoscrypt_copy(&B[80], &salt[0], 80); + neoscrypt_copy(&B[160], &salt[0], 80); + neoscrypt_copy(&B[240], &salt[0], 16); + neoscrypt_copy(&B[256], &salt[0], 32); + } else { + output_len = 32; + neoscrypt_copy(&B[0], &salt[0], 256); + neoscrypt_copy(&B[256], &salt[0], 32); + } + + for(i = 0, bufptr = 0; i < 32; i++) { + + /* BLAKE2s: initialise */ + neoscrypt_copy(&S[0], blake2s_IV_P_XOR, 32); + neoscrypt_erase(&S[8], 16); + + /* BLAKE2s: update key */ + neoscrypt_copy(&S[12], &B[bufptr], 32); + neoscrypt_erase(&S[20], 32); + + /* BLAKE2s: compress IV using key */ + S[8] = 64; + blake2s_compress((blake2s_state *) S); + + /* BLAKE2s: update input */ + neoscrypt_copy(&S[12], &A[bufptr], 64); + + /* BLAKE2s: compress again using input */ + S[8] = 128; + S[10] = ~0U; + blake2s_compress((blake2s_state *) S); + + for(j = 0, bufptr = 0; j < 8; j++) { + bufptr += S[j]; + bufptr += (S[j] >> 8); + bufptr += (S[j] >> 16); + bufptr += (S[j] >> 24); + } + bufptr &= 0xFF; + + neoscrypt_xor(&B[bufptr], &S[0], 32); + + if(bufptr < 32) + neoscrypt_copy(&B[256 + bufptr], &B[bufptr], 32 - bufptr); + else if(bufptr > 224) + neoscrypt_copy(&B[0], &B[256], bufptr - 224); + + } + + i = 256 - bufptr; + if(i >= output_len) { + neoscrypt_xor(&B[bufptr], &A[0], output_len); + neoscrypt_copy(&output[0], &B[bufptr], output_len); + } else { + neoscrypt_xor(&B[bufptr], &A[0], i); + neoscrypt_xor(&B[0], &A[i], output_len - i); + neoscrypt_copy(&output[0], &B[bufptr], i); + neoscrypt_copy(&output[i], &B[0], output_len - i); + } +} + +#endif /* ASM */ + +#endif /* !(OPT) */ + + +#ifndef ASM /* Configurable optimised block mixer */ static void neoscrypt_blkmix(uint *X, uint *Y, uint r, uint mixmode) { @@ -1058,60 +2502,62 @@ static void neoscrypt_blkmix(uint *X, uint *Y, uint r, uint mixmode) { Xc" = Yb; Xd" = Yd; */ if(r == 1) { - neoscrypt_blkxor(&X[0], &X[16], SCRYPT_BLOCK_SIZE); - if(mixer) - neoscrypt_chacha(&X[0], rounds); - else - neoscrypt_salsa(&X[0], rounds); - neoscrypt_blkxor(&X[16], &X[0], SCRYPT_BLOCK_SIZE); - if(mixer) - neoscrypt_chacha(&X[16], rounds); - else - neoscrypt_salsa(&X[16], rounds); + if(mixer) { + neoscrypt_blkxor(&X[0], &X[16], BLOCK_SIZE); + neoscrypt_chacha(&X[0], rounds); + neoscrypt_blkxor(&X[16], &X[0], BLOCK_SIZE); + neoscrypt_chacha(&X[16], rounds); + } else { + neoscrypt_blkxor(&X[0], &X[16], BLOCK_SIZE); + neoscrypt_salsa(&X[0], rounds); + neoscrypt_blkxor(&X[16], &X[0], BLOCK_SIZE); + neoscrypt_salsa(&X[16], rounds); + } return; } if(r == 2) { - neoscrypt_blkxor(&X[0], &X[48], SCRYPT_BLOCK_SIZE); - if(mixer) - neoscrypt_chacha(&X[0], rounds); - else - neoscrypt_salsa(&X[0], rounds); - neoscrypt_blkxor(&X[16], &X[0], SCRYPT_BLOCK_SIZE); - if(mixer) - neoscrypt_chacha(&X[16], rounds); - else - neoscrypt_salsa(&X[16], rounds); - neoscrypt_blkxor(&X[32], &X[16], SCRYPT_BLOCK_SIZE); - if(mixer) - neoscrypt_chacha(&X[32], rounds); - else - neoscrypt_salsa(&X[32], rounds); - neoscrypt_blkxor(&X[48], &X[32], SCRYPT_BLOCK_SIZE); - if(mixer) - neoscrypt_chacha(&X[48], rounds); - else - neoscrypt_salsa(&X[48], rounds); - neoscrypt_blkswp(&X[16], &X[32], SCRYPT_BLOCK_SIZE); + if(mixer) { + neoscrypt_blkxor(&X[0], &X[48], BLOCK_SIZE); + neoscrypt_chacha(&X[0], rounds); + neoscrypt_blkxor(&X[16], &X[0], BLOCK_SIZE); + neoscrypt_chacha(&X[16], rounds); + neoscrypt_blkxor(&X[32], &X[16], BLOCK_SIZE); + neoscrypt_chacha(&X[32], rounds); + neoscrypt_blkxor(&X[48], &X[32], BLOCK_SIZE); + neoscrypt_chacha(&X[48], rounds); + neoscrypt_blkswp(&X[16], &X[32], BLOCK_SIZE); + } else { + neoscrypt_blkxor(&X[0], &X[48], BLOCK_SIZE); + neoscrypt_salsa(&X[0], rounds); + neoscrypt_blkxor(&X[16], &X[0], BLOCK_SIZE); + neoscrypt_salsa(&X[16], rounds); + neoscrypt_blkxor(&X[32], &X[16], BLOCK_SIZE); + neoscrypt_salsa(&X[32], rounds); + neoscrypt_blkxor(&X[48], &X[32], BLOCK_SIZE); + neoscrypt_salsa(&X[48], rounds); + neoscrypt_blkswp(&X[16], &X[32], BLOCK_SIZE); + } return; } /* Reference code for any reasonable r */ for(i = 0; i < 2 * r; i++) { - if(i) neoscrypt_blkxor(&X[16 * i], &X[16 * (i - 1)], SCRYPT_BLOCK_SIZE); - else neoscrypt_blkxor(&X[0], &X[16 * (2 * r - 1)], SCRYPT_BLOCK_SIZE); + if(i) neoscrypt_blkxor(&X[16 * i], &X[16 * (i - 1)], BLOCK_SIZE); + else neoscrypt_blkxor(&X[0], &X[16 * (2 * r - 1)], BLOCK_SIZE); if(mixer) neoscrypt_chacha(&X[16 * i], rounds); else neoscrypt_salsa(&X[16 * i], rounds); - neoscrypt_blkcpy(&Y[16 * i], &X[16 * i], SCRYPT_BLOCK_SIZE); + neoscrypt_blkcpy(&Y[16 * i], &X[16 * i], BLOCK_SIZE); } for(i = 0; i < r; i++) - neoscrypt_blkcpy(&X[16 * i], &Y[16 * 2 * i], SCRYPT_BLOCK_SIZE); + neoscrypt_blkcpy(&X[16 * i], &Y[16 * 2 * i], BLOCK_SIZE); for(i = 0; i < r; i++) - neoscrypt_blkcpy(&X[16 * (i + r)], &Y[16 * (2 * i + 1)], SCRYPT_BLOCK_SIZE); + neoscrypt_blkcpy(&X[16 * (i + r)], &Y[16 * (2 * i + 1)], BLOCK_SIZE); } + /* NeoScrypt core engine: * p = 1, salt = password; * Basic customisation (required): @@ -1143,11 +2589,9 @@ static void neoscrypt_blkmix(uint *X, uint *Y, uint r, uint mixmode) { * ..... * 11110 = N of 2147483648; * profile bits 30 to 13 are reserved */ -void neoscrypt(const char *input, char *uoutput, int profile) { - const unsigned char *password = input; - const unsigned char *output = uoutput; - - uint N = 128, r = 2, dblmix = 1, mixmode = 0x14, stack_align = 0x40; +void neoscrypt(const uchar *password, uchar *output, uint profile) { + const size_t stack_align = 0x40; + uint N = 128, r = 2, dblmix = 1, mixmode = 0x14; uint kdf, i, j; uint *X, *Y, *Z, *V; @@ -1163,20 +2607,19 @@ void neoscrypt(const char *input, char *uoutput, int profile) { r = (1 << ((profile >> 5) & 0x7)); } - const int stack_size = (N + 3) * r * 2 * SCRYPT_BLOCK_SIZE + stack_align; - -#if !defined(_MSC_VER) - uchar stack[stack_size]; + // No VLAs with VC ;-( +#ifndef _MSC_VER + uchar stack[(N + 3) * r * 2 * BLOCK_SIZE + stack_align]; #else - uchar *stack = _alloca(stack_size); + uchar* stack = alloca((N + 3) * r * 2 * BLOCK_SIZE + stack_align); #endif - /* X = r * 2 * SCRYPT_BLOCK_SIZE */ - X = (uint *) &stack[stack_align & ~(stack_align - 1)]; + /* X = r * 2 * BLOCK_SIZE */ + X = (uint *) (((size_t)stack & ~(stack_align - 1)) + stack_align); /* Z is a copy of X for ChaCha */ Z = &X[32 * r]; /* Y is an X sized temporal space */ Y = &X[64 * r]; - /* V = N * r * 2 * SCRYPT_BLOCK_SIZE */ + /* V = N * r * 2 * BLOCK_SIZE */ V = &X[96 * r]; /* X = KDF(password, salt) */ @@ -1186,55 +2629,58 @@ void neoscrypt(const char *input, char *uoutput, int profile) { default: case(0x0): - neoscrypt_fastkdf(password, 80, password, 80, 32, (uchar *) X, r * 2 * SCRYPT_BLOCK_SIZE); +#ifdef OPT + neoscrypt_fastkdf_opt(password, password, (uchar *) X, 0); +#else + neoscrypt_fastkdf(password, 80, password, 80, 32, + (uchar *) X, r * 2 * BLOCK_SIZE); +#endif break; -#if (NEOSCRYPT_SHA256) +#ifdef SHA256 case(0x1): - neoscrypt_pbkdf2_sha256(password, 80, password, 80, 1, (uchar *) X, r * 2 * SCRYPT_BLOCK_SIZE); + neoscrypt_pbkdf2_sha256(password, 80, password, 80, 1, + (uchar *) X, r * 2 * BLOCK_SIZE); break; #endif -#if (NEOSCRYPT_BLAKE256) +#ifdef BLAKE256 case(0x2): - neoscrypt_pbkdf2_blake256(password, 80, password, 80, 1, (uchar *) X, r * 2 * SCRYPT_BLOCK_SIZE); + neoscrypt_pbkdf2_blake256(password, 80, password, 80, 1, + (uchar *) X, r * 2 * BLOCK_SIZE); break; #endif } - /* Process ChaCha 1st, Salsa 2nd and XOR them into PBKDF2; otherwise Salsa only */ + /* Process ChaCha 1st, Salsa 2nd and XOR them into FastKDF; otherwise Salsa only */ if(dblmix) { /* blkcpy(Z, X) */ - neoscrypt_blkcpy(&Z[0], &X[0], r * 2 * SCRYPT_BLOCK_SIZE); + neoscrypt_blkcpy(&Z[0], &X[0], r * 2 * BLOCK_SIZE); /* Z = SMix(Z) */ for(i = 0; i < N; i++) { /* blkcpy(V, Z) */ - neoscrypt_blkcpy(&V[i * (32 * r)], &Z[0], r * 2 * SCRYPT_BLOCK_SIZE); + neoscrypt_blkcpy(&V[i * (32 * r)], &Z[0], r * 2 * BLOCK_SIZE); /* blkmix(Z, Y) */ neoscrypt_blkmix(&Z[0], &Y[0], r, (mixmode | 0x0100)); } + for(i = 0; i < N; i++) { /* integerify(Z) mod N */ j = (32 * r) * (Z[16 * (2 * r - 1)] & (N - 1)); /* blkxor(Z, V) */ - neoscrypt_blkxor(&Z[0], &V[j], r * 2 * SCRYPT_BLOCK_SIZE); + neoscrypt_blkxor(&Z[0], &V[j], r * 2 * BLOCK_SIZE); /* blkmix(Z, Y) */ neoscrypt_blkmix(&Z[0], &Y[0], r, (mixmode | 0x0100)); } } -#if (ASM) - /* Must be called before and after SSE2 Salsa */ - neoscrypt_salsa_tangle(&X[0], r * 2); -#endif - /* X = SMix(X) */ for(i = 0; i < N; i++) { /* blkcpy(V, X) */ - neoscrypt_blkcpy(&V[i * (32 * r)], &X[0], r * 2 * SCRYPT_BLOCK_SIZE); + neoscrypt_blkcpy(&V[i * (32 * r)], &X[0], r * 2 * BLOCK_SIZE); /* blkmix(X, Y) */ neoscrypt_blkmix(&X[0], &Y[0], r, mixmode); } @@ -1242,36 +2688,39 @@ void neoscrypt(const char *input, char *uoutput, int profile) { /* integerify(X) mod N */ j = (32 * r) * (X[16 * (2 * r - 1)] & (N - 1)); /* blkxor(X, V) */ - neoscrypt_blkxor(&X[0], &V[j], r * 2 * SCRYPT_BLOCK_SIZE); + neoscrypt_blkxor(&X[0], &V[j], r * 2 * BLOCK_SIZE); /* blkmix(X, Y) */ neoscrypt_blkmix(&X[0], &Y[0], r, mixmode); } -#if (ASM) - neoscrypt_salsa_tangle(&X[0], r * 2); -#endif - if(dblmix) /* blkxor(X, Z) */ - neoscrypt_blkxor(&X[0], &Z[0], r * 2 * SCRYPT_BLOCK_SIZE); + neoscrypt_blkxor(&X[0], &Z[0], r * 2 * BLOCK_SIZE); /* output = KDF(password, X) */ switch(kdf) { default: case(0x0): - neoscrypt_fastkdf(password, 80, (uchar *) X, r * 2 * SCRYPT_BLOCK_SIZE, 32, output, 32); +#ifdef OPT + neoscrypt_fastkdf_opt(password, (uchar *) X, output, 1); +#else + neoscrypt_fastkdf(password, 80, (uchar *) X, + r * 2 * BLOCK_SIZE, 32, output, 32); +#endif break; -#if (NEOSCRYPT_SHA256) +#ifdef SHA256 case(0x1): - neoscrypt_pbkdf2_sha256(password, 80, (uchar *) X, r * 2 * SCRYPT_BLOCK_SIZE, 1, output, 32); + neoscrypt_pbkdf2_sha256(password, 80, (uchar *) X, + r * 2 * BLOCK_SIZE, 1, output, 32); break; #endif -#if (NEOSCRYPT_BLAKE256) +#ifdef BLAKE256 case(0x2): - neoscrypt_pbkdf2_blake256(password, 80, (uchar *) X, r * 2 * SCRYPT_BLOCK_SIZE, 1, output, 32); + neoscrypt_pbkdf2_blake256(password, 80, (uchar *) X, + r * 2 * BLOCK_SIZE, 1, output, 32); break; #endif @@ -1279,119 +2728,552 @@ void neoscrypt(const char *input, char *uoutput, int profile) { } +#endif /* !(ASM) */ + + +#if defined(ASM) && defined(MINER_4WAY) + +extern void neoscrypt_xor_salsa_4way(uint *X, uint *X0, uint *Y, uint double_rounds); +extern void neoscrypt_xor_chacha_4way(uint *Z, uint *Z0, uint *Y, uint double_rounds); + +#if (1) + +extern void neoscrypt_blkcpy(void *dstp, const void *srcp, uint len); +extern void neoscrypt_blkswp(void *blkAp, void *blkBp, uint len); +extern void neoscrypt_blkxor(void *dstp, const void *srcp, uint len); + +extern void neoscrypt_pack_4way(void *dstp, const void *srcp, uint len); +extern void neoscrypt_unpack_4way(void *dstp, const void *srcp, uint len); +extern void neoscrypt_xor_4way(void *dstp, const void *srcAp, + const void *srcBp, const void *srcCp, const void *srcDp, uint len); + +#else + +/* The following code is for reference only */ + +static void neoscrypt_blkcpy(void *dstp, const void *srcp, uint len) { + size_t *dst = (size_t *) dstp; + size_t *src = (size_t *) srcp; + uint i; + + for(i = 0; i < (len / sizeof(size_t)); i += 4) { + dst[i] = src[i]; + dst[i + 1] = src[i + 1]; + dst[i + 2] = src[i + 2]; + dst[i + 3] = src[i + 3]; + } +} + +static void neoscrypt_blkswp(void *blkAp, void *blkBp, uint len) { + size_t *blkA = (size_t *) blkAp; + size_t *blkB = (size_t *) blkBp; + register size_t t0, t1, t2, t3; + uint i; + + for(i = 0; i < (len / sizeof(size_t)); i += 4) { + t0 = blkA[i]; + t1 = blkA[i + 1]; + t2 = blkA[i + 2]; + t3 = blkA[i + 3]; + blkA[i] = blkB[i]; + blkA[i + 1] = blkB[i + 1]; + blkA[i + 2] = blkB[i + 2]; + blkA[i + 3] = blkB[i + 3]; + blkB[i] = t0; + blkB[i + 1] = t1; + blkB[i + 2] = t2; + blkB[i + 3] = t3; + } +} + +static void neoscrypt_blkxor(void *dstp, const void *srcp, uint len) { + size_t *dst = (size_t *) dstp; + size_t *src = (size_t *) srcp; + uint i; + + for(i = 0; i < (len / sizeof(size_t)); i += 4) { + dst[i] ^= src[i]; + dst[i + 1] ^= src[i + 1]; + dst[i + 2] ^= src[i + 2]; + dst[i + 3] ^= src[i + 3]; + } +} + + +static void neoscrypt_pack_4way(void *dstp, const void *srcp, uint len) { + uint *dst = (uint *) dstp; + uint *src = (uint *) srcp; + uint i, j; + + len >>= 4; + + for(i = 0, j = 0; j < len; i += 4, j++) { + dst[i] = src[j]; + dst[i + 1] = src[j + len]; + dst[i + 2] = src[j + 2 * len]; + dst[i + 3] = src[j + 3 * len]; + } +} -#if (NEOSCRYPT_TEST) +static void neoscrypt_unpack_4way(void *dstp, const void *srcp, uint len) { + uint *dst = (uint *) dstp; + uint *src = (uint *) srcp; + uint i, j; -#include + len >>= 4; -int main() { - uint prf_input_len = 64, prf_key_len = 32, prf_output_len = 32; - uint kdf_input_len = 80, kdf_output_len = 256, N = 32; - uint neoscrypt_output_len = 32; - uchar input[kdf_input_len], output[kdf_output_len]; + for(i = 0, j = 0; j < len; i += 4, j++) { + dst[j] = src[i]; + dst[j + len] = src[i + 1]; + dst[j + 2 * len] = src[i + 2]; + dst[j + 3 * len] = src[i + 3]; + } +} + +static void neoscrypt_xor_4way(void *dstp, const void *srcAp, + const void *srcBp, const void *srcCp, const void *srcDp, uint len) { + uint *dst = (uint *) dstp; + uint *srcA = (uint *) srcAp; + uint *srcB = (uint *) srcBp; + uint *srcC = (uint *) srcCp; + uint *srcD = (uint *) srcDp; uint i; - bool fail; - for(i = 0; i < kdf_input_len; i++) { - input[i] = i; + for(i = 0; i < (len >> 2); i += 4) { + dst[i] ^= srcA[i]; + dst[i + 1] ^= srcB[i + 1]; + dst[i + 2] ^= srcC[i + 2]; + dst[i + 3] ^= srcD[i + 3]; } +} - neoscrypt_blake2s(input, prf_input_len, input, prf_key_len, output, prf_output_len); +#endif - uchar blake2s_ref[32] = { - 0x89, 0x75, 0xB0, 0x57, 0x7F, 0xD3, 0x55, 0x66, - 0xD7, 0x50, 0xB3, 0x62, 0xB0, 0x89, 0x7A, 0x26, - 0xC3, 0x99, 0x13, 0x6D, 0xF0, 0x7B, 0xAB, 0xAB, - 0xBD, 0xE6, 0x20, 0x3F, 0xF2, 0x95, 0x4E, 0xD4 }; - for(i = 0, fail = 0; i < prf_output_len; i++) { - if(output[i] != blake2s_ref[i]) { - fail = 1; - break; - } +/* 4-way NeoScrypt(128, 2, 1) with Salsa20/20 and ChaCha20/20 */ +void neoscrypt_4way(const uchar *password, uchar *output, uchar *scratchpad) { + const uint N = 128, r = 2, double_rounds = 10; + uint *X, *Z, *V, *Y, *P; + uint i, j0, j1, j2, j3, k; + + /* 2 * BLOCK_SIZE compacted to 128 below */; + + /* Scratchpad size is 4 * ((N + 3) * r * 128 + 80) bytes */ + + X = (uint *) &scratchpad[0]; + Z = &X[4 * 32 * r]; + V = &X[4 * 64 * r]; + /* Y is a temporary work space */ + Y = &X[4 * (N + 2) * 32 * r]; + /* P is a set of passwords 80 bytes each */ + P = &X[4 * (N + 3) * 32 * r]; + + /* Load the password and increment nonces */ + for(k = 0; k < 4; k++) { + neoscrypt_copy(&P[k * 20], password, 80); + P[(k + 1) * 20 - 1] += k; } - if(fail) { - printf("BLAKE2s integrity test failed!\n"); - return(1); - } else { - printf("BLAKE2s integrity test passed.\n"); + neoscrypt_fastkdf_4way((uchar *) &P[0], (uchar *) &P[0], (uchar *) &Y[0], + (uchar *) &scratchpad[0], 0); + + neoscrypt_pack_4way(&X[0], &Y[0], 4 * r * 128); + + neoscrypt_blkcpy(&Z[0], &X[0], 4 * r * 128); + + for(i = 0; i < N; i++) { + neoscrypt_blkcpy(&V[i * r * 128], &Z[0], 4 * r * 128); + neoscrypt_xor_chacha_4way(&Z[0], &Z[192], &Y[0], double_rounds); + neoscrypt_xor_chacha_4way(&Z[64], &Z[0], &Y[0], double_rounds); + neoscrypt_xor_chacha_4way(&Z[128], &Z[64], &Y[0], double_rounds); + neoscrypt_xor_chacha_4way(&Z[192], &Z[128], &Y[0], double_rounds); + neoscrypt_blkswp(&Z[64], &Z[128], r * 128); } - neoscrypt_fastkdf(input, kdf_input_len, input, kdf_input_len, N, output, kdf_output_len); - - uchar fastkdf_ref[256] = { - 0xCC, 0xBC, 0x19, 0x71, 0xEC, 0x44, 0xE3, 0x17, - 0xB3, 0xC9, 0xDE, 0x16, 0x76, 0x02, 0x60, 0xB8, - 0xE2, 0xD4, 0x79, 0xB6, 0x88, 0xCA, 0xB5, 0x4A, - 0xCF, 0x6E, 0x0E, 0x9A, 0xAE, 0x48, 0x78, 0x12, - 0xA1, 0x95, 0x1E, 0xE1, 0xD1, 0x0A, 0xC2, 0x94, - 0x1F, 0x0A, 0x39, 0x73, 0xFE, 0xA4, 0xCD, 0x87, - 0x4B, 0x38, 0x54, 0x72, 0xB5, 0x53, 0xC3, 0xEA, - 0xC1, 0x26, 0x8D, 0xA7, 0xFF, 0x3F, 0xC1, 0x79, - 0xA6, 0xFF, 0x96, 0x54, 0x29, 0x05, 0xC0, 0x22, - 0x90, 0xDB, 0x53, 0x87, 0x2D, 0x29, 0x00, 0xA6, - 0x14, 0x16, 0x38, 0x63, 0xDA, 0xBC, 0x0E, 0x99, - 0x68, 0xB3, 0x98, 0x92, 0x42, 0xE3, 0xF6, 0xB4, - 0x19, 0xE3, 0xE3, 0xF6, 0x8E, 0x67, 0x47, 0x7B, - 0xB6, 0xFB, 0xEA, 0xCE, 0x6D, 0x0F, 0xAF, 0xF6, - 0x19, 0x43, 0x8D, 0xF7, 0x3E, 0xB5, 0xFB, 0xA3, - 0x64, 0x5E, 0xD2, 0x72, 0x80, 0x6B, 0x39, 0x93, - 0xB7, 0x80, 0x04, 0xCB, 0xF5, 0xC2, 0x61, 0xB1, - 0x90, 0x4E, 0x2B, 0x02, 0x57, 0x53, 0x77, 0x16, - 0x6A, 0x52, 0xBD, 0xD1, 0x62, 0xEC, 0xA1, 0xCB, - 0x89, 0x03, 0x29, 0xA2, 0x02, 0x5C, 0x9A, 0x62, - 0x99, 0x44, 0x54, 0xEA, 0x44, 0x91, 0x27, 0x3A, - 0x50, 0x82, 0x62, 0x03, 0x99, 0xB3, 0xFA, 0xF7, - 0xD4, 0x13, 0x47, 0x61, 0xFB, 0x0A, 0xE7, 0x81, - 0x61, 0x57, 0x58, 0x4C, 0x69, 0x4E, 0x67, 0x0A, - 0xC1, 0x21, 0xA7, 0xD2, 0xF6, 0x6D, 0x2F, 0x10, - 0x01, 0xFB, 0xA5, 0x47, 0x2C, 0xE5, 0x15, 0xD7, - 0x6A, 0xEF, 0xC9, 0xE2, 0xC2, 0x88, 0xA2, 0x3B, - 0x6C, 0x8D, 0xBB, 0x26, 0xE7, 0xC4, 0x15, 0xEC, - 0x5E, 0x5D, 0x74, 0x79, 0xBD, 0x81, 0x35, 0xA1, - 0x42, 0x27, 0xEB, 0x57, 0xCF, 0xF6, 0x2E, 0x51, - 0x90, 0xFD, 0xD9, 0xE4, 0x53, 0x6E, 0x12, 0xA1, - 0x99, 0x79, 0x4D, 0x29, 0x6F, 0x5B, 0x4D, 0x9A }; - - for(i = 0, fail = 0; i < kdf_output_len; i++) { - if(output[i] != fastkdf_ref[i]) { - fail = 1; - break; - } + for(i = 0; i < N; i++) { + j0 = (4 * r * 32) * (Z[64 * (2 * r - 1)] & (N - 1)); + j1 = (4 * r * 32) * (Z[1 + (64 * (2 * r - 1))] & (N - 1)); + j2 = (4 * r * 32) * (Z[2 + (64 * (2 * r - 1))] & (N - 1)); + j3 = (4 * r * 32) * (Z[3 + (64 * (2 * r - 1))] & (N - 1)); + neoscrypt_xor_4way(&Z[0], + &V[j0], &V[j1], &V[j2], &V[j3], 4 * r * 128); + neoscrypt_xor_chacha_4way(&Z[0], &Z[192], &Y[0], double_rounds); + neoscrypt_xor_chacha_4way(&Z[64], &Z[0], &Y[0], double_rounds); + neoscrypt_xor_chacha_4way(&Z[128], &Z[64], &Y[0], double_rounds); + neoscrypt_xor_chacha_4way(&Z[192], &Z[128], &Y[0], double_rounds); + neoscrypt_blkswp(&Z[64], &Z[128], 256); } - if(fail) { - printf("FastKDF integrity test failed!\n"); - return(1); - } else { - printf("FastKDF integrity test passed.\n"); + for(i = 0; i < N; i++) { + neoscrypt_blkcpy(&V[i * r * 128], &X[0], 4 * r * 128); + neoscrypt_xor_salsa_4way(&X[0], &X[192], &Y[0], double_rounds); + neoscrypt_xor_salsa_4way(&X[64], &X[0], &Y[0], double_rounds); + neoscrypt_xor_salsa_4way(&X[128], &X[64], &Y[0], double_rounds); + neoscrypt_xor_salsa_4way(&X[192], &X[128], &Y[0], double_rounds); + neoscrypt_blkswp(&X[64], &X[128], r * 128); } - neoscrypt(input, output, 0x80000620); + for(i = 0; i < N; i++) { + j0 = (4 * r * 32) * (X[64 * (2 * r - 1)] & (N - 1)); + j1 = (4 * r * 32) * (X[1 + (64 * (2 * r - 1))] & (N - 1)); + j2 = (4 * r * 32) * (X[2 + (64 * (2 * r - 1))] & (N - 1)); + j3 = (4 * r * 32) * (X[3 + (64 * (2 * r - 1))] & (N - 1)); + neoscrypt_xor_4way(&X[0], + &V[j0], &V[j1], &V[j2], &V[j3], 4 * r * 128); + neoscrypt_xor_salsa_4way(&X[0], &X[192], &Y[0], double_rounds); + neoscrypt_xor_salsa_4way(&X[64], &X[0], &Y[0], double_rounds); + neoscrypt_xor_salsa_4way(&X[128], &X[64], &Y[0], double_rounds); + neoscrypt_xor_salsa_4way(&X[192], &X[128], &Y[0], double_rounds); + neoscrypt_blkswp(&X[64], &X[128], r * 128); + } - uchar neoscrypt_ref[32] = { - 0x72, 0x58, 0x96, 0x1A, 0xFB, 0x33, 0xFD, 0x12, - 0xD0, 0x0C, 0xAC, 0xB8, 0xD6, 0x3F, 0x4F, 0x4F, - 0x52, 0xBB, 0x69, 0x17, 0x04, 0x38, 0x65, 0xDD, - 0x24, 0xA0, 0x8F, 0x57, 0x88, 0x53, 0x12, 0x2D }; + neoscrypt_blkxor(&X[0], &Z[0], 4 * r * 128); - for(i = 0, fail = 0; i < neoscrypt_output_len; i++) { - if(output[i] != neoscrypt_ref[i]) { - fail = 1; - break; + neoscrypt_unpack_4way(&Y[0], &X[0], 4 * r * 128); + + neoscrypt_fastkdf_4way((uchar *) &P[0], (uchar *) &Y[0], (uchar *) &output[0], + (uchar *) &scratchpad[0], 1); +} + +#ifdef SHA256 +/* 4-way Scrypt(1024, 1, 1) with Salsa20/8 */ +void scrypt_4way(const uchar *password, uchar *output, uchar *scratchpad) { + const uint N = 1024, r = 1, double_rounds = 4; + uint *X, *V, *Y, *P; + uint i, j0, j1, j2, j3, k; + + /* Scratchpad size is 4 * ((N + 2) * r * 128 + 80) bytes */ + + X = (uint *) &scratchpad[0]; + V = &X[4 * 32 * r]; + Y = &X[4 * (N + 1) * 32 * r]; + P = &X[4 * (N + 2) * 32 * r]; + + for(k = 0; k < 4; k++) { + neoscrypt_copy(&P[k * 20], password, 80); + P[(k + 1) * 20 - 1] += k; + } + + for(k = 0; k < 4; k++) + neoscrypt_pbkdf2_sha256((uchar *) &P[k * 20], 80, + (uchar *) &P[k * 20], 80, 1, + (uchar *) &Y[k * r * 32], r * 128); + + neoscrypt_pack_4way(&X[0], &Y[0], 4 * r * 128); + + for(i = 0; i < N; i++) { + neoscrypt_blkcpy(&V[i * r * 128], &X[0], 4 * r * 128); + neoscrypt_xor_salsa_4way(&X[0], &X[64], &Y[0], double_rounds); + neoscrypt_xor_salsa_4way(&X[64], &X[0], &Y[0], double_rounds); + } + + for(i = 0; i < N; i++) { + j0 = (4 * r * 32) * (X[64 * (2 * r - 1)] & (N - 1)); + j1 = (4 * r * 32) * (X[1 + (64 * (2 * r - 1))] & (N - 1)); + j2 = (4 * r * 32) * (X[2 + (64 * (2 * r - 1))] & (N - 1)); + j3 = (4 * r * 32) * (X[3 + (64 * (2 * r - 1))] & (N - 1)); + neoscrypt_xor_4way(&X[0], + &V[j0], &V[j1], &V[j2], &V[j3], 4 * r * 128); + neoscrypt_xor_salsa_4way(&X[0], &X[64], &Y[0], double_rounds); + neoscrypt_xor_salsa_4way(&X[64], &X[0], &Y[0], double_rounds); + } + + neoscrypt_unpack_4way(&Y[0], &X[0], 4 * r * 128); + + for(k = 0; k < 4; k++) + neoscrypt_pbkdf2_sha256((uchar *) &P[k * 20], 80, + (uchar *) &Y[k * r * 32], r * 128, 1, + (uchar *) &output[k * 32], 32); +} +#endif /* SHA256 */ + + +extern void blake2s_compress_4way(void *T); + +/* 4-way initialisation vector with a parameter block XOR'ed in */ +static const uint blake2s_IV_P_XOR_4way[32] = { + 0x6B08C647, 0x6B08C647, 0x6B08C647, 0x6B08C647, + 0xBB67AE85, 0xBB67AE85, 0xBB67AE85, 0xBB67AE85, + 0x3C6EF372, 0x3C6EF372, 0x3C6EF372, 0x3C6EF372, + 0xA54FF53A, 0xA54FF53A, 0xA54FF53A, 0xA54FF53A, + 0x510E527F, 0x510E527F, 0x510E527F, 0x510E527F, + 0x9B05688C, 0x9B05688C, 0x9B05688C, 0x9B05688C, + 0x1F83D9AB, 0x1F83D9AB, 0x1F83D9AB, 0x1F83D9AB, + 0x5BE0CD19, 0x5BE0CD19, 0x5BE0CD19, 0x5BE0CD19 +}; + +/* 4-way BLAKE2s implementation */ +void neoscrypt_blake2s_4way(const uchar *input, const uchar *key, uchar *output) { + const size_t stack_align = 0x40; + uint *T; + + /* Align and set up the buffer in stack */ + uchar stack[704 + stack_align]; + T = (uint *) (((size_t)stack & ~(stack_align - 1)) + stack_align); + + /* Initialise */ + neoscrypt_copy(&T[0], blake2s_IV_P_XOR_4way, 128); + neoscrypt_erase(&T[32], 64); + + /* Update keys */ + neoscrypt_pack_4way(&T[48], &key[0], 128); + neoscrypt_erase(&T[80], 128); + + /* Compress IVs using keys */ + T[32] = 64; + T[33] = 64; + T[34] = 64; + T[35] = 64; + blake2s_compress_4way(&T[0]); + + /* Update inputs */ + neoscrypt_pack_4way(&T[48], &input[0], 256); + + /* Compress using inputs */ + T[32] = 128; + T[33] = 128; + T[34] = 128; + T[35] = 128; + T[40] = ~0U; + T[41] = ~0U; + T[42] = ~0U; + T[43] = ~0U; + blake2s_compress_4way(&T[0]); + + neoscrypt_unpack_4way(&output[0], &T[0], 128); +} + + +/* 4-way FastKDF with BLAKE2s integrated */ +void neoscrypt_fastkdf_4way(const uchar *password, const uchar *salt, + uchar *output, uchar *scratchpad, uint mode) { + uint bufptr_a = 0, bufptr_b = 0, bufptr_c = 0, bufptr_d = 0; + uint output_len, i, j; + uint *T; + uchar *Aa, *Ab, *Ac, *Ad; + uchar *Ba, *Bb, *Bc, *Bd; + + T = (uint *) &scratchpad[0]; + Aa = (uchar *) &T[176]; + Ab = (uchar *) &T[256]; + Ac = (uchar *) &T[336]; + Ad = (uchar *) &T[416]; + Ba = (uchar *) &T[496]; + Bb = (uchar *) &T[568]; + Bc = (uchar *) &T[640]; + Bd = (uchar *) &T[712]; + + neoscrypt_copy(&Aa[0], &password[0], 80); + neoscrypt_copy(&Aa[80], &password[0], 80); + neoscrypt_copy(&Aa[160], &password[0], 80); + neoscrypt_copy(&Aa[240], &password[0], 16); + neoscrypt_copy(&Aa[256], &password[0], 64); + neoscrypt_copy(&Ab[0], &password[80], 80); + neoscrypt_copy(&Ab[80], &password[80], 80); + neoscrypt_copy(&Ab[160], &password[80], 80); + neoscrypt_copy(&Ab[240], &password[80], 16); + neoscrypt_copy(&Ab[256], &password[80], 64); + neoscrypt_copy(&Ac[0], &password[160], 80); + neoscrypt_copy(&Ac[80], &password[160], 80); + neoscrypt_copy(&Ac[160], &password[160], 80); + neoscrypt_copy(&Ac[240], &password[160], 16); + neoscrypt_copy(&Ac[256], &password[160], 64); + neoscrypt_copy(&Ad[0], &password[240], 80); + neoscrypt_copy(&Ad[80], &password[240], 80); + neoscrypt_copy(&Ad[160], &password[240], 80); + neoscrypt_copy(&Ad[240], &password[240], 16); + neoscrypt_copy(&Ad[256], &password[240], 64); + + if(!mode) { + output_len = 256; + neoscrypt_copy(&Ba[0], &salt[0], 80); + neoscrypt_copy(&Ba[80], &salt[0], 80); + neoscrypt_copy(&Ba[160], &salt[0], 80); + neoscrypt_copy(&Ba[240], &salt[0], 16); + neoscrypt_copy(&Ba[256], &salt[0], 32); + neoscrypt_copy(&Bb[0], &salt[80], 80); + neoscrypt_copy(&Bb[80], &salt[80], 80); + neoscrypt_copy(&Bb[160], &salt[80], 80); + neoscrypt_copy(&Bb[240], &salt[80], 16); + neoscrypt_copy(&Bb[256], &salt[80], 32); + neoscrypt_copy(&Bc[0], &salt[160], 80); + neoscrypt_copy(&Bc[80], &salt[160], 80); + neoscrypt_copy(&Bc[160], &salt[160], 80); + neoscrypt_copy(&Bc[240], &salt[160], 16); + neoscrypt_copy(&Bc[256], &salt[160], 32); + neoscrypt_copy(&Bd[0], &salt[240], 80); + neoscrypt_copy(&Bd[80], &salt[240], 80); + neoscrypt_copy(&Bd[160], &salt[240], 80); + neoscrypt_copy(&Bd[240], &salt[240], 16); + neoscrypt_copy(&Bd[256], &salt[240], 32); + } else { + output_len = 32; + neoscrypt_copy(&Ba[0], &salt[0], 256); + neoscrypt_copy(&Ba[256], &salt[0], 32); + neoscrypt_copy(&Bb[0], &salt[256], 256); + neoscrypt_copy(&Bb[256], &salt[256], 32); + neoscrypt_copy(&Bc[0], &salt[512], 256); + neoscrypt_copy(&Bc[256], &salt[512], 32); + neoscrypt_copy(&Bd[0], &salt[768], 256); + neoscrypt_copy(&Bd[256], &salt[768], 32); + } + + for(i = 0; i < 32; i++) { + + /* BLAKE2s: initialise */ + neoscrypt_copy(&T[0], blake2s_IV_P_XOR_4way, 128); + neoscrypt_erase(&T[32], 64); + + /* BLAKE2s: update keys */ + for(j = 0; j < 32; j += 8) { + T[j + 48] = *((uint *) &Ba[bufptr_a + j]); + T[j + 49] = *((uint *) &Bb[bufptr_b + j]); + T[j + 50] = *((uint *) &Bc[bufptr_c + j]); + T[j + 51] = *((uint *) &Bd[bufptr_d + j]); + T[j + 52] = *((uint *) &Ba[bufptr_a + j + 4]); + T[j + 53] = *((uint *) &Bb[bufptr_b + j + 4]); + T[j + 54] = *((uint *) &Bc[bufptr_c + j + 4]); + T[j + 55] = *((uint *) &Bd[bufptr_d + j + 4]); + } + neoscrypt_erase(&T[80], 128); + + /* BLAKE2s: compress IVs using keys */ + T[32] = 64; + T[33] = 64; + T[34] = 64; + T[35] = 64; + blake2s_compress_4way(&T[0]); + + /* BLAKE2s: update inputs */ + for(j = 0; j < 64; j += 8) { + T[j + 48] = *((uint *) &Aa[bufptr_a + j]); + T[j + 49] = *((uint *) &Ab[bufptr_b + j]); + T[j + 50] = *((uint *) &Ac[bufptr_c + j]); + T[j + 51] = *((uint *) &Ad[bufptr_d + j]); + T[j + 52] = *((uint *) &Aa[bufptr_a + j + 4]); + T[j + 53] = *((uint *) &Ab[bufptr_b + j + 4]); + T[j + 54] = *((uint *) &Ac[bufptr_c + j + 4]); + T[j + 55] = *((uint *) &Ad[bufptr_d + j + 4]); + } + + /* BLAKE2s: compress using inputs */ + T[32] = 128; + T[33] = 128; + T[34] = 128; + T[35] = 128; + T[40] = ~0U; + T[41] = ~0U; + T[42] = ~0U; + T[43] = ~0U; + blake2s_compress_4way(&T[0]); + + bufptr_a = 0; + bufptr_b = 0; + bufptr_c = 0; + bufptr_d = 0; + for(j = 0; j < 32; j += 4) { + bufptr_a += T[j]; + bufptr_a += (T[j] >> 8); + bufptr_a += (T[j] >> 16); + bufptr_a += (T[j] >> 24); + bufptr_b += T[j + 1]; + bufptr_b += (T[j + 1] >> 8); + bufptr_b += (T[j + 1] >> 16); + bufptr_b += (T[j + 1] >> 24); + bufptr_c += T[j + 2]; + bufptr_c += (T[j + 2] >> 8); + bufptr_c += (T[j + 2] >> 16); + bufptr_c += (T[j + 2] >> 24); + bufptr_d += T[j + 3]; + bufptr_d += (T[j + 3] >> 8); + bufptr_d += (T[j + 3] >> 16); + bufptr_d += (T[j + 3] >> 24); + } + bufptr_a &= 0xFF; + bufptr_b &= 0xFF; + bufptr_c &= 0xFF; + bufptr_d &= 0xFF; + + for(j = 0; j < 32; j += 8) { + *((uint *) &Ba[bufptr_a + j]) ^= T[j]; + *((uint *) &Bb[bufptr_b + j]) ^= T[j + 1]; + *((uint *) &Bc[bufptr_c + j]) ^= T[j + 2]; + *((uint *) &Bd[bufptr_d + j]) ^= T[j + 3]; + *((uint *) &Ba[bufptr_a + j + 4]) ^= T[j + 4]; + *((uint *) &Bb[bufptr_b + j + 4]) ^= T[j + 5]; + *((uint *) &Bc[bufptr_c + j + 4]) ^= T[j + 6]; + *((uint *) &Bd[bufptr_d + j + 4]) ^= T[j + 7]; } + + if(bufptr_a < 32) + neoscrypt_copy(&Ba[256 + bufptr_a], &Ba[bufptr_a], 32 - bufptr_a); + else if(bufptr_a > 224) + neoscrypt_copy(&Ba[0], &Ba[256], bufptr_a - 224); + if(bufptr_b < 32) + neoscrypt_copy(&Bb[256 + bufptr_b], &Bb[bufptr_b], 32 - bufptr_b); + else if(bufptr_b > 224) + neoscrypt_copy(&Bb[0], &Bb[256], bufptr_b - 224); + if(bufptr_c < 32) + neoscrypt_copy(&Bc[256 + bufptr_c], &Bc[bufptr_c], 32 - bufptr_c); + else if(bufptr_c > 224) + neoscrypt_copy(&Bc[0], &Bc[256], bufptr_c - 224); + if(bufptr_d < 32) + neoscrypt_copy(&Bd[256 + bufptr_d], &Bd[bufptr_d], 32 - bufptr_d); + else if(bufptr_d > 224) + neoscrypt_copy(&Bd[0], &Bd[256], bufptr_d - 224); + } - if(fail) { - printf("NeoScrypt integrity test failed!\n"); - return(1); + i = 256 - bufptr_a; + if(i >= output_len) { + neoscrypt_xor(&Ba[bufptr_a], &Aa[0], output_len); + neoscrypt_copy(&output[0], &Ba[bufptr_a], output_len); + } else { + neoscrypt_xor(&Ba[bufptr_a], &Aa[0], i); + neoscrypt_xor(&Ba[0], &Aa[i], output_len - i); + neoscrypt_copy(&output[0], &Ba[bufptr_a], i); + neoscrypt_copy(&output[i], &Ba[0], output_len - i); + } + i = 256 - bufptr_b; + if(i >= output_len) { + neoscrypt_xor(&Bb[bufptr_b], &Ab[0], output_len); + neoscrypt_copy(&output[output_len], &Bb[bufptr_b], output_len); + } else { + neoscrypt_xor(&Bb[bufptr_b], &Ab[0], i); + neoscrypt_xor(&Bb[0], &Ab[i], output_len - i); + neoscrypt_copy(&output[output_len], &Bb[bufptr_b], i); + neoscrypt_copy(&output[output_len + i], &Bb[0], output_len - i); + } + i = 256 - bufptr_c; + if(i >= output_len) { + neoscrypt_xor(&Bc[bufptr_c], &Ac[0], output_len); + neoscrypt_copy(&output[2 * output_len], &Bc[bufptr_c], output_len); + } else { + neoscrypt_xor(&Bc[bufptr_c], &Ac[0], i); + neoscrypt_xor(&Bc[0], &Ac[i], output_len - i); + neoscrypt_copy(&output[2 * output_len], &Bc[bufptr_c], i); + neoscrypt_copy(&output[2 * output_len + i], &Bc[0], output_len - i); + } + i = 256 - bufptr_d; + if(i >= output_len) { + neoscrypt_xor(&Bd[bufptr_d], &Ad[0], output_len); + neoscrypt_copy(&output[3 * output_len], &Bd[bufptr_d], output_len); } else { - printf("NeoScrypt integrity test passed.\n"); + neoscrypt_xor(&Bd[bufptr_d], &Ad[0], i); + neoscrypt_xor(&Bd[0], &Ad[i], output_len - i); + neoscrypt_copy(&output[3 * output_len], &Bd[bufptr_d], i); + neoscrypt_copy(&output[3 * output_len + i], &Bd[0], output_len - i); } - return(0); } -#endif +#endif /* (ASM) && (MINER_4WAY) */ + +#ifndef ASM +uint cpu_vec_exts() { + + /* No assembly, no extensions */ + return(0); +} +#endif diff --git a/src/Native/libmultihash/neoscrypt.h b/src/Native/libmultihash/neoscrypt.h index cfbcfc7e2..f385b4368 100644 --- a/src/Native/libmultihash/neoscrypt.h +++ b/src/Native/libmultihash/neoscrypt.h @@ -1,30 +1,72 @@ -#ifdef __cplusplus +#if (__cplusplus) extern "C" { #endif -void neoscrypt(const char *input, char *output, int profile); -#ifdef __cplusplus + +void neoscrypt(const unsigned char *password, unsigned char *output, + unsigned int profile); + +void neoscrypt_blake2s(const void *input, const unsigned int input_size, + const void *key, const unsigned char key_size, + void *output, const unsigned char output_size); + +void neoscrypt_copy(void *dstp, const void *srcp, unsigned int len); +void neoscrypt_erase(void *dstp, unsigned int len); +void neoscrypt_xor(void *dstp, const void *srcp, unsigned int len); + +#if defined(ASM) && defined(MINER_4WAY) +void neoscrypt_4way(const unsigned char *password, unsigned char *output, + unsigned char *scratchpad); + +#ifdef SHA256 +void scrypt_4way(const unsigned char *password, unsigned char *output, + unsigned char *scratchpad); +#endif + +void neoscrypt_blake2s_4way(const unsigned char *input, + const unsigned char *key, unsigned char *output); + +void neoscrypt_fastkdf_4way(const unsigned char *password, + const unsigned char *salt, unsigned char *output, unsigned char *scratchpad, + const unsigned int mode); +#endif + +unsigned int cpu_vec_exts(void); + +#if (__cplusplus) } #else -#define SCRYPT_BLOCK_SIZE 64 -#define SCRYPT_HASH_BLOCK_SIZE 64 -#define SCRYPT_HASH_DIGEST_SIZE 32 -typedef uint8_t hash_digest[SCRYPT_HASH_DIGEST_SIZE]; +typedef unsigned long long ullong; +typedef signed long long llong; +typedef unsigned int uint; +typedef unsigned char uchar; + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? a : b) +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? a : b) +#endif + +#define BLOCK_SIZE 64 +#define DIGEST_SIZE 32 + +typedef uchar hash_digest[DIGEST_SIZE]; #define ROTL32(a,b) (((a) << (b)) | ((a) >> (32 - b))) #define ROTR32(a,b) (((a) >> (b)) | ((a) << (32 - b))) #define U8TO32_BE(p) \ - (((uint32_t)((p)[0]) << 24) | ((uint32_t)((p)[1]) << 16) | \ - ((uint32_t)((p)[2]) << 8) | ((uint32_t)((p)[3]))) + (((uint)((p)[0]) << 24) | ((uint)((p)[1]) << 16) | \ + ((uint)((p)[2]) << 8) | ((uint)((p)[3]))) #define U32TO8_BE(p, v) \ - (p)[0] = (uint8_t)((v) >> 24); (p)[1] = (uint8_t)((v) >> 16); \ - (p)[2] = (uint8_t)((v) >> 8); (p)[3] = (uint8_t)((v) ); + (p)[0] = (uchar)((v) >> 24); (p)[1] = (uchar)((v) >> 16); \ + (p)[2] = (uchar)((v) >> 8); (p)[3] = (uchar)((v) ); #define U64TO8_BE(p, v) \ - U32TO8_BE((p), (uint32_t)((v) >> 32)); \ - U32TO8_BE((p) + 4, (uint32_t)((v) )); + U32TO8_BE((p), (uint)((v) >> 32)); \ + U32TO8_BE((p) + 4, (uint)((v) )); #endif - diff --git a/src/Native/libmultihash/sha3/hamsi_helper.c b/src/Native/libmultihash/sha3/hamsi_helper.c index cdf2fc9fe..807085295 100644 --- a/src/Native/libmultihash/sha3/hamsi_helper.c +++ b/src/Native/libmultihash/sha3/hamsi_helper.c @@ -10,7 +10,7 @@ * ==========================(LICENSE BEGIN)============================ * * Copyright (c) 2007-2010 Projet RNRT SAPHIR - * + * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -18,10 +18,10 @@ * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. diff --git a/src/Native/libmultihash/sha3/haval_helper.c b/src/Native/libmultihash/sha3/haval_helper.c new file mode 100644 index 000000000..c402fc699 --- /dev/null +++ b/src/Native/libmultihash/sha3/haval_helper.c @@ -0,0 +1,195 @@ +/* $Id: haval_helper.c 218 2010-06-08 17:06:34Z tp $ */ +/* + * Helper code, included (three times !) by HAVAL implementation. + * + * TODO: try to merge this with md_helper.c. + * + * ==========================(LICENSE BEGIN)============================ + * + * Copyright (c) 2007-2010 Projet RNRT SAPHIR + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * ===========================(LICENSE END)============================= + * + * @author Thomas Pornin + */ + +#undef SPH_XCAT +#define SPH_XCAT(a, b) SPH_XCAT_(a, b) +#undef SPH_XCAT_ +#define SPH_XCAT_(a, b) a ## b + +static void +#ifdef SPH_UPTR +SPH_XCAT(SPH_XCAT(haval, PASSES), _short) +#else +SPH_XCAT(haval, PASSES) +#endif +(sph_haval_context *sc, const void *data, size_t len) +{ + unsigned current; + +#if SPH_64 + current = (unsigned)sc->count & 127U; +#else + current = (unsigned)sc->count_low & 127U; +#endif + while (len > 0) { + unsigned clen; +#if !SPH_64 + sph_u32 clow, clow2; +#endif + + clen = 128U - current; + if (clen > len) + clen = len; + memcpy(sc->buf + current, data, clen); + data = (const unsigned char *)data + clen; + current += clen; + len -= clen; + if (current == 128U) { + DSTATE; + IN_PREPARE(sc->buf); + + RSTATE; + SPH_XCAT(CORE, PASSES)(INW); + WSTATE; + current = 0; + } +#if SPH_64 + sc->count += clen; +#else + clow = sc->count_low; + clow2 = SPH_T32(clow + clen); + sc->count_low = clow2; + if (clow2 < clow) + sc->count_high ++; +#endif + } +} + +#ifdef SPH_UPTR +static void +SPH_XCAT(haval, PASSES)(sph_haval_context *sc, const void *data, size_t len) +{ + unsigned current; + size_t orig_len; +#if !SPH_64 + sph_u32 clow, clow2; +#endif + DSTATE; + + if (len < 256U) { + SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, len); + return; + } +#if SPH_64 + current = (unsigned)sc->count & 127U; +#else + current = (unsigned)sc->count_low & 127U; +#endif + if (current > 0) { + unsigned clen; + + clen = 128U - current; + SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, clen); + data = (const unsigned char *)data + clen; + len -= clen; + } +#if !SPH_UNALIGNED + if (((SPH_UPTR)data & 3U) != 0) { + SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, len); + return; + } +#endif + orig_len = len; + RSTATE; + while (len >= 128U) { + IN_PREPARE(data); + + SPH_XCAT(CORE, PASSES)(INW); + data = (const unsigned char *)data + 128U; + len -= 128U; + } + WSTATE; + if (len > 0) + memcpy(sc->buf, data, len); +#if SPH_64 + sc->count += (sph_u64)orig_len; +#else + clow = sc->count_low; + clow2 = SPH_T32(clow + orig_len); + sc->count_low = clow2; + if (clow2 < clow) + sc->count_high ++; + orig_len >>= 12; + orig_len >>= 10; + orig_len >>= 10; + sc->count_high += orig_len; +#endif +} +#endif + +static void +SPH_XCAT(SPH_XCAT(haval, PASSES), _close)(sph_haval_context *sc, + unsigned ub, unsigned n, void *dst) +{ + unsigned current; + DSTATE; + +#if SPH_64 + current = (unsigned)sc->count & 127U; +#else + current = (unsigned)sc->count_low & 127U; +#endif + sc->buf[current ++] = (0x01 << n) | ((ub & 0xFF) >> (8 - n)); + RSTATE; + if (current > 118U) { + memset(sc->buf + current, 0, 128U - current); + + do { + IN_PREPARE(sc->buf); + + SPH_XCAT(CORE, PASSES)(INW); + } while (0); + current = 0; + } + memset(sc->buf + current, 0, 118U - current); + sc->buf[118] = 0x01 | (PASSES << 3); + sc->buf[119] = sc->olen << 3; +#if SPH_64 + sph_enc64le_aligned(sc->buf + 120, SPH_T64(sc->count << 3)); +#else + sph_enc32le_aligned(sc->buf + 120, SPH_T32(sc->count_low << 3)); + sph_enc32le_aligned(sc->buf + 124, + SPH_T32((sc->count_high << 3) | (sc->count_low >> 29))); +#endif + do { + IN_PREPARE(sc->buf); + + SPH_XCAT(CORE, PASSES)(INW); + } while (0); + + WSTATE; + haval_out(sc, dst); + haval_init(sc, sc->olen, sc->passes); +} + diff --git a/src/Native/libmultihash/sha3/sph_haval.c b/src/Native/libmultihash/sha3/sph_haval.c new file mode 100644 index 000000000..90922b638 --- /dev/null +++ b/src/Native/libmultihash/sha3/sph_haval.c @@ -0,0 +1,975 @@ +/* $Id: haval.c 227 2010-06-16 17:28:38Z tp $ */ +/* + * HAVAL implementation. + * + * The HAVAL reference paper is of questionable clarity with regards to + * some details such as endianness of bits within a byte, bytes within + * a 32-bit word, or the actual ordering of words within a stream of + * words. This implementation has been made compatible with the reference + * implementation available on: http://labs.calyptix.com/haval.php + * + * ==========================(LICENSE BEGIN)============================ + * + * Copyright (c) 2007-2010 Projet RNRT SAPHIR + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * ===========================(LICENSE END)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_haval.h" + +#if SPH_SMALL_FOOTPRINT && !defined SPH_SMALL_FOOTPRINT_HAVAL +#define SPH_SMALL_FOOTPRINT_HAVAL 1 +#endif + +/* + * Basic definition from the reference paper. + * +#define F1(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & (x4)) ^ ((x2) & (x5)) ^ ((x3) & (x6)) ^ ((x0) & (x1)) ^ (x0)) + * + */ + +#define F1(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & ((x0) ^ (x4))) ^ ((x2) & (x5)) ^ ((x3) & (x6)) ^ (x0)) + +/* + * Basic definition from the reference paper. + * +#define F2(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & (x2) & (x3)) ^ ((x2) & (x4) & (x5)) ^ ((x1) & (x2)) \ + ^ ((x1) & (x4)) ^ ((x2) & (x6)) ^ ((x3) & (x5)) \ + ^ ((x4) & (x5)) ^ ((x0) & (x2)) ^ (x0)) + * + */ + +#define F2(x6, x5, x4, x3, x2, x1, x0) \ + (((x2) & (((x1) & ~(x3)) ^ ((x4) & (x5)) ^ (x6) ^ (x0))) \ + ^ ((x4) & ((x1) ^ (x5))) ^ ((x3 & (x5)) ^ (x0))) + +/* + * Basic definition from the reference paper. + * +#define F3(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & (x2) & (x3)) ^ ((x1) & (x4)) ^ ((x2) & (x5)) \ + ^ ((x3) & (x6)) ^ ((x0) & (x3)) ^ (x0)) + * + */ + +#define F3(x6, x5, x4, x3, x2, x1, x0) \ + (((x3) & (((x1) & (x2)) ^ (x6) ^ (x0))) \ + ^ ((x1) & (x4)) ^ ((x2) & (x5)) ^ (x0)) + +/* + * Basic definition from the reference paper. + * +#define F4(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & (x2) & (x3)) ^ ((x2) & (x4) & (x5)) ^ ((x3) & (x4) & (x6)) \ + ^ ((x1) & (x4)) ^ ((x2) & (x6)) ^ ((x3) & (x4)) ^ ((x3) & (x5)) \ + ^ ((x3) & (x6)) ^ ((x4) & (x5)) ^ ((x4) & (x6)) ^ ((x0) & (x4)) ^ (x0)) + * + */ + +#define F4(x6, x5, x4, x3, x2, x1, x0) \ + (((x3) & (((x1) & (x2)) ^ ((x4) | (x6)) ^ (x5))) \ + ^ ((x4) & ((~(x2) & (x5)) ^ (x1) ^ (x6) ^ (x0))) \ + ^ ((x2) & (x6)) ^ (x0)) + +/* + * Basic definition from the reference paper. + * +#define F5(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & (x4)) ^ ((x2) & (x5)) ^ ((x3) & (x6)) \ + ^ ((x0) & (x1) & (x2) & (x3)) ^ ((x0) & (x5)) ^ (x0)) + * + */ + +#define F5(x6, x5, x4, x3, x2, x1, x0) \ + (((x0) & ~(((x1) & (x2) & (x3)) ^ (x5))) \ + ^ ((x1) & (x4)) ^ ((x2) & (x5)) ^ ((x3) & (x6))) + +/* + * The macros below integrate the phi() permutations, depending on the + * pass and the total number of passes. + */ + +#define FP3_1(x6, x5, x4, x3, x2, x1, x0) \ + F1(x1, x0, x3, x5, x6, x2, x4) +#define FP3_2(x6, x5, x4, x3, x2, x1, x0) \ + F2(x4, x2, x1, x0, x5, x3, x6) +#define FP3_3(x6, x5, x4, x3, x2, x1, x0) \ + F3(x6, x1, x2, x3, x4, x5, x0) + +#define FP4_1(x6, x5, x4, x3, x2, x1, x0) \ + F1(x2, x6, x1, x4, x5, x3, x0) +#define FP4_2(x6, x5, x4, x3, x2, x1, x0) \ + F2(x3, x5, x2, x0, x1, x6, x4) +#define FP4_3(x6, x5, x4, x3, x2, x1, x0) \ + F3(x1, x4, x3, x6, x0, x2, x5) +#define FP4_4(x6, x5, x4, x3, x2, x1, x0) \ + F4(x6, x4, x0, x5, x2, x1, x3) + +#define FP5_1(x6, x5, x4, x3, x2, x1, x0) \ + F1(x3, x4, x1, x0, x5, x2, x6) +#define FP5_2(x6, x5, x4, x3, x2, x1, x0) \ + F2(x6, x2, x1, x0, x3, x4, x5) +#define FP5_3(x6, x5, x4, x3, x2, x1, x0) \ + F3(x2, x6, x0, x4, x3, x1, x5) +#define FP5_4(x6, x5, x4, x3, x2, x1, x0) \ + F4(x1, x5, x3, x2, x0, x4, x6) +#define FP5_5(x6, x5, x4, x3, x2, x1, x0) \ + F5(x2, x5, x0, x6, x4, x3, x1) + +/* + * One step, for "n" passes, pass number "p" (1 <= p <= n), using + * input word number "w" and step constant "c". + */ +#define STEP(n, p, x7, x6, x5, x4, x3, x2, x1, x0, w, c) do { \ + sph_u32 t = FP ## n ## _ ## p(x6, x5, x4, x3, x2, x1, x0); \ + (x7) = SPH_T32(SPH_ROTR32(t, 7) + SPH_ROTR32((x7), 11) \ + + (w) + (c)); \ + } while (0) + +/* + * PASSy(n, in) computes pass number "y", for a total of "n", using the + * one-argument macro "in" to access input words. Current state is assumed + * to be held in variables "s0" to "s7". + */ + +#if SPH_SMALL_FOOTPRINT_HAVAL + +#define PASS1(n, in) do { \ + unsigned pass_count; \ + for (pass_count = 0; pass_count < 32; pass_count += 8) { \ + STEP(n, 1, s7, s6, s5, s4, s3, s2, s1, s0, \ + in(pass_count + 0), SPH_C32(0x00000000)); \ + STEP(n, 1, s6, s5, s4, s3, s2, s1, s0, s7, \ + in(pass_count + 1), SPH_C32(0x00000000)); \ + STEP(n, 1, s5, s4, s3, s2, s1, s0, s7, s6, \ + in(pass_count + 2), SPH_C32(0x00000000)); \ + STEP(n, 1, s4, s3, s2, s1, s0, s7, s6, s5, \ + in(pass_count + 3), SPH_C32(0x00000000)); \ + STEP(n, 1, s3, s2, s1, s0, s7, s6, s5, s4, \ + in(pass_count + 4), SPH_C32(0x00000000)); \ + STEP(n, 1, s2, s1, s0, s7, s6, s5, s4, s3, \ + in(pass_count + 5), SPH_C32(0x00000000)); \ + STEP(n, 1, s1, s0, s7, s6, s5, s4, s3, s2, \ + in(pass_count + 6), SPH_C32(0x00000000)); \ + STEP(n, 1, s0, s7, s6, s5, s4, s3, s2, s1, \ + in(pass_count + 7), SPH_C32(0x00000000)); \ + } \ + } while (0) + +#define PASSG(p, n, in) do { \ + unsigned pass_count; \ + for (pass_count = 0; pass_count < 32; pass_count += 8) { \ + STEP(n, p, s7, s6, s5, s4, s3, s2, s1, s0, \ + in(MP ## p[pass_count + 0]), \ + RK ## p[pass_count + 0]); \ + STEP(n, p, s6, s5, s4, s3, s2, s1, s0, s7, \ + in(MP ## p[pass_count + 1]), \ + RK ## p[pass_count + 1]); \ + STEP(n, p, s5, s4, s3, s2, s1, s0, s7, s6, \ + in(MP ## p[pass_count + 2]), \ + RK ## p[pass_count + 2]); \ + STEP(n, p, s4, s3, s2, s1, s0, s7, s6, s5, \ + in(MP ## p[pass_count + 3]), \ + RK ## p[pass_count + 3]); \ + STEP(n, p, s3, s2, s1, s0, s7, s6, s5, s4, \ + in(MP ## p[pass_count + 4]), \ + RK ## p[pass_count + 4]); \ + STEP(n, p, s2, s1, s0, s7, s6, s5, s4, s3, \ + in(MP ## p[pass_count + 5]), \ + RK ## p[pass_count + 5]); \ + STEP(n, p, s1, s0, s7, s6, s5, s4, s3, s2, \ + in(MP ## p[pass_count + 6]), \ + RK ## p[pass_count + 6]); \ + STEP(n, p, s0, s7, s6, s5, s4, s3, s2, s1, \ + in(MP ## p[pass_count + 7]), \ + RK ## p[pass_count + 7]); \ + } \ + } while (0) + +#define PASS2(n, in) PASSG(2, n, in) +#define PASS3(n, in) PASSG(3, n, in) +#define PASS4(n, in) PASSG(4, n, in) +#define PASS5(n, in) PASSG(5, n, in) + +static const unsigned MP2[32] = { + 5, 14, 26, 18, 11, 28, 7, 16, + 0, 23, 20, 22, 1, 10, 4, 8, + 30, 3, 21, 9, 17, 24, 29, 6, + 19, 12, 15, 13, 2, 25, 31, 27 +}; + +static const unsigned MP3[32] = { + 19, 9, 4, 20, 28, 17, 8, 22, + 29, 14, 25, 12, 24, 30, 16, 26, + 31, 15, 7, 3, 1, 0, 18, 27, + 13, 6, 21, 10, 23, 11, 5, 2 +}; + +static const unsigned MP4[32] = { + 24, 4, 0, 14, 2, 7, 28, 23, + 26, 6, 30, 20, 18, 25, 19, 3, + 22, 11, 31, 21, 8, 27, 12, 9, + 1, 29, 5, 15, 17, 10, 16, 13 +}; + +static const unsigned MP5[32] = { + 27, 3, 21, 26, 17, 11, 20, 29, + 19, 0, 12, 7, 13, 8, 31, 10, + 5, 9, 14, 30, 18, 6, 28, 24, + 2, 23, 16, 22, 4, 1, 25, 15 +}; + +static const sph_u32 RK2[32] = { + SPH_C32(0x452821E6), SPH_C32(0x38D01377), + SPH_C32(0xBE5466CF), SPH_C32(0x34E90C6C), + SPH_C32(0xC0AC29B7), SPH_C32(0xC97C50DD), + SPH_C32(0x3F84D5B5), SPH_C32(0xB5470917), + SPH_C32(0x9216D5D9), SPH_C32(0x8979FB1B), + SPH_C32(0xD1310BA6), SPH_C32(0x98DFB5AC), + SPH_C32(0x2FFD72DB), SPH_C32(0xD01ADFB7), + SPH_C32(0xB8E1AFED), SPH_C32(0x6A267E96), + SPH_C32(0xBA7C9045), SPH_C32(0xF12C7F99), + SPH_C32(0x24A19947), SPH_C32(0xB3916CF7), + SPH_C32(0x0801F2E2), SPH_C32(0x858EFC16), + SPH_C32(0x636920D8), SPH_C32(0x71574E69), + SPH_C32(0xA458FEA3), SPH_C32(0xF4933D7E), + SPH_C32(0x0D95748F), SPH_C32(0x728EB658), + SPH_C32(0x718BCD58), SPH_C32(0x82154AEE), + SPH_C32(0x7B54A41D), SPH_C32(0xC25A59B5) +}; + +static const sph_u32 RK3[32] = { + SPH_C32(0x9C30D539), SPH_C32(0x2AF26013), + SPH_C32(0xC5D1B023), SPH_C32(0x286085F0), + SPH_C32(0xCA417918), SPH_C32(0xB8DB38EF), + SPH_C32(0x8E79DCB0), SPH_C32(0x603A180E), + SPH_C32(0x6C9E0E8B), SPH_C32(0xB01E8A3E), + SPH_C32(0xD71577C1), SPH_C32(0xBD314B27), + SPH_C32(0x78AF2FDA), SPH_C32(0x55605C60), + SPH_C32(0xE65525F3), SPH_C32(0xAA55AB94), + SPH_C32(0x57489862), SPH_C32(0x63E81440), + SPH_C32(0x55CA396A), SPH_C32(0x2AAB10B6), + SPH_C32(0xB4CC5C34), SPH_C32(0x1141E8CE), + SPH_C32(0xA15486AF), SPH_C32(0x7C72E993), + SPH_C32(0xB3EE1411), SPH_C32(0x636FBC2A), + SPH_C32(0x2BA9C55D), SPH_C32(0x741831F6), + SPH_C32(0xCE5C3E16), SPH_C32(0x9B87931E), + SPH_C32(0xAFD6BA33), SPH_C32(0x6C24CF5C) +}; + +static const sph_u32 RK4[32] = { + SPH_C32(0x7A325381), SPH_C32(0x28958677), + SPH_C32(0x3B8F4898), SPH_C32(0x6B4BB9AF), + SPH_C32(0xC4BFE81B), SPH_C32(0x66282193), + SPH_C32(0x61D809CC), SPH_C32(0xFB21A991), + SPH_C32(0x487CAC60), SPH_C32(0x5DEC8032), + SPH_C32(0xEF845D5D), SPH_C32(0xE98575B1), + SPH_C32(0xDC262302), SPH_C32(0xEB651B88), + SPH_C32(0x23893E81), SPH_C32(0xD396ACC5), + SPH_C32(0x0F6D6FF3), SPH_C32(0x83F44239), + SPH_C32(0x2E0B4482), SPH_C32(0xA4842004), + SPH_C32(0x69C8F04A), SPH_C32(0x9E1F9B5E), + SPH_C32(0x21C66842), SPH_C32(0xF6E96C9A), + SPH_C32(0x670C9C61), SPH_C32(0xABD388F0), + SPH_C32(0x6A51A0D2), SPH_C32(0xD8542F68), + SPH_C32(0x960FA728), SPH_C32(0xAB5133A3), + SPH_C32(0x6EEF0B6C), SPH_C32(0x137A3BE4) +}; + +static const sph_u32 RK5[32] = { + SPH_C32(0xBA3BF050), SPH_C32(0x7EFB2A98), + SPH_C32(0xA1F1651D), SPH_C32(0x39AF0176), + SPH_C32(0x66CA593E), SPH_C32(0x82430E88), + SPH_C32(0x8CEE8619), SPH_C32(0x456F9FB4), + SPH_C32(0x7D84A5C3), SPH_C32(0x3B8B5EBE), + SPH_C32(0xE06F75D8), SPH_C32(0x85C12073), + SPH_C32(0x401A449F), SPH_C32(0x56C16AA6), + SPH_C32(0x4ED3AA62), SPH_C32(0x363F7706), + SPH_C32(0x1BFEDF72), SPH_C32(0x429B023D), + SPH_C32(0x37D0D724), SPH_C32(0xD00A1248), + SPH_C32(0xDB0FEAD3), SPH_C32(0x49F1C09B), + SPH_C32(0x075372C9), SPH_C32(0x80991B7B), + SPH_C32(0x25D479D8), SPH_C32(0xF6E8DEF7), + SPH_C32(0xE3FE501A), SPH_C32(0xB6794C3B), + SPH_C32(0x976CE0BD), SPH_C32(0x04C006BA), + SPH_C32(0xC1A94FB6), SPH_C32(0x409F60C4) +}; + +#else + +#define PASS1(n, in) do { \ + STEP(n, 1, s7, s6, s5, s4, s3, s2, s1, s0, in( 0), SPH_C32(0x00000000)); \ + STEP(n, 1, s6, s5, s4, s3, s2, s1, s0, s7, in( 1), SPH_C32(0x00000000)); \ + STEP(n, 1, s5, s4, s3, s2, s1, s0, s7, s6, in( 2), SPH_C32(0x00000000)); \ + STEP(n, 1, s4, s3, s2, s1, s0, s7, s6, s5, in( 3), SPH_C32(0x00000000)); \ + STEP(n, 1, s3, s2, s1, s0, s7, s6, s5, s4, in( 4), SPH_C32(0x00000000)); \ + STEP(n, 1, s2, s1, s0, s7, s6, s5, s4, s3, in( 5), SPH_C32(0x00000000)); \ + STEP(n, 1, s1, s0, s7, s6, s5, s4, s3, s2, in( 6), SPH_C32(0x00000000)); \ + STEP(n, 1, s0, s7, s6, s5, s4, s3, s2, s1, in( 7), SPH_C32(0x00000000)); \ + \ + STEP(n, 1, s7, s6, s5, s4, s3, s2, s1, s0, in( 8), SPH_C32(0x00000000)); \ + STEP(n, 1, s6, s5, s4, s3, s2, s1, s0, s7, in( 9), SPH_C32(0x00000000)); \ + STEP(n, 1, s5, s4, s3, s2, s1, s0, s7, s6, in(10), SPH_C32(0x00000000)); \ + STEP(n, 1, s4, s3, s2, s1, s0, s7, s6, s5, in(11), SPH_C32(0x00000000)); \ + STEP(n, 1, s3, s2, s1, s0, s7, s6, s5, s4, in(12), SPH_C32(0x00000000)); \ + STEP(n, 1, s2, s1, s0, s7, s6, s5, s4, s3, in(13), SPH_C32(0x00000000)); \ + STEP(n, 1, s1, s0, s7, s6, s5, s4, s3, s2, in(14), SPH_C32(0x00000000)); \ + STEP(n, 1, s0, s7, s6, s5, s4, s3, s2, s1, in(15), SPH_C32(0x00000000)); \ + \ + STEP(n, 1, s7, s6, s5, s4, s3, s2, s1, s0, in(16), SPH_C32(0x00000000)); \ + STEP(n, 1, s6, s5, s4, s3, s2, s1, s0, s7, in(17), SPH_C32(0x00000000)); \ + STEP(n, 1, s5, s4, s3, s2, s1, s0, s7, s6, in(18), SPH_C32(0x00000000)); \ + STEP(n, 1, s4, s3, s2, s1, s0, s7, s6, s5, in(19), SPH_C32(0x00000000)); \ + STEP(n, 1, s3, s2, s1, s0, s7, s6, s5, s4, in(20), SPH_C32(0x00000000)); \ + STEP(n, 1, s2, s1, s0, s7, s6, s5, s4, s3, in(21), SPH_C32(0x00000000)); \ + STEP(n, 1, s1, s0, s7, s6, s5, s4, s3, s2, in(22), SPH_C32(0x00000000)); \ + STEP(n, 1, s0, s7, s6, s5, s4, s3, s2, s1, in(23), SPH_C32(0x00000000)); \ + \ + STEP(n, 1, s7, s6, s5, s4, s3, s2, s1, s0, in(24), SPH_C32(0x00000000)); \ + STEP(n, 1, s6, s5, s4, s3, s2, s1, s0, s7, in(25), SPH_C32(0x00000000)); \ + STEP(n, 1, s5, s4, s3, s2, s1, s0, s7, s6, in(26), SPH_C32(0x00000000)); \ + STEP(n, 1, s4, s3, s2, s1, s0, s7, s6, s5, in(27), SPH_C32(0x00000000)); \ + STEP(n, 1, s3, s2, s1, s0, s7, s6, s5, s4, in(28), SPH_C32(0x00000000)); \ + STEP(n, 1, s2, s1, s0, s7, s6, s5, s4, s3, in(29), SPH_C32(0x00000000)); \ + STEP(n, 1, s1, s0, s7, s6, s5, s4, s3, s2, in(30), SPH_C32(0x00000000)); \ + STEP(n, 1, s0, s7, s6, s5, s4, s3, s2, s1, in(31), SPH_C32(0x00000000)); \ + } while (0) + +#define PASS2(n, in) do { \ + STEP(n, 2, s7, s6, s5, s4, s3, s2, s1, s0, in( 5), SPH_C32(0x452821E6)); \ + STEP(n, 2, s6, s5, s4, s3, s2, s1, s0, s7, in(14), SPH_C32(0x38D01377)); \ + STEP(n, 2, s5, s4, s3, s2, s1, s0, s7, s6, in(26), SPH_C32(0xBE5466CF)); \ + STEP(n, 2, s4, s3, s2, s1, s0, s7, s6, s5, in(18), SPH_C32(0x34E90C6C)); \ + STEP(n, 2, s3, s2, s1, s0, s7, s6, s5, s4, in(11), SPH_C32(0xC0AC29B7)); \ + STEP(n, 2, s2, s1, s0, s7, s6, s5, s4, s3, in(28), SPH_C32(0xC97C50DD)); \ + STEP(n, 2, s1, s0, s7, s6, s5, s4, s3, s2, in( 7), SPH_C32(0x3F84D5B5)); \ + STEP(n, 2, s0, s7, s6, s5, s4, s3, s2, s1, in(16), SPH_C32(0xB5470917)); \ + \ + STEP(n, 2, s7, s6, s5, s4, s3, s2, s1, s0, in( 0), SPH_C32(0x9216D5D9)); \ + STEP(n, 2, s6, s5, s4, s3, s2, s1, s0, s7, in(23), SPH_C32(0x8979FB1B)); \ + STEP(n, 2, s5, s4, s3, s2, s1, s0, s7, s6, in(20), SPH_C32(0xD1310BA6)); \ + STEP(n, 2, s4, s3, s2, s1, s0, s7, s6, s5, in(22), SPH_C32(0x98DFB5AC)); \ + STEP(n, 2, s3, s2, s1, s0, s7, s6, s5, s4, in( 1), SPH_C32(0x2FFD72DB)); \ + STEP(n, 2, s2, s1, s0, s7, s6, s5, s4, s3, in(10), SPH_C32(0xD01ADFB7)); \ + STEP(n, 2, s1, s0, s7, s6, s5, s4, s3, s2, in( 4), SPH_C32(0xB8E1AFED)); \ + STEP(n, 2, s0, s7, s6, s5, s4, s3, s2, s1, in( 8), SPH_C32(0x6A267E96)); \ + \ + STEP(n, 2, s7, s6, s5, s4, s3, s2, s1, s0, in(30), SPH_C32(0xBA7C9045)); \ + STEP(n, 2, s6, s5, s4, s3, s2, s1, s0, s7, in( 3), SPH_C32(0xF12C7F99)); \ + STEP(n, 2, s5, s4, s3, s2, s1, s0, s7, s6, in(21), SPH_C32(0x24A19947)); \ + STEP(n, 2, s4, s3, s2, s1, s0, s7, s6, s5, in( 9), SPH_C32(0xB3916CF7)); \ + STEP(n, 2, s3, s2, s1, s0, s7, s6, s5, s4, in(17), SPH_C32(0x0801F2E2)); \ + STEP(n, 2, s2, s1, s0, s7, s6, s5, s4, s3, in(24), SPH_C32(0x858EFC16)); \ + STEP(n, 2, s1, s0, s7, s6, s5, s4, s3, s2, in(29), SPH_C32(0x636920D8)); \ + STEP(n, 2, s0, s7, s6, s5, s4, s3, s2, s1, in( 6), SPH_C32(0x71574E69)); \ + \ + STEP(n, 2, s7, s6, s5, s4, s3, s2, s1, s0, in(19), SPH_C32(0xA458FEA3)); \ + STEP(n, 2, s6, s5, s4, s3, s2, s1, s0, s7, in(12), SPH_C32(0xF4933D7E)); \ + STEP(n, 2, s5, s4, s3, s2, s1, s0, s7, s6, in(15), SPH_C32(0x0D95748F)); \ + STEP(n, 2, s4, s3, s2, s1, s0, s7, s6, s5, in(13), SPH_C32(0x728EB658)); \ + STEP(n, 2, s3, s2, s1, s0, s7, s6, s5, s4, in( 2), SPH_C32(0x718BCD58)); \ + STEP(n, 2, s2, s1, s0, s7, s6, s5, s4, s3, in(25), SPH_C32(0x82154AEE)); \ + STEP(n, 2, s1, s0, s7, s6, s5, s4, s3, s2, in(31), SPH_C32(0x7B54A41D)); \ + STEP(n, 2, s0, s7, s6, s5, s4, s3, s2, s1, in(27), SPH_C32(0xC25A59B5)); \ + } while (0) + +#define PASS3(n, in) do { \ + STEP(n, 3, s7, s6, s5, s4, s3, s2, s1, s0, in(19), SPH_C32(0x9C30D539)); \ + STEP(n, 3, s6, s5, s4, s3, s2, s1, s0, s7, in( 9), SPH_C32(0x2AF26013)); \ + STEP(n, 3, s5, s4, s3, s2, s1, s0, s7, s6, in( 4), SPH_C32(0xC5D1B023)); \ + STEP(n, 3, s4, s3, s2, s1, s0, s7, s6, s5, in(20), SPH_C32(0x286085F0)); \ + STEP(n, 3, s3, s2, s1, s0, s7, s6, s5, s4, in(28), SPH_C32(0xCA417918)); \ + STEP(n, 3, s2, s1, s0, s7, s6, s5, s4, s3, in(17), SPH_C32(0xB8DB38EF)); \ + STEP(n, 3, s1, s0, s7, s6, s5, s4, s3, s2, in( 8), SPH_C32(0x8E79DCB0)); \ + STEP(n, 3, s0, s7, s6, s5, s4, s3, s2, s1, in(22), SPH_C32(0x603A180E)); \ + \ + STEP(n, 3, s7, s6, s5, s4, s3, s2, s1, s0, in(29), SPH_C32(0x6C9E0E8B)); \ + STEP(n, 3, s6, s5, s4, s3, s2, s1, s0, s7, in(14), SPH_C32(0xB01E8A3E)); \ + STEP(n, 3, s5, s4, s3, s2, s1, s0, s7, s6, in(25), SPH_C32(0xD71577C1)); \ + STEP(n, 3, s4, s3, s2, s1, s0, s7, s6, s5, in(12), SPH_C32(0xBD314B27)); \ + STEP(n, 3, s3, s2, s1, s0, s7, s6, s5, s4, in(24), SPH_C32(0x78AF2FDA)); \ + STEP(n, 3, s2, s1, s0, s7, s6, s5, s4, s3, in(30), SPH_C32(0x55605C60)); \ + STEP(n, 3, s1, s0, s7, s6, s5, s4, s3, s2, in(16), SPH_C32(0xE65525F3)); \ + STEP(n, 3, s0, s7, s6, s5, s4, s3, s2, s1, in(26), SPH_C32(0xAA55AB94)); \ + \ + STEP(n, 3, s7, s6, s5, s4, s3, s2, s1, s0, in(31), SPH_C32(0x57489862)); \ + STEP(n, 3, s6, s5, s4, s3, s2, s1, s0, s7, in(15), SPH_C32(0x63E81440)); \ + STEP(n, 3, s5, s4, s3, s2, s1, s0, s7, s6, in( 7), SPH_C32(0x55CA396A)); \ + STEP(n, 3, s4, s3, s2, s1, s0, s7, s6, s5, in( 3), SPH_C32(0x2AAB10B6)); \ + STEP(n, 3, s3, s2, s1, s0, s7, s6, s5, s4, in( 1), SPH_C32(0xB4CC5C34)); \ + STEP(n, 3, s2, s1, s0, s7, s6, s5, s4, s3, in( 0), SPH_C32(0x1141E8CE)); \ + STEP(n, 3, s1, s0, s7, s6, s5, s4, s3, s2, in(18), SPH_C32(0xA15486AF)); \ + STEP(n, 3, s0, s7, s6, s5, s4, s3, s2, s1, in(27), SPH_C32(0x7C72E993)); \ + \ + STEP(n, 3, s7, s6, s5, s4, s3, s2, s1, s0, in(13), SPH_C32(0xB3EE1411)); \ + STEP(n, 3, s6, s5, s4, s3, s2, s1, s0, s7, in( 6), SPH_C32(0x636FBC2A)); \ + STEP(n, 3, s5, s4, s3, s2, s1, s0, s7, s6, in(21), SPH_C32(0x2BA9C55D)); \ + STEP(n, 3, s4, s3, s2, s1, s0, s7, s6, s5, in(10), SPH_C32(0x741831F6)); \ + STEP(n, 3, s3, s2, s1, s0, s7, s6, s5, s4, in(23), SPH_C32(0xCE5C3E16)); \ + STEP(n, 3, s2, s1, s0, s7, s6, s5, s4, s3, in(11), SPH_C32(0x9B87931E)); \ + STEP(n, 3, s1, s0, s7, s6, s5, s4, s3, s2, in( 5), SPH_C32(0xAFD6BA33)); \ + STEP(n, 3, s0, s7, s6, s5, s4, s3, s2, s1, in( 2), SPH_C32(0x6C24CF5C)); \ + } while (0) + +#define PASS4(n, in) do { \ + STEP(n, 4, s7, s6, s5, s4, s3, s2, s1, s0, in(24), SPH_C32(0x7A325381)); \ + STEP(n, 4, s6, s5, s4, s3, s2, s1, s0, s7, in( 4), SPH_C32(0x28958677)); \ + STEP(n, 4, s5, s4, s3, s2, s1, s0, s7, s6, in( 0), SPH_C32(0x3B8F4898)); \ + STEP(n, 4, s4, s3, s2, s1, s0, s7, s6, s5, in(14), SPH_C32(0x6B4BB9AF)); \ + STEP(n, 4, s3, s2, s1, s0, s7, s6, s5, s4, in( 2), SPH_C32(0xC4BFE81B)); \ + STEP(n, 4, s2, s1, s0, s7, s6, s5, s4, s3, in( 7), SPH_C32(0x66282193)); \ + STEP(n, 4, s1, s0, s7, s6, s5, s4, s3, s2, in(28), SPH_C32(0x61D809CC)); \ + STEP(n, 4, s0, s7, s6, s5, s4, s3, s2, s1, in(23), SPH_C32(0xFB21A991)); \ + \ + STEP(n, 4, s7, s6, s5, s4, s3, s2, s1, s0, in(26), SPH_C32(0x487CAC60)); \ + STEP(n, 4, s6, s5, s4, s3, s2, s1, s0, s7, in( 6), SPH_C32(0x5DEC8032)); \ + STEP(n, 4, s5, s4, s3, s2, s1, s0, s7, s6, in(30), SPH_C32(0xEF845D5D)); \ + STEP(n, 4, s4, s3, s2, s1, s0, s7, s6, s5, in(20), SPH_C32(0xE98575B1)); \ + STEP(n, 4, s3, s2, s1, s0, s7, s6, s5, s4, in(18), SPH_C32(0xDC262302)); \ + STEP(n, 4, s2, s1, s0, s7, s6, s5, s4, s3, in(25), SPH_C32(0xEB651B88)); \ + STEP(n, 4, s1, s0, s7, s6, s5, s4, s3, s2, in(19), SPH_C32(0x23893E81)); \ + STEP(n, 4, s0, s7, s6, s5, s4, s3, s2, s1, in( 3), SPH_C32(0xD396ACC5)); \ + \ + STEP(n, 4, s7, s6, s5, s4, s3, s2, s1, s0, in(22), SPH_C32(0x0F6D6FF3)); \ + STEP(n, 4, s6, s5, s4, s3, s2, s1, s0, s7, in(11), SPH_C32(0x83F44239)); \ + STEP(n, 4, s5, s4, s3, s2, s1, s0, s7, s6, in(31), SPH_C32(0x2E0B4482)); \ + STEP(n, 4, s4, s3, s2, s1, s0, s7, s6, s5, in(21), SPH_C32(0xA4842004)); \ + STEP(n, 4, s3, s2, s1, s0, s7, s6, s5, s4, in( 8), SPH_C32(0x69C8F04A)); \ + STEP(n, 4, s2, s1, s0, s7, s6, s5, s4, s3, in(27), SPH_C32(0x9E1F9B5E)); \ + STEP(n, 4, s1, s0, s7, s6, s5, s4, s3, s2, in(12), SPH_C32(0x21C66842)); \ + STEP(n, 4, s0, s7, s6, s5, s4, s3, s2, s1, in( 9), SPH_C32(0xF6E96C9A)); \ + \ + STEP(n, 4, s7, s6, s5, s4, s3, s2, s1, s0, in( 1), SPH_C32(0x670C9C61)); \ + STEP(n, 4, s6, s5, s4, s3, s2, s1, s0, s7, in(29), SPH_C32(0xABD388F0)); \ + STEP(n, 4, s5, s4, s3, s2, s1, s0, s7, s6, in( 5), SPH_C32(0x6A51A0D2)); \ + STEP(n, 4, s4, s3, s2, s1, s0, s7, s6, s5, in(15), SPH_C32(0xD8542F68)); \ + STEP(n, 4, s3, s2, s1, s0, s7, s6, s5, s4, in(17), SPH_C32(0x960FA728)); \ + STEP(n, 4, s2, s1, s0, s7, s6, s5, s4, s3, in(10), SPH_C32(0xAB5133A3)); \ + STEP(n, 4, s1, s0, s7, s6, s5, s4, s3, s2, in(16), SPH_C32(0x6EEF0B6C)); \ + STEP(n, 4, s0, s7, s6, s5, s4, s3, s2, s1, in(13), SPH_C32(0x137A3BE4)); \ + } while (0) + +#define PASS5(n, in) do { \ + STEP(n, 5, s7, s6, s5, s4, s3, s2, s1, s0, in(27), SPH_C32(0xBA3BF050)); \ + STEP(n, 5, s6, s5, s4, s3, s2, s1, s0, s7, in( 3), SPH_C32(0x7EFB2A98)); \ + STEP(n, 5, s5, s4, s3, s2, s1, s0, s7, s6, in(21), SPH_C32(0xA1F1651D)); \ + STEP(n, 5, s4, s3, s2, s1, s0, s7, s6, s5, in(26), SPH_C32(0x39AF0176)); \ + STEP(n, 5, s3, s2, s1, s0, s7, s6, s5, s4, in(17), SPH_C32(0x66CA593E)); \ + STEP(n, 5, s2, s1, s0, s7, s6, s5, s4, s3, in(11), SPH_C32(0x82430E88)); \ + STEP(n, 5, s1, s0, s7, s6, s5, s4, s3, s2, in(20), SPH_C32(0x8CEE8619)); \ + STEP(n, 5, s0, s7, s6, s5, s4, s3, s2, s1, in(29), SPH_C32(0x456F9FB4)); \ + \ + STEP(n, 5, s7, s6, s5, s4, s3, s2, s1, s0, in(19), SPH_C32(0x7D84A5C3)); \ + STEP(n, 5, s6, s5, s4, s3, s2, s1, s0, s7, in( 0), SPH_C32(0x3B8B5EBE)); \ + STEP(n, 5, s5, s4, s3, s2, s1, s0, s7, s6, in(12), SPH_C32(0xE06F75D8)); \ + STEP(n, 5, s4, s3, s2, s1, s0, s7, s6, s5, in( 7), SPH_C32(0x85C12073)); \ + STEP(n, 5, s3, s2, s1, s0, s7, s6, s5, s4, in(13), SPH_C32(0x401A449F)); \ + STEP(n, 5, s2, s1, s0, s7, s6, s5, s4, s3, in( 8), SPH_C32(0x56C16AA6)); \ + STEP(n, 5, s1, s0, s7, s6, s5, s4, s3, s2, in(31), SPH_C32(0x4ED3AA62)); \ + STEP(n, 5, s0, s7, s6, s5, s4, s3, s2, s1, in(10), SPH_C32(0x363F7706)); \ + \ + STEP(n, 5, s7, s6, s5, s4, s3, s2, s1, s0, in( 5), SPH_C32(0x1BFEDF72)); \ + STEP(n, 5, s6, s5, s4, s3, s2, s1, s0, s7, in( 9), SPH_C32(0x429B023D)); \ + STEP(n, 5, s5, s4, s3, s2, s1, s0, s7, s6, in(14), SPH_C32(0x37D0D724)); \ + STEP(n, 5, s4, s3, s2, s1, s0, s7, s6, s5, in(30), SPH_C32(0xD00A1248)); \ + STEP(n, 5, s3, s2, s1, s0, s7, s6, s5, s4, in(18), SPH_C32(0xDB0FEAD3)); \ + STEP(n, 5, s2, s1, s0, s7, s6, s5, s4, s3, in( 6), SPH_C32(0x49F1C09B)); \ + STEP(n, 5, s1, s0, s7, s6, s5, s4, s3, s2, in(28), SPH_C32(0x075372C9)); \ + STEP(n, 5, s0, s7, s6, s5, s4, s3, s2, s1, in(24), SPH_C32(0x80991B7B)); \ + \ + STEP(n, 5, s7, s6, s5, s4, s3, s2, s1, s0, in( 2), SPH_C32(0x25D479D8)); \ + STEP(n, 5, s6, s5, s4, s3, s2, s1, s0, s7, in(23), SPH_C32(0xF6E8DEF7)); \ + STEP(n, 5, s5, s4, s3, s2, s1, s0, s7, s6, in(16), SPH_C32(0xE3FE501A)); \ + STEP(n, 5, s4, s3, s2, s1, s0, s7, s6, s5, in(22), SPH_C32(0xB6794C3B)); \ + STEP(n, 5, s3, s2, s1, s0, s7, s6, s5, s4, in( 4), SPH_C32(0x976CE0BD)); \ + STEP(n, 5, s2, s1, s0, s7, s6, s5, s4, s3, in( 1), SPH_C32(0x04C006BA)); \ + STEP(n, 5, s1, s0, s7, s6, s5, s4, s3, s2, in(25), SPH_C32(0xC1A94FB6)); \ + STEP(n, 5, s0, s7, s6, s5, s4, s3, s2, s1, in(15), SPH_C32(0x409F60C4)); \ + } while (0) + +#endif + +#define SAVE_STATE \ + sph_u32 u0, u1, u2, u3, u4, u5, u6, u7; \ + do { \ + u0 = s0; \ + u1 = s1; \ + u2 = s2; \ + u3 = s3; \ + u4 = s4; \ + u5 = s5; \ + u6 = s6; \ + u7 = s7; \ + } while (0) + +#define UPDATE_STATE do { \ + s0 = SPH_T32(s0 + u0); \ + s1 = SPH_T32(s1 + u1); \ + s2 = SPH_T32(s2 + u2); \ + s3 = SPH_T32(s3 + u3); \ + s4 = SPH_T32(s4 + u4); \ + s5 = SPH_T32(s5 + u5); \ + s6 = SPH_T32(s6 + u6); \ + s7 = SPH_T32(s7 + u7); \ + } while (0) + +/* + * COREn(in) performs the core HAVAL computation for "n" passes, using + * the one-argument macro "in" to access the input words. Running state + * is held in variable "s0" to "s7". + */ + +#define CORE3(in) do { \ + SAVE_STATE; \ + PASS1(3, in); \ + PASS2(3, in); \ + PASS3(3, in); \ + UPDATE_STATE; \ + } while (0) + +#define CORE4(in) do { \ + SAVE_STATE; \ + PASS1(4, in); \ + PASS2(4, in); \ + PASS3(4, in); \ + PASS4(4, in); \ + UPDATE_STATE; \ + } while (0) + +#define CORE5(in) do { \ + SAVE_STATE; \ + PASS1(5, in); \ + PASS2(5, in); \ + PASS3(5, in); \ + PASS4(5, in); \ + PASS5(5, in); \ + UPDATE_STATE; \ + } while (0) + +/* + * DSTATE declares the state variables "s0" to "s7". + */ +#define DSTATE sph_u32 s0, s1, s2, s3, s4, s5, s6, s7 + +/* + * RSTATE fills the state variables from the context "sc". + */ +#define RSTATE do { \ + s0 = sc->s0; \ + s1 = sc->s1; \ + s2 = sc->s2; \ + s3 = sc->s3; \ + s4 = sc->s4; \ + s5 = sc->s5; \ + s6 = sc->s6; \ + s7 = sc->s7; \ + } while (0) + +/* + * WSTATE updates the context "sc" from the state variables. + */ +#define WSTATE do { \ + sc->s0 = s0; \ + sc->s1 = s1; \ + sc->s2 = s2; \ + sc->s3 = s3; \ + sc->s4 = s4; \ + sc->s5 = s5; \ + sc->s6 = s6; \ + sc->s7 = s7; \ + } while (0) + +/* + * Initialize a context. "olen" is the output length, in 32-bit words + * (between 4 and 8, inclusive). "passes" is the number of passes + * (3, 4 or 5). + */ +static void +haval_init(sph_haval_context *sc, unsigned olen, unsigned passes) +{ + sc->s0 = SPH_C32(0x243F6A88); + sc->s1 = SPH_C32(0x85A308D3); + sc->s2 = SPH_C32(0x13198A2E); + sc->s3 = SPH_C32(0x03707344); + sc->s4 = SPH_C32(0xA4093822); + sc->s5 = SPH_C32(0x299F31D0); + sc->s6 = SPH_C32(0x082EFA98); + sc->s7 = SPH_C32(0xEC4E6C89); + sc->olen = olen; + sc->passes = passes; +#if SPH_64 + sc->count = 0; +#else + sc->count_high = 0; + sc->count_low = 0; +#endif +} + +/* + * IN_PREPARE(data) contains declarations and code to prepare for + * reading input words pointed to by "data". + * INW(i) reads the word number "i" (from 0 to 31). + */ +#if SPH_LITTLE_FAST +#define IN_PREPARE(indata) const unsigned char *const load_ptr = \ + (const unsigned char *)(indata) +#define INW(i) sph_dec32le_aligned(load_ptr + 4 * (i)) +#else +#define IN_PREPARE(indata) \ + sph_u32 X_var[32]; \ + int load_index; \ + \ + for (load_index = 0; load_index < 32; load_index ++) \ + X_var[load_index] = sph_dec32le_aligned( \ + (const unsigned char *)(indata) + 4 * load_index) +#define INW(i) X_var[i] +#endif + +/* + * Mixing operation used for 128-bit output tailoring. This function + * takes the byte 0 from a0, byte 1 from a1, byte 2 from a2 and byte 3 + * from a3, and combines them into a 32-bit word, which is then rotated + * to the left by n bits. + */ +static SPH_INLINE sph_u32 +mix128(sph_u32 a0, sph_u32 a1, sph_u32 a2, sph_u32 a3, int n) +{ + sph_u32 tmp; + + tmp = (a0 & SPH_C32(0x000000FF)) + | (a1 & SPH_C32(0x0000FF00)) + | (a2 & SPH_C32(0x00FF0000)) + | (a3 & SPH_C32(0xFF000000)); + if (n > 0) + tmp = SPH_ROTL32(tmp, n); + return tmp; +} + +/* + * Mixing operation used to compute output word 0 for 160-bit output. + */ +static SPH_INLINE sph_u32 +mix160_0(sph_u32 x5, sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x5 & SPH_C32(0x01F80000)) + | (x6 & SPH_C32(0xFE000000)) + | (x7 & SPH_C32(0x0000003F)); + return SPH_ROTL32(tmp, 13); +} + +/* + * Mixing operation used to compute output word 1 for 160-bit output. + */ +static SPH_INLINE sph_u32 +mix160_1(sph_u32 x5, sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x5 & SPH_C32(0xFE000000)) + | (x6 & SPH_C32(0x0000003F)) + | (x7 & SPH_C32(0x00000FC0)); + return SPH_ROTL32(tmp, 7); +} + +/* + * Mixing operation used to compute output word 2 for 160-bit output. + */ +static SPH_INLINE sph_u32 +mix160_2(sph_u32 x5, sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x5 & SPH_C32(0x0000003F)) + | (x6 & SPH_C32(0x00000FC0)) + | (x7 & SPH_C32(0x0007F000)); + return tmp; +} + +/* + * Mixing operation used to compute output word 3 for 160-bit output. + */ +static SPH_INLINE sph_u32 +mix160_3(sph_u32 x5, sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x5 & SPH_C32(0x00000FC0)) + | (x6 & SPH_C32(0x0007F000)) + | (x7 & SPH_C32(0x01F80000)); + return tmp >> 6; +} + +/* + * Mixing operation used to compute output word 4 for 160-bit output. + */ +static SPH_INLINE sph_u32 +mix160_4(sph_u32 x5, sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x5 & SPH_C32(0x0007F000)) + | (x6 & SPH_C32(0x01F80000)) + | (x7 & SPH_C32(0xFE000000)); + return tmp >> 12; +} + +/* + * Mixing operation used to compute output word 0 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_0(sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x6 & SPH_C32(0xFC000000)) | (x7 & SPH_C32(0x0000001F)); + return SPH_ROTL32(tmp, 6); +} + +/* + * Mixing operation used to compute output word 1 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_1(sph_u32 x6, sph_u32 x7) +{ + return (x6 & SPH_C32(0x0000001F)) | (x7 & SPH_C32(0x000003E0)); +} + +/* + * Mixing operation used to compute output word 2 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_2(sph_u32 x6, sph_u32 x7) +{ + return ((x6 & SPH_C32(0x000003E0)) | (x7 & SPH_C32(0x0000FC00))) >> 5; +} + +/* + * Mixing operation used to compute output word 3 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_3(sph_u32 x6, sph_u32 x7) +{ + return ((x6 & SPH_C32(0x0000FC00)) | (x7 & SPH_C32(0x001F0000))) >> 10; +} + +/* + * Mixing operation used to compute output word 4 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_4(sph_u32 x6, sph_u32 x7) +{ + return ((x6 & SPH_C32(0x001F0000)) | (x7 & SPH_C32(0x03E00000))) >> 16; +} + +/* + * Mixing operation used to compute output word 5 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_5(sph_u32 x6, sph_u32 x7) +{ + return ((x6 & SPH_C32(0x03E00000)) | (x7 & SPH_C32(0xFC000000))) >> 21; +} + +/* + * Write out HAVAL output. The output length is tailored to the requested + * length. + */ +static void +haval_out(sph_haval_context *sc, void *dst) +{ + DSTATE; + unsigned char *buf; + + buf = (unsigned char*)dst; + RSTATE; + switch (sc->olen) { + case 4: + sph_enc32le(buf, SPH_T32(s0 + mix128(s7, s4, s5, s6, 24))); + sph_enc32le(buf + 4, SPH_T32(s1 + mix128(s6, s7, s4, s5, 16))); + sph_enc32le(buf + 8, SPH_T32(s2 + mix128(s5, s6, s7, s4, 8))); + sph_enc32le(buf + 12, SPH_T32(s3 + mix128(s4, s5, s6, s7, 0))); + break; + case 5: + sph_enc32le(buf, SPH_T32(s0 + mix160_0(s5, s6, s7))); + sph_enc32le(buf + 4, SPH_T32(s1 + mix160_1(s5, s6, s7))); + sph_enc32le(buf + 8, SPH_T32(s2 + mix160_2(s5, s6, s7))); + sph_enc32le(buf + 12, SPH_T32(s3 + mix160_3(s5, s6, s7))); + sph_enc32le(buf + 16, SPH_T32(s4 + mix160_4(s5, s6, s7))); + break; + case 6: + sph_enc32le(buf, SPH_T32(s0 + mix192_0(s6, s7))); + sph_enc32le(buf + 4, SPH_T32(s1 + mix192_1(s6, s7))); + sph_enc32le(buf + 8, SPH_T32(s2 + mix192_2(s6, s7))); + sph_enc32le(buf + 12, SPH_T32(s3 + mix192_3(s6, s7))); + sph_enc32le(buf + 16, SPH_T32(s4 + mix192_4(s6, s7))); + sph_enc32le(buf + 20, SPH_T32(s5 + mix192_5(s6, s7))); + break; + case 7: + sph_enc32le(buf, SPH_T32(s0 + ((s7 >> 27) & 0x1F))); + sph_enc32le(buf + 4, SPH_T32(s1 + ((s7 >> 22) & 0x1F))); + sph_enc32le(buf + 8, SPH_T32(s2 + ((s7 >> 18) & 0x0F))); + sph_enc32le(buf + 12, SPH_T32(s3 + ((s7 >> 13) & 0x1F))); + sph_enc32le(buf + 16, SPH_T32(s4 + ((s7 >> 9) & 0x0F))); + sph_enc32le(buf + 20, SPH_T32(s5 + ((s7 >> 4) & 0x1F))); + sph_enc32le(buf + 24, SPH_T32(s6 + ((s7 ) & 0x0F))); + break; + case 8: + sph_enc32le(buf, s0); + sph_enc32le(buf + 4, s1); + sph_enc32le(buf + 8, s2); + sph_enc32le(buf + 12, s3); + sph_enc32le(buf + 16, s4); + sph_enc32le(buf + 20, s5); + sph_enc32le(buf + 24, s6); + sph_enc32le(buf + 28, s7); + break; + } +} + +/* + * The main core functions inline the code with the COREx() macros. We + * use a helper file, included three times, which avoids code copying. + */ + +#undef PASSES +#define PASSES 3 +#include "haval_helper.c" + +#undef PASSES +#define PASSES 4 +#include "haval_helper.c" + +#undef PASSES +#define PASSES 5 +#include "haval_helper.c" + +/* ====================================================================== */ + +#define API(xxx, y) \ +void \ +sph_haval ## xxx ## _ ## y ## _init(void *cc) \ +{ \ + haval_init((sph_haval_context*)cc, xxx >> 5, y); \ +} \ + \ +void \ +sph_haval ## xxx ## _ ## y (void *cc, const void *data, size_t len) \ +{ \ + haval ## y((sph_haval_context*)cc, data, len); \ +} \ + \ +void \ +sph_haval ## xxx ## _ ## y ## _close(void *cc, void *dst) \ +{ \ + haval ## y ## _close((sph_haval_context*)cc, 0, 0, dst); \ +} \ + \ +void \ +sph_haval ## xxx ## _ ## y ## addbits_and_close( \ + void *cc, unsigned ub, unsigned n, void *dst) \ +{ \ + haval ## y ## _close((sph_haval_context*)cc, ub, n, dst); \ +} + +API(128, 3) +API(128, 4) +API(128, 5) +API(160, 3) +API(160, 4) +API(160, 5) +API(192, 3) +API(192, 4) +API(192, 5) +API(224, 3) +API(224, 4) +API(224, 5) +API(256, 3) +API(256, 4) +API(256, 5) + +#define RVAL do { \ + s0 = val[0]; \ + s1 = val[1]; \ + s2 = val[2]; \ + s3 = val[3]; \ + s4 = val[4]; \ + s5 = val[5]; \ + s6 = val[6]; \ + s7 = val[7]; \ + } while (0) + +#define WVAL do { \ + val[0] = s0; \ + val[1] = s1; \ + val[2] = s2; \ + val[3] = s3; \ + val[4] = s4; \ + val[5] = s5; \ + val[6] = s6; \ + val[7] = s7; \ + } while (0) + +#define INMSG(i) msg[i] + +/* see sph_haval.h */ +void +sph_haval_3_comp(const sph_u32 msg[32], sph_u32 val[8]) +{ + DSTATE; + + RVAL; + CORE3(INMSG); + WVAL; +} + +/* see sph_haval.h */ +void +sph_haval_4_comp(const sph_u32 msg[32], sph_u32 val[8]) +{ + DSTATE; + + RVAL; + CORE4(INMSG); + WVAL; +} + +/* see sph_haval.h */ +void +sph_haval_5_comp(const sph_u32 msg[32], sph_u32 val[8]) +{ + DSTATE; + + RVAL; + CORE5(INMSG); + WVAL; +} + diff --git a/src/Native/libmultihash/sha3/sph_haval.h b/src/Native/libmultihash/sha3/sph_haval.h new file mode 100644 index 000000000..6334a9226 --- /dev/null +++ b/src/Native/libmultihash/sha3/sph_haval.h @@ -0,0 +1,969 @@ +/* $Id: sph_haval.h 218 2010-06-08 17:06:34Z tp $ */ +/** +* HAVAL interface. +* +* HAVAL is actually a family of 15 hash functions, depending on whether +* the internal computation uses 3, 4 or 5 passes, and on the output +* length, which is 128, 160, 192, 224 or 256 bits. This implementation +* provides interface functions for all 15, which internally map to +* three cores (depending on the number of passes). Note that output +* lengths other than 256 bits are not obtained by a simple truncation +* of a longer result; the requested length is encoded within the +* padding data. +* +* HAVAL was published in: Yuliang Zheng, Josef Pieprzyk and Jennifer +* Seberry: "HAVAL -- a one-way hashing algorithm with variable length +* of output", Advances in Cryptology -- AUSCRYPT'92, Lecture Notes in +* Computer Science, Vol.718, pp.83-104, Springer-Verlag, 1993. +* +* This paper, and a reference implementation, are available on the +* Calyptix web site: http://labs.calyptix.com/haval.php +* +* The HAVAL reference paper is quite unclear on the data encoding +* details, i.e. endianness (both byte order within a 32-bit word, and +* word order within a message block). This implementation has been +* made compatible with the reference implementation referenced above. +* +* @warning A collision for HAVAL-128/3 (HAVAL with three passes and +* 128-bit output) has been published; this function is thus considered +* as cryptographically broken. The status for other variants is unclear; +* use only with care. +* +* ==========================(LICENSE BEGIN)============================ +* +* Copyright (c) 2007-2010 Projet RNRT SAPHIR +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +* ===========================(LICENSE END)============================= +* +* @file sph_haval.h +* @author Thomas Pornin +*/ + +#ifndef SPH_HAVAL_H__ +#define SPH_HAVAL_H__ + +#include +#include "sph_types.h" + +/** +* Output size (in bits) for HAVAL-128/3. +*/ +#define SPH_SIZE_haval128_3 128 + +/** +* Output size (in bits) for HAVAL-128/4. +*/ +#define SPH_SIZE_haval128_4 128 + +/** +* Output size (in bits) for HAVAL-128/5. +*/ +#define SPH_SIZE_haval128_5 128 + +/** +* Output size (in bits) for HAVAL-160/3. +*/ +#define SPH_SIZE_haval160_3 160 + +/** +* Output size (in bits) for HAVAL-160/4. +*/ +#define SPH_SIZE_haval160_4 160 + +/** +* Output size (in bits) for HAVAL-160/5. +*/ +#define SPH_SIZE_haval160_5 160 + +/** +* Output size (in bits) for HAVAL-192/3. +*/ +#define SPH_SIZE_haval192_3 192 + +/** +* Output size (in bits) for HAVAL-192/4. +*/ +#define SPH_SIZE_haval192_4 192 + +/** +* Output size (in bits) for HAVAL-192/5. +*/ +#define SPH_SIZE_haval192_5 192 + +/** +* Output size (in bits) for HAVAL-224/3. +*/ +#define SPH_SIZE_haval224_3 224 + +/** +* Output size (in bits) for HAVAL-224/4. +*/ +#define SPH_SIZE_haval224_4 224 + +/** +* Output size (in bits) for HAVAL-224/5. +*/ +#define SPH_SIZE_haval224_5 224 + +/** +* Output size (in bits) for HAVAL-256/3. +*/ +#define SPH_SIZE_haval256_3 256 + +/** +* Output size (in bits) for HAVAL-256/4. +*/ +#define SPH_SIZE_haval256_4 256 + +/** +* Output size (in bits) for HAVAL-256/5. +*/ +#define SPH_SIZE_haval256_5 256 + +/** +* This structure is a context for HAVAL computations: it contains the +* intermediate values and some data from the last entered block. Once +* a HAVAL computation has been performed, the context can be reused for +* another computation. +* +* The contents of this structure are private. A running HAVAL computation +* can be cloned by copying the context (e.g. with a simple +* memcpy()). +*/ +typedef struct { +#ifndef DOXYGEN_IGNORE +unsigned char buf[128]; /* first field, for alignment */ +sph_u32 s0, s1, s2, s3, s4, s5, s6, s7; +unsigned olen, passes; +#if SPH_64 +sph_u64 count; +#else +sph_u32 count_high, count_low; +#endif +#endif +} sph_haval_context; + +/** +* Type for a HAVAL-128/3 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval128_3_context; + +/** +* Type for a HAVAL-128/4 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval128_4_context; + +/** +* Type for a HAVAL-128/5 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval128_5_context; + +/** +* Type for a HAVAL-160/3 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval160_3_context; + +/** +* Type for a HAVAL-160/4 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval160_4_context; + +/** +* Type for a HAVAL-160/5 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval160_5_context; + +/** +* Type for a HAVAL-192/3 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval192_3_context; + +/** +* Type for a HAVAL-192/4 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval192_4_context; + +/** +* Type for a HAVAL-192/5 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval192_5_context; + +/** +* Type for a HAVAL-224/3 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval224_3_context; + +/** +* Type for a HAVAL-224/4 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval224_4_context; + +/** +* Type for a HAVAL-224/5 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval224_5_context; + +/** +* Type for a HAVAL-256/3 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval256_3_context; + +/** +* Type for a HAVAL-256/4 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval256_4_context; + +/** +* Type for a HAVAL-256/5 context (identical to the common context). +*/ +typedef sph_haval_context sph_haval256_5_context; + +/** +* Initialize the context for HAVAL-128/3. +* +* @param cc context to initialize (pointer to a +* sph_haval128_3_context structure) +*/ +void sph_haval128_3_init(void *cc); + +/** +* Process some data bytes for HAVAL-128/3. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-128/3 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval128_3(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-128/3 computation. The output buffer must be wide +* enough to accomodate the result (16 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-128/3 context +* @param dst the output buffer +*/ +void sph_haval128_3_close(void *cc, void *dst); + +/** +* Close a HAVAL-128/3 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (16 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-128/3 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval128_3_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-128/4. +* +* @param cc context to initialize (pointer to a +* sph_haval128_4_context structure) +*/ +void sph_haval128_4_init(void *cc); + +/** +* Process some data bytes for HAVAL-128/4. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-128/4 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval128_4(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-128/4 computation. The output buffer must be wide +* enough to accomodate the result (16 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-128/4 context +* @param dst the output buffer +*/ +void sph_haval128_4_close(void *cc, void *dst); + +/** +* Close a HAVAL-128/4 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (16 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-128/4 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval128_4_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-128/5. +* +* @param cc context to initialize (pointer to a +* sph_haval128_5_context structure) +*/ +void sph_haval128_5_init(void *cc); + +/** +* Process some data bytes for HAVAL-128/5. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-128/5 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval128_5(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-128/5 computation. The output buffer must be wide +* enough to accomodate the result (16 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-128/5 context +* @param dst the output buffer +*/ +void sph_haval128_5_close(void *cc, void *dst); + +/** +* Close a HAVAL-128/5 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (16 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-128/5 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval128_5_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-160/3. +* +* @param cc context to initialize (pointer to a +* sph_haval160_3_context structure) +*/ +void sph_haval160_3_init(void *cc); + +/** +* Process some data bytes for HAVAL-160/3. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-160/3 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval160_3(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-160/3 computation. The output buffer must be wide +* enough to accomodate the result (20 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-160/3 context +* @param dst the output buffer +*/ +void sph_haval160_3_close(void *cc, void *dst); + +/** +* Close a HAVAL-160/3 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (20 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-160/3 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval160_3_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-160/4. +* +* @param cc context to initialize (pointer to a +* sph_haval160_4_context structure) +*/ +void sph_haval160_4_init(void *cc); + +/** +* Process some data bytes for HAVAL-160/4. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-160/4 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval160_4(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-160/4 computation. The output buffer must be wide +* enough to accomodate the result (20 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-160/4 context +* @param dst the output buffer +*/ +void sph_haval160_4_close(void *cc, void *dst); + +/** +* Close a HAVAL-160/4 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (20 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-160/4 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval160_3_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-160/5. +* +* @param cc context to initialize (pointer to a +* sph_haval160_5_context structure) +*/ +void sph_haval160_5_init(void *cc); + +/** +* Process some data bytes for HAVAL-160/5. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-160/5 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval160_5(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-160/5 computation. The output buffer must be wide +* enough to accomodate the result (20 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-160/5 context +* @param dst the output buffer +*/ +void sph_haval160_5_close(void *cc, void *dst); + +/** +* Close a HAVAL-160/5 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (20 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-160/5 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval160_5_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-192/3. +* +* @param cc context to initialize (pointer to a +* sph_haval192_3_context structure) +*/ +void sph_haval192_3_init(void *cc); + +/** +* Process some data bytes for HAVAL-192/3. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-192/3 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval192_3(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-192/3 computation. The output buffer must be wide +* enough to accomodate the result (24 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-192/3 context +* @param dst the output buffer +*/ +void sph_haval192_3_close(void *cc, void *dst); + +/** +* Close a HAVAL-192/3 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (24 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-192/3 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval192_3_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-192/4. +* +* @param cc context to initialize (pointer to a +* sph_haval192_4_context structure) +*/ +void sph_haval192_4_init(void *cc); + +/** +* Process some data bytes for HAVAL-192/4. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-192/4 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval192_4(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-192/4 computation. The output buffer must be wide +* enough to accomodate the result (24 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-192/4 context +* @param dst the output buffer +*/ +void sph_haval192_4_close(void *cc, void *dst); + +/** +* Close a HAVAL-192/4 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (24 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-192/4 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval192_4_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-192/5. +* +* @param cc context to initialize (pointer to a +* sph_haval192_5_context structure) +*/ +void sph_haval192_5_init(void *cc); + +/** +* Process some data bytes for HAVAL-192/5. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-192/5 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval192_5(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-192/5 computation. The output buffer must be wide +* enough to accomodate the result (24 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-192/5 context +* @param dst the output buffer +*/ +void sph_haval192_5_close(void *cc, void *dst); + +/** +* Close a HAVAL-192/5 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (24 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-192/5 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval192_5_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-224/3. +* +* @param cc context to initialize (pointer to a +* sph_haval224_3_context structure) +*/ +void sph_haval224_3_init(void *cc); + +/** +* Process some data bytes for HAVAL-224/3. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-224/3 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval224_3(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-224/3 computation. The output buffer must be wide +* enough to accomodate the result (28 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-224/3 context +* @param dst the output buffer +*/ +void sph_haval224_3_close(void *cc, void *dst); + +/** +* Close a HAVAL-224/3 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (28 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-224/3 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval224_3_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-224/4. +* +* @param cc context to initialize (pointer to a +* sph_haval224_4_context structure) +*/ +void sph_haval224_4_init(void *cc); + +/** +* Process some data bytes for HAVAL-224/4. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-224/4 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval224_4(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-224/4 computation. The output buffer must be wide +* enough to accomodate the result (28 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-224/4 context +* @param dst the output buffer +*/ +void sph_haval224_4_close(void *cc, void *dst); + +/** +* Close a HAVAL-224/4 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (28 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-224/4 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval224_4_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-224/5. +* +* @param cc context to initialize (pointer to a +* sph_haval224_5_context structure) +*/ +void sph_haval224_5_init(void *cc); + +/** +* Process some data bytes for HAVAL-224/5. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-224/5 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval224_5(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-224/5 computation. The output buffer must be wide +* enough to accomodate the result (28 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-224/5 context +* @param dst the output buffer +*/ +void sph_haval224_5_close(void *cc, void *dst); + +/** +* Close a HAVAL-224/5 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (28 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-224/5 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval224_5_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-256/3. +* +* @param cc context to initialize (pointer to a +* sph_haval256_3_context structure) +*/ +void sph_haval256_3_init(void *cc); + +/** +* Process some data bytes for HAVAL-256/3. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-256/3 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval256_3(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-256/3 computation. The output buffer must be wide +* enough to accomodate the result (32 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-256/3 context +* @param dst the output buffer +*/ +void sph_haval256_3_close(void *cc, void *dst); + +/** +* Close a HAVAL-256/3 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (32 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-256/3 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval256_3_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-256/4. +* +* @param cc context to initialize (pointer to a +* sph_haval256_4_context structure) +*/ +void sph_haval256_4_init(void *cc); + +/** +* Process some data bytes for HAVAL-256/4. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-256/4 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval256_4(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-256/4 computation. The output buffer must be wide +* enough to accomodate the result (32 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-256/4 context +* @param dst the output buffer +*/ +void sph_haval256_4_close(void *cc, void *dst); + +/** +* Close a HAVAL-256/4 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (32 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-256/4 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval256_4_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Initialize the context for HAVAL-256/5. +* +* @param cc context to initialize (pointer to a +* sph_haval256_5_context structure) +*/ +void sph_haval256_5_init(void *cc); + +/** +* Process some data bytes for HAVAL-256/5. If len is 0, +* then this function does nothing. +* +* @param cc the HAVAL-256/5 context +* @param data the input data +* @param len the input data length (in bytes) +*/ +void sph_haval256_5(void *cc, const void *data, size_t len); + +/** +* Close a HAVAL-256/5 computation. The output buffer must be wide +* enough to accomodate the result (32 bytes). The context is automatically +* reinitialized. +* +* @param cc the HAVAL-256/5 context +* @param dst the output buffer +*/ +void sph_haval256_5_close(void *cc, void *dst); + +/** +* Close a HAVAL-256/5 computation. Up to 7 extra input bits may be added +* to the input message; these are the n upper bits of +* the ub byte (i.e. the first extra bit has value 128 in +* ub, the second extra bit has value 64, and so on). Other +* bits in ub are ignored. +* +* The output buffer must be wide enough to accomodate the result (32 +* bytes). The context is automatically reinitialized. +* +* @param cc the HAVAL-256/5 context +* @param ub the extra bits +* @param n the number of extra bits (0 to 7) +* @param dst the output buffer +*/ +void sph_haval256_5_addbits_and_close(void *cc, +unsigned ub, unsigned n, void *dst); + +/** +* Apply the HAVAL compression function on the provided data. The +* msg parameter contains the 32 32-bit input blocks, +* as numerical values (hence after the little-endian decoding). The +* val parameter contains the 8 32-bit input blocks for +* the compression function; the output is written in place in this +* array. This function uses three internal passes. +* +* @param msg the message block (32 values) +* @param val the function 256-bit input and output +*/ +void sph_haval_3_comp(const sph_u32 msg[32], sph_u32 val[8]); + +/** +* Apply the HAVAL compression function on the provided data. The +* msg parameter contains the 32 32-bit input blocks, +* as numerical values (hence after the little-endian decoding). The +* val parameter contains the 8 32-bit input blocks for +* the compression function; the output is written in place in this +* array. This function uses four internal passes. +* +* @param msg the message block (32 values) +* @param val the function 256-bit input and output +*/ +void sph_haval_4_comp(const sph_u32 msg[32], sph_u32 val[8]); + +/** +* Apply the HAVAL compression function on the provided data. The +* msg parameter contains the 32 32-bit input blocks, +* as numerical values (hence after the little-endian decoding). The +* val parameter contains the 8 32-bit input blocks for +* the compression function; the output is written in place in this +* array. This function uses five internal passes. +* +* @param msg the message block (32 values) +* @param val the function 256-bit input and output +*/ +void sph_haval_5_comp(const sph_u32 msg[32], sph_u32 val[8]); + +#endif diff --git a/src/Native/libmultihash/sha3/sph_sha2.c b/src/Native/libmultihash/sha3/sph_sha2.c new file mode 100644 index 000000000..2c8de457a --- /dev/null +++ b/src/Native/libmultihash/sha3/sph_sha2.c @@ -0,0 +1,691 @@ +/* $Id: sha2.c 227 2010-06-16 17:28:38Z tp $ */ +/* + * SHA-224 / SHA-256 implementation. + * + * ==========================(LICENSE BEGIN)============================ + * + * Copyright (c) 2007-2010 Projet RNRT SAPHIR + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * ===========================(LICENSE END)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_sha2.h" + +#if SPH_SMALL_FOOTPRINT && !defined SPH_SMALL_FOOTPRINT_SHA2 +#define SPH_SMALL_FOOTPRINT_SHA2 1 +#endif + +#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z)) +#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X))) + +#define ROTR SPH_ROTR32 + +#define BSG2_0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define BSG2_1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SSG2_0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SPH_T32((x) >> 3)) +#define SSG2_1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SPH_T32((x) >> 10)) + +static const sph_u32 H224[8] = { + SPH_C32(0xC1059ED8), SPH_C32(0x367CD507), SPH_C32(0x3070DD17), + SPH_C32(0xF70E5939), SPH_C32(0xFFC00B31), SPH_C32(0x68581511), + SPH_C32(0x64F98FA7), SPH_C32(0xBEFA4FA4) +}; + +static const sph_u32 H256[8] = { + SPH_C32(0x6A09E667), SPH_C32(0xBB67AE85), SPH_C32(0x3C6EF372), + SPH_C32(0xA54FF53A), SPH_C32(0x510E527F), SPH_C32(0x9B05688C), + SPH_C32(0x1F83D9AB), SPH_C32(0x5BE0CD19) +}; + +/* + * The SHA2_ROUND_BODY defines the body for a SHA-224 / SHA-256 + * compression function implementation. The "in" parameter should + * evaluate, when applied to a numerical input parameter from 0 to 15, + * to an expression which yields the corresponding input block. The "r" + * parameter should evaluate to an array or pointer expression + * designating the array of 8 words which contains the input and output + * of the compression function. + */ + +#if SPH_SMALL_FOOTPRINT_SHA2 + +static const sph_u32 K[64] = { + SPH_C32(0x428A2F98), SPH_C32(0x71374491), + SPH_C32(0xB5C0FBCF), SPH_C32(0xE9B5DBA5), + SPH_C32(0x3956C25B), SPH_C32(0x59F111F1), + SPH_C32(0x923F82A4), SPH_C32(0xAB1C5ED5), + SPH_C32(0xD807AA98), SPH_C32(0x12835B01), + SPH_C32(0x243185BE), SPH_C32(0x550C7DC3), + SPH_C32(0x72BE5D74), SPH_C32(0x80DEB1FE), + SPH_C32(0x9BDC06A7), SPH_C32(0xC19BF174), + SPH_C32(0xE49B69C1), SPH_C32(0xEFBE4786), + SPH_C32(0x0FC19DC6), SPH_C32(0x240CA1CC), + SPH_C32(0x2DE92C6F), SPH_C32(0x4A7484AA), + SPH_C32(0x5CB0A9DC), SPH_C32(0x76F988DA), + SPH_C32(0x983E5152), SPH_C32(0xA831C66D), + SPH_C32(0xB00327C8), SPH_C32(0xBF597FC7), + SPH_C32(0xC6E00BF3), SPH_C32(0xD5A79147), + SPH_C32(0x06CA6351), SPH_C32(0x14292967), + SPH_C32(0x27B70A85), SPH_C32(0x2E1B2138), + SPH_C32(0x4D2C6DFC), SPH_C32(0x53380D13), + SPH_C32(0x650A7354), SPH_C32(0x766A0ABB), + SPH_C32(0x81C2C92E), SPH_C32(0x92722C85), + SPH_C32(0xA2BFE8A1), SPH_C32(0xA81A664B), + SPH_C32(0xC24B8B70), SPH_C32(0xC76C51A3), + SPH_C32(0xD192E819), SPH_C32(0xD6990624), + SPH_C32(0xF40E3585), SPH_C32(0x106AA070), + SPH_C32(0x19A4C116), SPH_C32(0x1E376C08), + SPH_C32(0x2748774C), SPH_C32(0x34B0BCB5), + SPH_C32(0x391C0CB3), SPH_C32(0x4ED8AA4A), + SPH_C32(0x5B9CCA4F), SPH_C32(0x682E6FF3), + SPH_C32(0x748F82EE), SPH_C32(0x78A5636F), + SPH_C32(0x84C87814), SPH_C32(0x8CC70208), + SPH_C32(0x90BEFFFA), SPH_C32(0xA4506CEB), + SPH_C32(0xBEF9A3F7), SPH_C32(0xC67178F2) +}; + +#define SHA2_MEXP1(in, pc) do { \ + W[pc] = in(pc); \ + } while (0) + +#define SHA2_MEXP2(in, pc) do { \ + W[(pc) & 0x0F] = SPH_T32(SSG2_1(W[((pc) - 2) & 0x0F]) \ + + W[((pc) - 7) & 0x0F] \ + + SSG2_0(W[((pc) - 15) & 0x0F]) + W[(pc) & 0x0F]); \ + } while (0) + +#define SHA2_STEPn(n, a, b, c, d, e, f, g, h, in, pc) do { \ + sph_u32 t1, t2; \ + SHA2_MEXP ## n(in, pc); \ + t1 = SPH_T32(h + BSG2_1(e) + CH(e, f, g) \ + + K[pcount + (pc)] + W[(pc) & 0x0F]); \ + t2 = SPH_T32(BSG2_0(a) + MAJ(a, b, c)); \ + d = SPH_T32(d + t1); \ + h = SPH_T32(t1 + t2); \ + } while (0) + +#define SHA2_STEP1(a, b, c, d, e, f, g, h, in, pc) \ + SHA2_STEPn(1, a, b, c, d, e, f, g, h, in, pc) +#define SHA2_STEP2(a, b, c, d, e, f, g, h, in, pc) \ + SHA2_STEPn(2, a, b, c, d, e, f, g, h, in, pc) + +#define SHA2_ROUND_BODY(in, r) do { \ + sph_u32 A, B, C, D, E, F, G, H; \ + sph_u32 W[16]; \ + unsigned pcount; \ + \ + A = (r)[0]; \ + B = (r)[1]; \ + C = (r)[2]; \ + D = (r)[3]; \ + E = (r)[4]; \ + F = (r)[5]; \ + G = (r)[6]; \ + H = (r)[7]; \ + pcount = 0; \ + SHA2_STEP1(A, B, C, D, E, F, G, H, in, 0); \ + SHA2_STEP1(H, A, B, C, D, E, F, G, in, 1); \ + SHA2_STEP1(G, H, A, B, C, D, E, F, in, 2); \ + SHA2_STEP1(F, G, H, A, B, C, D, E, in, 3); \ + SHA2_STEP1(E, F, G, H, A, B, C, D, in, 4); \ + SHA2_STEP1(D, E, F, G, H, A, B, C, in, 5); \ + SHA2_STEP1(C, D, E, F, G, H, A, B, in, 6); \ + SHA2_STEP1(B, C, D, E, F, G, H, A, in, 7); \ + SHA2_STEP1(A, B, C, D, E, F, G, H, in, 8); \ + SHA2_STEP1(H, A, B, C, D, E, F, G, in, 9); \ + SHA2_STEP1(G, H, A, B, C, D, E, F, in, 10); \ + SHA2_STEP1(F, G, H, A, B, C, D, E, in, 11); \ + SHA2_STEP1(E, F, G, H, A, B, C, D, in, 12); \ + SHA2_STEP1(D, E, F, G, H, A, B, C, in, 13); \ + SHA2_STEP1(C, D, E, F, G, H, A, B, in, 14); \ + SHA2_STEP1(B, C, D, E, F, G, H, A, in, 15); \ + for (pcount = 16; pcount < 64; pcount += 16) { \ + SHA2_STEP2(A, B, C, D, E, F, G, H, in, 0); \ + SHA2_STEP2(H, A, B, C, D, E, F, G, in, 1); \ + SHA2_STEP2(G, H, A, B, C, D, E, F, in, 2); \ + SHA2_STEP2(F, G, H, A, B, C, D, E, in, 3); \ + SHA2_STEP2(E, F, G, H, A, B, C, D, in, 4); \ + SHA2_STEP2(D, E, F, G, H, A, B, C, in, 5); \ + SHA2_STEP2(C, D, E, F, G, H, A, B, in, 6); \ + SHA2_STEP2(B, C, D, E, F, G, H, A, in, 7); \ + SHA2_STEP2(A, B, C, D, E, F, G, H, in, 8); \ + SHA2_STEP2(H, A, B, C, D, E, F, G, in, 9); \ + SHA2_STEP2(G, H, A, B, C, D, E, F, in, 10); \ + SHA2_STEP2(F, G, H, A, B, C, D, E, in, 11); \ + SHA2_STEP2(E, F, G, H, A, B, C, D, in, 12); \ + SHA2_STEP2(D, E, F, G, H, A, B, C, in, 13); \ + SHA2_STEP2(C, D, E, F, G, H, A, B, in, 14); \ + SHA2_STEP2(B, C, D, E, F, G, H, A, in, 15); \ + } \ + (r)[0] = SPH_T32((r)[0] + A); \ + (r)[1] = SPH_T32((r)[1] + B); \ + (r)[2] = SPH_T32((r)[2] + C); \ + (r)[3] = SPH_T32((r)[3] + D); \ + (r)[4] = SPH_T32((r)[4] + E); \ + (r)[5] = SPH_T32((r)[5] + F); \ + (r)[6] = SPH_T32((r)[6] + G); \ + (r)[7] = SPH_T32((r)[7] + H); \ + } while (0) + +#else + +#define SHA2_ROUND_BODY(in, r) do { \ + sph_u32 A, B, C, D, E, F, G, H, T1, T2; \ + sph_u32 W00, W01, W02, W03, W04, W05, W06, W07; \ + sph_u32 W08, W09, W10, W11, W12, W13, W14, W15; \ + \ + A = (r)[0]; \ + B = (r)[1]; \ + C = (r)[2]; \ + D = (r)[3]; \ + E = (r)[4]; \ + F = (r)[5]; \ + G = (r)[6]; \ + H = (r)[7]; \ + W00 = in(0); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0x428A2F98) + W00); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W01 = in(1); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0x71374491) + W01); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W02 = in(2); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0xB5C0FBCF) + W02); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W03 = in(3); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0xE9B5DBA5) + W03); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W04 = in(4); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x3956C25B) + W04); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W05 = in(5); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0x59F111F1) + W05); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W06 = in(6); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x923F82A4) + W06); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W07 = in(7); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0xAB1C5ED5) + W07); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W08 = in(8); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0xD807AA98) + W08); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W09 = in(9); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0x12835B01) + W09); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W10 = in(10); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0x243185BE) + W10); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W11 = in(11); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0x550C7DC3) + W11); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W12 = in(12); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x72BE5D74) + W12); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W13 = in(13); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0x80DEB1FE) + W13); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W14 = in(14); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x9BDC06A7) + W14); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W15 = in(15); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0xC19BF174) + W15); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W00 = SPH_T32(SSG2_1(W14) + W09 + SSG2_0(W01) + W00); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0xE49B69C1) + W00); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W01 = SPH_T32(SSG2_1(W15) + W10 + SSG2_0(W02) + W01); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0xEFBE4786) + W01); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W02 = SPH_T32(SSG2_1(W00) + W11 + SSG2_0(W03) + W02); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0x0FC19DC6) + W02); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W03 = SPH_T32(SSG2_1(W01) + W12 + SSG2_0(W04) + W03); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0x240CA1CC) + W03); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W04 = SPH_T32(SSG2_1(W02) + W13 + SSG2_0(W05) + W04); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x2DE92C6F) + W04); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W05 = SPH_T32(SSG2_1(W03) + W14 + SSG2_0(W06) + W05); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0x4A7484AA) + W05); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W06 = SPH_T32(SSG2_1(W04) + W15 + SSG2_0(W07) + W06); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x5CB0A9DC) + W06); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W07 = SPH_T32(SSG2_1(W05) + W00 + SSG2_0(W08) + W07); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0x76F988DA) + W07); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W08 = SPH_T32(SSG2_1(W06) + W01 + SSG2_0(W09) + W08); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0x983E5152) + W08); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W09 = SPH_T32(SSG2_1(W07) + W02 + SSG2_0(W10) + W09); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0xA831C66D) + W09); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W10 = SPH_T32(SSG2_1(W08) + W03 + SSG2_0(W11) + W10); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0xB00327C8) + W10); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W11 = SPH_T32(SSG2_1(W09) + W04 + SSG2_0(W12) + W11); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0xBF597FC7) + W11); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W12 = SPH_T32(SSG2_1(W10) + W05 + SSG2_0(W13) + W12); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0xC6E00BF3) + W12); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W13 = SPH_T32(SSG2_1(W11) + W06 + SSG2_0(W14) + W13); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0xD5A79147) + W13); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W14 = SPH_T32(SSG2_1(W12) + W07 + SSG2_0(W15) + W14); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x06CA6351) + W14); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W15 = SPH_T32(SSG2_1(W13) + W08 + SSG2_0(W00) + W15); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0x14292967) + W15); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W00 = SPH_T32(SSG2_1(W14) + W09 + SSG2_0(W01) + W00); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0x27B70A85) + W00); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W01 = SPH_T32(SSG2_1(W15) + W10 + SSG2_0(W02) + W01); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0x2E1B2138) + W01); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W02 = SPH_T32(SSG2_1(W00) + W11 + SSG2_0(W03) + W02); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0x4D2C6DFC) + W02); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W03 = SPH_T32(SSG2_1(W01) + W12 + SSG2_0(W04) + W03); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0x53380D13) + W03); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W04 = SPH_T32(SSG2_1(W02) + W13 + SSG2_0(W05) + W04); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x650A7354) + W04); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W05 = SPH_T32(SSG2_1(W03) + W14 + SSG2_0(W06) + W05); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0x766A0ABB) + W05); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W06 = SPH_T32(SSG2_1(W04) + W15 + SSG2_0(W07) + W06); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x81C2C92E) + W06); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W07 = SPH_T32(SSG2_1(W05) + W00 + SSG2_0(W08) + W07); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0x92722C85) + W07); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W08 = SPH_T32(SSG2_1(W06) + W01 + SSG2_0(W09) + W08); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0xA2BFE8A1) + W08); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W09 = SPH_T32(SSG2_1(W07) + W02 + SSG2_0(W10) + W09); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0xA81A664B) + W09); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W10 = SPH_T32(SSG2_1(W08) + W03 + SSG2_0(W11) + W10); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0xC24B8B70) + W10); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W11 = SPH_T32(SSG2_1(W09) + W04 + SSG2_0(W12) + W11); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0xC76C51A3) + W11); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W12 = SPH_T32(SSG2_1(W10) + W05 + SSG2_0(W13) + W12); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0xD192E819) + W12); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W13 = SPH_T32(SSG2_1(W11) + W06 + SSG2_0(W14) + W13); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0xD6990624) + W13); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W14 = SPH_T32(SSG2_1(W12) + W07 + SSG2_0(W15) + W14); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0xF40E3585) + W14); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W15 = SPH_T32(SSG2_1(W13) + W08 + SSG2_0(W00) + W15); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0x106AA070) + W15); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W00 = SPH_T32(SSG2_1(W14) + W09 + SSG2_0(W01) + W00); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0x19A4C116) + W00); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W01 = SPH_T32(SSG2_1(W15) + W10 + SSG2_0(W02) + W01); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0x1E376C08) + W01); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W02 = SPH_T32(SSG2_1(W00) + W11 + SSG2_0(W03) + W02); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0x2748774C) + W02); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W03 = SPH_T32(SSG2_1(W01) + W12 + SSG2_0(W04) + W03); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0x34B0BCB5) + W03); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W04 = SPH_T32(SSG2_1(W02) + W13 + SSG2_0(W05) + W04); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x391C0CB3) + W04); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W05 = SPH_T32(SSG2_1(W03) + W14 + SSG2_0(W06) + W05); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0x4ED8AA4A) + W05); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W06 = SPH_T32(SSG2_1(W04) + W15 + SSG2_0(W07) + W06); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x5B9CCA4F) + W06); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W07 = SPH_T32(SSG2_1(W05) + W00 + SSG2_0(W08) + W07); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0x682E6FF3) + W07); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W08 = SPH_T32(SSG2_1(W06) + W01 + SSG2_0(W09) + W08); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0x748F82EE) + W08); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W09 = SPH_T32(SSG2_1(W07) + W02 + SSG2_0(W10) + W09); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0x78A5636F) + W09); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W10 = SPH_T32(SSG2_1(W08) + W03 + SSG2_0(W11) + W10); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0x84C87814) + W10); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W11 = SPH_T32(SSG2_1(W09) + W04 + SSG2_0(W12) + W11); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0x8CC70208) + W11); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W12 = SPH_T32(SSG2_1(W10) + W05 + SSG2_0(W13) + W12); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x90BEFFFA) + W12); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W13 = SPH_T32(SSG2_1(W11) + W06 + SSG2_0(W14) + W13); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0xA4506CEB) + W13); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W14 = SPH_T32(SSG2_1(W12) + W07 + SSG2_0(W15) + W14); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0xBEF9A3F7) + W14); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W15 = SPH_T32(SSG2_1(W13) + W08 + SSG2_0(W00) + W15); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0xC67178F2) + W15); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + (r)[0] = SPH_T32((r)[0] + A); \ + (r)[1] = SPH_T32((r)[1] + B); \ + (r)[2] = SPH_T32((r)[2] + C); \ + (r)[3] = SPH_T32((r)[3] + D); \ + (r)[4] = SPH_T32((r)[4] + E); \ + (r)[5] = SPH_T32((r)[5] + F); \ + (r)[6] = SPH_T32((r)[6] + G); \ + (r)[7] = SPH_T32((r)[7] + H); \ + } while (0) + +#endif + +/* + * One round of SHA-224 / SHA-256. The data must be aligned for 32-bit access. + */ +static void +sha2_round(const unsigned char *data, sph_u32 r[8]) +{ +#define SHA2_IN(x) sph_dec32be_aligned(data + (4 * (x))) + SHA2_ROUND_BODY(SHA2_IN, r); +#undef SHA2_IN +} + +/* see sph_sha2.h */ +void +sph_sha224_init(void *cc) +{ + sph_sha224_context *sc; + + sc = (sph_sha224_context*)cc; + memcpy(sc->val, H224, sizeof H224); +#if SPH_64 + sc->count = 0; +#else + sc->count_high = sc->count_low = 0; +#endif +} + +/* see sph_sha2.h */ +void +sph_sha256_init(void *cc) +{ + sph_sha256_context *sc; + + sc = (sph_sha224_context*)cc; + memcpy(sc->val, H256, sizeof H256); +#if SPH_64 + sc->count = 0; +#else + sc->count_high = sc->count_low = 0; +#endif +} + +#define RFUN sha2_round +#define HASH sha224 +#define BE32 1 +#include "md_helper.c" + +/* see sph_sha2.h */ +void +sph_sha224_close(void *cc, void *dst) +{ + sha224_close(cc, dst, 7); + sph_sha224_init(cc); +} + +/* see sph_sha2.h */ +void +sph_sha224_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) +{ + sha224_addbits_and_close(cc, ub, n, dst, 7); + sph_sha224_init(cc); +} + +/* see sph_sha2.h */ +void +sph_sha256_close(void *cc, void *dst) +{ + sha224_close(cc, dst, 8); + sph_sha256_init(cc); +} + +/* see sph_sha2.h */ +void +sph_sha256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) +{ + sha224_addbits_and_close(cc, ub, n, dst, 8); + sph_sha256_init(cc); +} + +/* see sph_sha2.h */ +void +sph_sha224_comp(const sph_u32 msg[16], sph_u32 val[8]) +{ +#define SHA2_IN(x) msg[x] + SHA2_ROUND_BODY(SHA2_IN, val); +#undef SHA2_IN +} + diff --git a/src/Native/libmultihash/sha3/sph_sha2.h b/src/Native/libmultihash/sha3/sph_sha2.h new file mode 100644 index 000000000..4b957c2ae --- /dev/null +++ b/src/Native/libmultihash/sha3/sph_sha2.h @@ -0,0 +1,371 @@ +/* $Id: sph_sha2.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * SHA-224, SHA-256, SHA-384 and SHA-512 interface. + * + * SHA-256 has been published in FIPS 180-2, now amended with a change + * notice to include SHA-224 as well (which is a simple variation on + * SHA-256). SHA-384 and SHA-512 are also defined in FIPS 180-2. FIPS + * standards can be found at: + * http://csrc.nist.gov/publications/fips/ + * + * ==========================(LICENSE BEGIN)============================ + * + * Copyright (c) 2007-2010 Projet RNRT SAPHIR + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * ===========================(LICENSE END)============================= + * + * @file sph_sha2.h + * @author Thomas Pornin + */ + +#ifndef SPH_SHA2_H__ +#define SPH_SHA2_H__ + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for SHA-224. + */ +#define SPH_SIZE_sha224 224 + +/** + * Output size (in bits) for SHA-256. + */ +#define SPH_SIZE_sha256 256 + +/** + * This structure is a context for SHA-224 computations: it contains the + * intermediate values and some data from the last entered block. Once + * a SHA-224 computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running SHA-224 computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + sph_u32 val[8]; +#if SPH_64 + sph_u64 count; +#else + sph_u32 count_high, count_low; +#endif +#endif +} sph_sha224_context; + +/** + * This structure is a context for SHA-256 computations. It is identical + * to the SHA-224 context. However, a context is initialized for SHA-224 + * or SHA-256, but not both (the internal IV is not the + * same). + */ +typedef sph_sha224_context sph_sha256_context; + +/** + * Initialize a SHA-224 context. This process performs no memory allocation. + * + * @param cc the SHA-224 context (pointer to + * a sph_sha224_context) + */ +void sph_sha224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SHA-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_sha224(void *cc, const void *data, size_t len); + +/** + * Terminate the current SHA-224 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHA-224 context + * @param dst the destination buffer + */ +void sph_sha224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHA-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_sha224_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Apply the SHA-224 compression function on the provided data. The + * msg parameter contains the 16 32-bit input blocks, + * as numerical values (hence after the big-endian decoding). The + * val parameter contains the 8 32-bit input blocks for + * the compression function; the output is written in place in this + * array. + * + * @param msg the message block (16 values) + * @param val the function 256-bit input and output + */ +void sph_sha224_comp(const sph_u32 msg[16], sph_u32 val[8]); + +/** + * Initialize a SHA-256 context. This process performs no memory allocation. + * + * @param cc the SHA-256 context (pointer to + * a sph_sha256_context) + */ +void sph_sha256_init(void *cc); + +#ifdef DOXYGEN_IGNORE +/** + * Process some data bytes, for SHA-256. This function is identical to + * sha_224() + * + * @param cc the SHA-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_sha256(void *cc, const void *data, size_t len); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_sha256 sph_sha224 +#endif + +/** + * Terminate the current SHA-256 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHA-256 context + * @param dst the destination buffer + */ +void sph_sha256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHA-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_sha256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef DOXYGEN_IGNORE +/** + * Apply the SHA-256 compression function on the provided data. This + * function is identical to sha224_comp(). + * + * @param msg the message block (16 values) + * @param val the function 256-bit input and output + */ +void sph_sha256_comp(const sph_u32 msg[16], sph_u32 val[8]); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_sha256_comp sph_sha224_comp +#endif + +#if SPH_64 + +/** + * Output size (in bits) for SHA-384. + */ +#define SPH_SIZE_sha384 384 + +/** + * Output size (in bits) for SHA-512. + */ +#define SPH_SIZE_sha512 512 + +/** + * This structure is a context for SHA-384 computations: it contains the + * intermediate values and some data from the last entered block. Once + * a SHA-384 computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running SHA-384 computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[128]; /* first field, for alignment */ + sph_u64 val[8]; + sph_u64 count; +#endif +} sph_sha384_context; + +/** + * Initialize a SHA-384 context. This process performs no memory allocation. + * + * @param cc the SHA-384 context (pointer to + * a sph_sha384_context) + */ +void sph_sha384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SHA-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_sha384(void *cc, const void *data, size_t len); + +/** + * Terminate the current SHA-384 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHA-384 context + * @param dst the destination buffer + */ +void sph_sha384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHA-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_sha384_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Apply the SHA-384 compression function on the provided data. The + * msg parameter contains the 16 64-bit input blocks, + * as numerical values (hence after the big-endian decoding). The + * val parameter contains the 8 64-bit input blocks for + * the compression function; the output is written in place in this + * array. + * + * @param msg the message block (16 values) + * @param val the function 512-bit input and output + */ +void sph_sha384_comp(const sph_u64 msg[16], sph_u64 val[8]); + +/** + * This structure is a context for SHA-512 computations. It is identical + * to the SHA-384 context. However, a context is initialized for SHA-384 + * or SHA-512, but not both (the internal IV is not the + * same). + */ +typedef sph_sha384_context sph_sha512_context; + +/** + * Initialize a SHA-512 context. This process performs no memory allocation. + * + * @param cc the SHA-512 context (pointer to + * a sph_sha512_context) + */ +void sph_sha512_init(void *cc); + +#ifdef DOXYGEN_IGNORE +/** + * Process some data bytes, for SHA-512. This function is identical to + * sph_sha384(). + * + * @param cc the SHA-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_sha512(void *cc, const void *data, size_t len); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_sha512 sph_sha384 +#endif + +/** + * Terminate the current SHA-512 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHA-512 context + * @param dst the destination buffer + */ +void sph_sha512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHA-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_sha512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef DOXYGEN_IGNORE +/** + * Apply the SHA-512 compression function. This function is identical to + * sph_sha384_comp(). + * + * @param msg the message block (16 values) + * @param val the function 512-bit input and output + */ +void sph_sha512_comp(const sph_u64 msg[16], sph_u64 val[8]); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_sha512_comp sph_sha384_comp +#endif + +#endif + +#endif + diff --git a/src/Native/libmultihash/sha3/sph_sha2big.c b/src/Native/libmultihash/sha3/sph_sha2big.c new file mode 100644 index 000000000..be97eb986 --- /dev/null +++ b/src/Native/libmultihash/sha3/sph_sha2big.c @@ -0,0 +1,248 @@ +/* $Id: sha2big.c 216 2010-06-08 09:46:57Z tp $ */ +/* + * SHA-384 / SHA-512 implementation. + * + * ==========================(LICENSE BEGIN)============================ + * + * Copyright (c) 2007-2010 Projet RNRT SAPHIR + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * ===========================(LICENSE END)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_sha2.h" + +#if SPH_64 + +#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z)) +#define MAJ(X, Y, Z) (((X) & (Y)) | (((X) | (Y)) & (Z))) + +#define ROTR64 SPH_ROTR64 + +#define BSG5_0(x) (ROTR64(x, 28) ^ ROTR64(x, 34) ^ ROTR64(x, 39)) +#define BSG5_1(x) (ROTR64(x, 14) ^ ROTR64(x, 18) ^ ROTR64(x, 41)) +#define SSG5_0(x) (ROTR64(x, 1) ^ ROTR64(x, 8) ^ SPH_T64((x) >> 7)) +#define SSG5_1(x) (ROTR64(x, 19) ^ ROTR64(x, 61) ^ SPH_T64((x) >> 6)) + +static const sph_u64 K512[80] = { + SPH_C64(0x428A2F98D728AE22), SPH_C64(0x7137449123EF65CD), + SPH_C64(0xB5C0FBCFEC4D3B2F), SPH_C64(0xE9B5DBA58189DBBC), + SPH_C64(0x3956C25BF348B538), SPH_C64(0x59F111F1B605D019), + SPH_C64(0x923F82A4AF194F9B), SPH_C64(0xAB1C5ED5DA6D8118), + SPH_C64(0xD807AA98A3030242), SPH_C64(0x12835B0145706FBE), + SPH_C64(0x243185BE4EE4B28C), SPH_C64(0x550C7DC3D5FFB4E2), + SPH_C64(0x72BE5D74F27B896F), SPH_C64(0x80DEB1FE3B1696B1), + SPH_C64(0x9BDC06A725C71235), SPH_C64(0xC19BF174CF692694), + SPH_C64(0xE49B69C19EF14AD2), SPH_C64(0xEFBE4786384F25E3), + SPH_C64(0x0FC19DC68B8CD5B5), SPH_C64(0x240CA1CC77AC9C65), + SPH_C64(0x2DE92C6F592B0275), SPH_C64(0x4A7484AA6EA6E483), + SPH_C64(0x5CB0A9DCBD41FBD4), SPH_C64(0x76F988DA831153B5), + SPH_C64(0x983E5152EE66DFAB), SPH_C64(0xA831C66D2DB43210), + SPH_C64(0xB00327C898FB213F), SPH_C64(0xBF597FC7BEEF0EE4), + SPH_C64(0xC6E00BF33DA88FC2), SPH_C64(0xD5A79147930AA725), + SPH_C64(0x06CA6351E003826F), SPH_C64(0x142929670A0E6E70), + SPH_C64(0x27B70A8546D22FFC), SPH_C64(0x2E1B21385C26C926), + SPH_C64(0x4D2C6DFC5AC42AED), SPH_C64(0x53380D139D95B3DF), + SPH_C64(0x650A73548BAF63DE), SPH_C64(0x766A0ABB3C77B2A8), + SPH_C64(0x81C2C92E47EDAEE6), SPH_C64(0x92722C851482353B), + SPH_C64(0xA2BFE8A14CF10364), SPH_C64(0xA81A664BBC423001), + SPH_C64(0xC24B8B70D0F89791), SPH_C64(0xC76C51A30654BE30), + SPH_C64(0xD192E819D6EF5218), SPH_C64(0xD69906245565A910), + SPH_C64(0xF40E35855771202A), SPH_C64(0x106AA07032BBD1B8), + SPH_C64(0x19A4C116B8D2D0C8), SPH_C64(0x1E376C085141AB53), + SPH_C64(0x2748774CDF8EEB99), SPH_C64(0x34B0BCB5E19B48A8), + SPH_C64(0x391C0CB3C5C95A63), SPH_C64(0x4ED8AA4AE3418ACB), + SPH_C64(0x5B9CCA4F7763E373), SPH_C64(0x682E6FF3D6B2B8A3), + SPH_C64(0x748F82EE5DEFB2FC), SPH_C64(0x78A5636F43172F60), + SPH_C64(0x84C87814A1F0AB72), SPH_C64(0x8CC702081A6439EC), + SPH_C64(0x90BEFFFA23631E28), SPH_C64(0xA4506CEBDE82BDE9), + SPH_C64(0xBEF9A3F7B2C67915), SPH_C64(0xC67178F2E372532B), + SPH_C64(0xCA273ECEEA26619C), SPH_C64(0xD186B8C721C0C207), + SPH_C64(0xEADA7DD6CDE0EB1E), SPH_C64(0xF57D4F7FEE6ED178), + SPH_C64(0x06F067AA72176FBA), SPH_C64(0x0A637DC5A2C898A6), + SPH_C64(0x113F9804BEF90DAE), SPH_C64(0x1B710B35131C471B), + SPH_C64(0x28DB77F523047D84), SPH_C64(0x32CAAB7B40C72493), + SPH_C64(0x3C9EBE0A15C9BEBC), SPH_C64(0x431D67C49C100D4C), + SPH_C64(0x4CC5D4BECB3E42B6), SPH_C64(0x597F299CFC657E2A), + SPH_C64(0x5FCB6FAB3AD6FAEC), SPH_C64(0x6C44198C4A475817) +}; + +static const sph_u64 H384[8] = { + SPH_C64(0xCBBB9D5DC1059ED8), SPH_C64(0x629A292A367CD507), + SPH_C64(0x9159015A3070DD17), SPH_C64(0x152FECD8F70E5939), + SPH_C64(0x67332667FFC00B31), SPH_C64(0x8EB44A8768581511), + SPH_C64(0xDB0C2E0D64F98FA7), SPH_C64(0x47B5481DBEFA4FA4) +}; + +static const sph_u64 H512[8] = { + SPH_C64(0x6A09E667F3BCC908), SPH_C64(0xBB67AE8584CAA73B), + SPH_C64(0x3C6EF372FE94F82B), SPH_C64(0xA54FF53A5F1D36F1), + SPH_C64(0x510E527FADE682D1), SPH_C64(0x9B05688C2B3E6C1F), + SPH_C64(0x1F83D9ABFB41BD6B), SPH_C64(0x5BE0CD19137E2179) +}; + +/* + * This macro defines the body for a SHA-384 / SHA-512 compression function + * implementation. The "in" parameter should evaluate, when applied to a + * numerical input parameter from 0 to 15, to an expression which yields + * the corresponding input block. The "r" parameter should evaluate to + * an array or pointer expression designating the array of 8 words which + * contains the input and output of the compression function. + * + * SHA-512 is hard for the compiler. If the loop is completely unrolled, + * then the code will be quite huge (possibly more than 100 kB), and the + * performance will be degraded due to cache misses on the code. We + * unroll only eight steps, which avoids all needless copies when + * 64-bit registers are swapped. + */ + +#define SHA3_STEP(A, B, C, D, E, F, G, H, i) do { \ + sph_u64 T1, T2; \ + T1 = SPH_T64(H + BSG5_1(E) + CH(E, F, G) + K512[i] + W[i]); \ + T2 = SPH_T64(BSG5_0(A) + MAJ(A, B, C)); \ + D = SPH_T64(D + T1); \ + H = SPH_T64(T1 + T2); \ + } while (0) + +#define SHA3_ROUND_BODY(in, r) do { \ + int i; \ + sph_u64 A, B, C, D, E, F, G, H; \ + sph_u64 W[80]; \ + \ + for (i = 0; i < 16; i ++) \ + W[i] = in(i); \ + for (i = 16; i < 80; i ++) \ + W[i] = SPH_T64(SSG5_1(W[i - 2]) + W[i - 7] \ + + SSG5_0(W[i - 15]) + W[i - 16]); \ + A = (r)[0]; \ + B = (r)[1]; \ + C = (r)[2]; \ + D = (r)[3]; \ + E = (r)[4]; \ + F = (r)[5]; \ + G = (r)[6]; \ + H = (r)[7]; \ + for (i = 0; i < 80; i += 8) { \ + SHA3_STEP(A, B, C, D, E, F, G, H, i + 0); \ + SHA3_STEP(H, A, B, C, D, E, F, G, i + 1); \ + SHA3_STEP(G, H, A, B, C, D, E, F, i + 2); \ + SHA3_STEP(F, G, H, A, B, C, D, E, i + 3); \ + SHA3_STEP(E, F, G, H, A, B, C, D, i + 4); \ + SHA3_STEP(D, E, F, G, H, A, B, C, i + 5); \ + SHA3_STEP(C, D, E, F, G, H, A, B, i + 6); \ + SHA3_STEP(B, C, D, E, F, G, H, A, i + 7); \ + } \ + (r)[0] = SPH_T64((r)[0] + A); \ + (r)[1] = SPH_T64((r)[1] + B); \ + (r)[2] = SPH_T64((r)[2] + C); \ + (r)[3] = SPH_T64((r)[3] + D); \ + (r)[4] = SPH_T64((r)[4] + E); \ + (r)[5] = SPH_T64((r)[5] + F); \ + (r)[6] = SPH_T64((r)[6] + G); \ + (r)[7] = SPH_T64((r)[7] + H); \ + } while (0) + +/* + * One round of SHA-384 / SHA-512. The data must be aligned for 64-bit access. + */ +static void +sha3_round(const unsigned char *data, sph_u64 r[8]) +{ +#define SHA3_IN(x) sph_dec64be_aligned(data + (8 * (x))) + SHA3_ROUND_BODY(SHA3_IN, r); +#undef SHA3_IN +} + +/* see sph_sha3.h */ +void +sph_sha384_init(void *cc) +{ + sph_sha384_context *sc; + + sc = (sph_sha384_context*)cc; + memcpy(sc->val, H384, sizeof H384); + sc->count = 0; +} + +/* see sph_sha3.h */ +void +sph_sha512_init(void *cc) +{ + sph_sha512_context *sc; + + sc = (sph_sha512_context*)cc; + memcpy(sc->val, H512, sizeof H512); + sc->count = 0; +} + +#define RFUN sha3_round +#define HASH sha384 +#define BE64 1 +#include "md_helper.c" + +/* see sph_sha3.h */ +void +sph_sha384_close(void *cc, void *dst) +{ + sha384_close(cc, dst, 6); + sph_sha384_init(cc); +} + +/* see sph_sha3.h */ +void +sph_sha384_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) +{ + sha384_addbits_and_close(cc, ub, n, dst, 6); + sph_sha384_init(cc); +} + +/* see sph_sha3.h */ +void +sph_sha512_close(void *cc, void *dst) +{ + sha384_close(cc, dst, 8); + sph_sha512_init(cc); +} + +/* see sph_sha3.h */ +void +sph_sha512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) +{ + sha384_addbits_and_close(cc, ub, n, dst, 8); + sph_sha512_init(cc); +} + +/* see sph_sha3.h */ +void +sph_sha384_comp(const sph_u64 msg[16], sph_u64 val[8]) +{ +#define SHA3_IN(x) msg[x] + SHA3_ROUND_BODY(SHA3_IN, val); +#undef SHA3_IN +} + +#endif + diff --git a/src/Native/libmultihash/x17.c b/src/Native/libmultihash/x17.c new file mode 100644 index 000000000..9defffb57 --- /dev/null +++ b/src/Native/libmultihash/x17.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include + +#include "sha3/sph_blake.h" +#include "sha3/sph_bmw.h" +#include "sha3/sph_groestl.h" +#include "sha3/sph_jh.h" +#include "sha3/sph_keccak.h" +#include "sha3/sph_skein.h" +#include "sha3/sph_luffa.h" +#include "sha3/sph_cubehash.h" +#include "sha3/sph_shavite.h" +#include "sha3/sph_simd.h" +#include "sha3/sph_echo.h" +#include "sha3/sph_hamsi.h" +#include "sha3/sph_fugue.h" +#include "sha3/sph_shabal.h" +#include "sha3/sph_whirlpool.h" +#include "sha3/sph_sha2.h" +#include "sha3/sph_haval.h" + +void x17_hash(const char* input, char* output, uint32_t len) +{ + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa1; + sph_cubehash512_context ctx_cubehash1; + sph_shavite512_context ctx_shavite1; + sph_simd512_context ctx_simd1; + sph_echo512_context ctx_echo1; + sph_hamsi512_context ctx_hamsi1; + sph_fugue512_context ctx_fugue1; + sph_shabal512_context ctx_shabal1; + sph_whirlpool_context ctx_whirlpool1; + sph_sha512_context ctx_sha512; + sph_haval256_5_context ctx_haval; + + uint32_t hash[16]; + + sph_blake512_init(&ctx_blake); + sph_blake512 (&ctx_blake, input, len); + sph_blake512_close (&ctx_blake, hash); + + sph_bmw512_init(&ctx_bmw); + sph_bmw512 (&ctx_bmw, hash, 64); + sph_bmw512_close(&ctx_bmw, hash); + + sph_groestl512_init(&ctx_groestl); + sph_groestl512 (&ctx_groestl, hash, 64); + sph_groestl512_close(&ctx_groestl, hash); + + sph_skein512_init(&ctx_skein); + sph_skein512 (&ctx_skein, hash, 64); + sph_skein512_close (&ctx_skein, hash); + + sph_jh512_init(&ctx_jh); + sph_jh512 (&ctx_jh, hash, 64); + sph_jh512_close(&ctx_jh, hash); + + sph_keccak512_init(&ctx_keccak); + sph_keccak512 (&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + + sph_luffa512_init (&ctx_luffa1); + sph_luffa512 (&ctx_luffa1, hash, 64); + sph_luffa512_close (&ctx_luffa1, hash); + + sph_cubehash512_init (&ctx_cubehash1); + sph_cubehash512 (&ctx_cubehash1, hash, 64); + sph_cubehash512_close(&ctx_cubehash1, hash); + + sph_shavite512_init (&ctx_shavite1); + sph_shavite512 (&ctx_shavite1, hash, 64); + sph_shavite512_close(&ctx_shavite1, hash); + + sph_simd512_init (&ctx_simd1); + sph_simd512 (&ctx_simd1, hash, 64); + sph_simd512_close(&ctx_simd1, hash); + + sph_echo512_init (&ctx_echo1); + sph_echo512 (&ctx_echo1, hash, 64); + sph_echo512_close(&ctx_echo1, hash); + + sph_hamsi512_init (&ctx_hamsi1); + sph_hamsi512 (&ctx_hamsi1, hash, 64); + sph_hamsi512_close(&ctx_hamsi1, hash); + + sph_fugue512_init (&ctx_fugue1); + sph_fugue512 (&ctx_fugue1, hash, 64); + sph_fugue512_close(&ctx_fugue1, hash); + + sph_shabal512_init (&ctx_shabal1); + sph_shabal512 (&ctx_shabal1, hash, 64); + sph_shabal512_close(&ctx_shabal1, hash); + + sph_whirlpool_init (&ctx_whirlpool1); + sph_whirlpool (&ctx_whirlpool1, hash, 64); + sph_whirlpool_close(&ctx_whirlpool1, hash); + + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) hash, 64); + sph_sha512_close(&ctx_sha512,(void*) hash); + + sph_haval256_5_init(&ctx_haval); + sph_haval256_5(&ctx_haval,(const void*) hash, 64); + sph_haval256_5_close(&ctx_haval, hash); + + memcpy(output, hash, 32); +} diff --git a/src/Native/libmultihash/x17.h b/src/Native/libmultihash/x17.h new file mode 100644 index 000000000..11c29b889 --- /dev/null +++ b/src/Native/libmultihash/x17.h @@ -0,0 +1,16 @@ +#ifndef X17_H +#define X17_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void x17_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif