| 13 | #define mul32x32_64(a,b) ((uint64_t)(a) * (b)) |
| 14 | |
| 15 | void poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) { |
| 16 | uint32_t t0,t1,t2,t3; |
| 17 | uint32_t h0,h1,h2,h3,h4; |
| 18 | uint32_t r0,r1,r2,r3,r4; |
| 19 | uint32_t s1,s2,s3,s4; |
| 20 | uint32_t b, nb; |
| 21 | size_t j; |
| 22 | uint64_t t[5]; |
| 23 | uint64_t f0,f1,f2,f3; |
| 24 | uint64_t g0,g1,g2,g3,g4; |
| 25 | uint64_t c; |
| 26 | unsigned char mp[16]; |
| 27 | |
| 28 | /* clamp key */ |
| 29 | t0 = ReadLE32(key+0); |
| 30 | t1 = ReadLE32(key+4); |
| 31 | t2 = ReadLE32(key+8); |
| 32 | t3 = ReadLE32(key+12); |
| 33 | |
| 34 | /* precompute multipliers */ |
| 35 | r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6; |
| 36 | r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12; |
| 37 | r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18; |
| 38 | r3 = t2 & 0x3f03fff; t3 >>= 8; |
| 39 | r4 = t3 & 0x00fffff; |
| 40 | |
| 41 | s1 = r1 * 5; |
| 42 | s2 = r2 * 5; |
| 43 | s3 = r3 * 5; |
| 44 | s4 = r4 * 5; |
| 45 | |
| 46 | /* init state */ |
| 47 | h0 = 0; |
| 48 | h1 = 0; |
| 49 | h2 = 0; |
| 50 | h3 = 0; |
| 51 | h4 = 0; |
| 52 | |
| 53 | /* full blocks */ |
| 54 | if (inlen < 16) goto poly1305_donna_atmost15bytes; |
| 55 | poly1305_donna_16bytes: |
| 56 | m += 16; |
| 57 | inlen -= 16; |
| 58 | |
| 59 | t0 = ReadLE32(m-16); |
| 60 | t1 = ReadLE32(m-12); |
| 61 | t2 = ReadLE32(m-8); |
| 62 | t3 = ReadLE32(m-4); |
| 63 | |
| 64 | h0 += t0 & 0x3ffffff; |
| 65 | h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; |
| 66 | h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; |
| 67 | h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; |
| 68 | h4 += (t3 >> 8) | (1 << 24); |
| 69 | |
| 70 | |
| 71 | poly1305_donna_mul: |
| 72 | t[0] = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1); |