< Summary

Information
Class: Renci.SshNet.Security.Chaos.NaCl.Internal.Poly1305Donna
Assembly: Renci.SshNet
File(s): \home\appveyor\projects\ssh-net\src\Renci.SshNet\Security\Chaos.NaCl\Internal\Poly1305Donna.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 100
Coverable lines: 100
Total lines: 154
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
poly1305_auth(...)0%100%

File(s)

\home\appveyor\projects\ssh-net\src\Renci.SshNet\Security\Chaos.NaCl\Internal\Poly1305Donna.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3
 4namespace Renci.SshNet.Security.Chaos.NaCl.Internal
 5{
 6    internal class Poly1305Donna
 7    {
 8        // written by floodyberry (Andrew M.)
 9        // original license: MIT or PUBLIC DOMAIN
 10        // https://github.com/floodyberry/poly1305-donna/blob/master/poly1305-donna-unrolled.c
 11        internal static void poly1305_auth(byte[] output, int outputOffset, byte[] m, int mStart, int mLength, ref Array
 012        {
 13            UInt32 t0, t1, t2, t3;
 14            UInt32 h0, h1, h2, h3, h4;
 15            UInt32 r0, r1, r2, r3, r4;
 16            UInt32 s1, s2, s3, s4;
 17            UInt32 b, nb;
 18            int j;
 19            UInt64 tt0, tt1, tt2, tt3, tt4;
 20            UInt64 f0, f1, f2, f3;
 21            UInt32 g0, g1, g2, g3, g4;
 22            UInt64 c;
 23
 24            /* clamp key */
 025            t0 = key.x0;
 026            t1 = key.x1;
 027            t2 = key.x2;
 028            t3 = key.x3;
 29
 30            /* precompute multipliers */
 031            r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
 032            r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
 033            r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
 034            r3 = t2 & 0x3f03fff; t3 >>= 8;
 035            r4 = t3 & 0x00fffff;
 36
 037            s1 = r1 * 5;
 038            s2 = r2 * 5;
 039            s3 = r3 * 5;
 040            s4 = r4 * 5;
 41
 42            /* init state */
 043            h0 = 0;
 044            h1 = 0;
 045            h2 = 0;
 046            h3 = 0;
 047            h4 = 0;
 48
 49            /* full blocks */
 050            if (mLength < 16)
 051                goto poly1305_donna_atmost15bytes;
 52
 053        poly1305_donna_16bytes:
 054            mStart += 16;
 055            mLength -= 16;
 56
 057            t0 = ByteIntegerConverter.LoadLittleEndian32(m, mStart - 16);
 058            t1 = ByteIntegerConverter.LoadLittleEndian32(m, mStart - 12);
 059            t2 = ByteIntegerConverter.LoadLittleEndian32(m, mStart - 8);
 060            t3 = ByteIntegerConverter.LoadLittleEndian32(m, mStart - 4);
 61
 62            //todo: looks like these can be simplified a bit
 063            h0 += t0 & 0x3ffffff;
 064            h1 += (uint)(((((UInt64)t1 << 32) | t0) >> 26) & 0x3ffffff);
 065            h2 += (uint)(((((UInt64)t2 << 32) | t1) >> 20) & 0x3ffffff);
 066            h3 += (uint)(((((UInt64)t3 << 32) | t2) >> 14) & 0x3ffffff);
 067            h4 += (t3 >> 8) | (1 << 24);
 68
 69
 070        poly1305_donna_mul:
 071            tt0 = (ulong)h0 * r0 + (ulong)h1 * s4 + (ulong)h2 * s3 + (ulong)h3 * s2 + (ulong)h4 * s1;
 072            tt1 = (ulong)h0 * r1 + (ulong)h1 * r0 + (ulong)h2 * s4 + (ulong)h3 * s3 + (ulong)h4 * s2;
 073            tt2 = (ulong)h0 * r2 + (ulong)h1 * r1 + (ulong)h2 * r0 + (ulong)h3 * s4 + (ulong)h4 * s3;
 074            tt3 = (ulong)h0 * r3 + (ulong)h1 * r2 + (ulong)h2 * r1 + (ulong)h3 * r0 + (ulong)h4 * s4;
 075            tt4 = (ulong)h0 * r4 + (ulong)h1 * r3 + (ulong)h2 * r2 + (ulong)h3 * r1 + (ulong)h4 * r0;
 76
 77            unchecked
 078            {
 079                h0 = (UInt32)tt0 & 0x3ffffff; c = (tt0 >> 26);
 080                tt1 += c; h1 = (UInt32)tt1 & 0x3ffffff; b = (UInt32)(tt1 >> 26);
 081                tt2 += b; h2 = (UInt32)tt2 & 0x3ffffff; b = (UInt32)(tt2 >> 26);
 082                tt3 += b; h3 = (UInt32)tt3 & 0x3ffffff; b = (UInt32)(tt3 >> 26);
 083                tt4 += b; h4 = (UInt32)tt4 & 0x3ffffff; b = (UInt32)(tt4 >> 26);
 084            }
 085            h0 += b * 5;
 86
 087            if (mLength >= 16)
 088                goto poly1305_donna_16bytes;
 89
 90    /* final bytes */
 091        poly1305_donna_atmost15bytes:
 092            if (mLength == 0)
 093                goto poly1305_donna_finish;
 94
 095            byte[] mp = new byte[16];//todo remove allocation
 96
 097            for (j = 0; j < mLength; j++)
 098                mp[j] = m[mStart + j];
 099            mp[j++] = 1;
 0100            for (; j < 16; j++)
 0101                mp[j] = 0;
 0102            mLength = 0;
 103
 0104            t0 = ByteIntegerConverter.LoadLittleEndian32(mp, 0);
 0105            t1 = ByteIntegerConverter.LoadLittleEndian32(mp, 4);
 0106            t2 = ByteIntegerConverter.LoadLittleEndian32(mp, 8);
 0107            t3 = ByteIntegerConverter.LoadLittleEndian32(mp, 12);
 0108            CryptoBytes.Wipe(mp);
 109
 0110            h0 += t0 & 0x3ffffff;
 0111            h1 += (uint)(((((UInt64)t1 << 32) | t0) >> 26) & 0x3ffffff);
 0112            h2 += (uint)(((((UInt64)t2 << 32) | t1) >> 20) & 0x3ffffff);
 0113            h3 += (uint)(((((UInt64)t3 << 32) | t2) >> 14) & 0x3ffffff);
 0114            h4 += t3 >> 8;
 115
 0116            goto poly1305_donna_mul;
 117
 0118        poly1305_donna_finish:
 0119            b = h0 >> 26; h0 = h0 & 0x3ffffff;
 0120            h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff;
 0121            h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff;
 0122            h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff;
 0123            h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff;
 0124            h0 += b * 5;
 125
 0126            g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff;
 0127            g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
 0128            g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
 0129            g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
 0130            g4 = unchecked(h4 + b - (1 << 26));
 131
 0132            b = (g4 >> 31) - 1;
 0133            nb = ~b;
 0134            h0 = (h0 & nb) | (g0 & b);
 0135            h1 = (h1 & nb) | (g1 & b);
 0136            h2 = (h2 & nb) | (g2 & b);
 0137            h3 = (h3 & nb) | (g3 & b);
 0138            h4 = (h4 & nb) | (g4 & b);
 139
 0140            f0 = ((h0) | (h1 << 26)) + (UInt64)key.x4;
 0141            f1 = ((h1 >> 6) | (h2 << 20)) + (UInt64)key.x5;
 0142            f2 = ((h2 >> 12) | (h3 << 14)) + (UInt64)key.x6;
 0143            f3 = ((h3 >> 18) | (h4 << 8)) + (UInt64)key.x7;
 144
 145            unchecked
 0146            {
 0147                ByteIntegerConverter.StoreLittleEndian32(output, outputOffset + 0, (uint)f0); f1 += (f0 >> 32);
 0148                ByteIntegerConverter.StoreLittleEndian32(output, outputOffset + 4, (uint)f1); f2 += (f1 >> 32);
 0149                ByteIntegerConverter.StoreLittleEndian32(output, outputOffset + 8, (uint)f2); f3 += (f2 >> 32);
 0150                ByteIntegerConverter.StoreLittleEndian32(output, outputOffset + 12, (uint)f3);
 0151            }
 0152        }
 153    }
 154}