Blame lib/nettle/backport/poly1305-internal.c

Packit Service 4684c1
/* poly1305-internal.c
Packit Service 4684c1
Packit Service 4684c1
   Copyright: 2012-2013 Andrew M. (floodyberry)
Packit Service 4684c1
   Copyright: 2013 Nikos Mavrogiannopoulos
Packit Service 4684c1
   Copyright: 2013 Niels Möller
Packit Service 4684c1
Packit Service 4684c1
   This file is part of GNU Nettle.
Packit Service 4684c1
Packit Service 4684c1
   GNU Nettle is free software: you can redistribute it and/or
Packit Service 4684c1
   modify it under the terms of either:
Packit Service 4684c1
Packit Service 4684c1
     * the GNU Lesser General Public License as published by the Free
Packit Service 4684c1
       Software Foundation; either version 3 of the License, or (at your
Packit Service 4684c1
       option) any later version.
Packit Service 4684c1
Packit Service 4684c1
   or
Packit Service 4684c1
Packit Service 4684c1
     * the GNU General Public License as published by the Free
Packit Service 4684c1
       Software Foundation; either version 2 of the License, or (at your
Packit Service 4684c1
       option) any later version.
Packit Service 4684c1
Packit Service 4684c1
   or both in parallel, as here.
Packit Service 4684c1
Packit Service 4684c1
   GNU Nettle is distributed in the hope that it will be useful,
Packit Service 4684c1
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4684c1
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 4684c1
   General Public License for more details.
Packit Service 4684c1
Packit Service 4684c1
   You should have received copies of the GNU General Public License and
Packit Service 4684c1
   the GNU Lesser General Public License along with this program.  If
Packit Service 4684c1
   not, see http://www.gnu.org/licenses/.
Packit Service 4684c1
*/
Packit Service 4684c1
Packit Service 4684c1
/* Based on https://github.com/floodyberry/poly1305-donna.
Packit Service 4684c1
 * Modified for nettle by Nikos Mavrogiannopoulos and Niels Möller.
Packit Service 4684c1
 * Original license notice:
Packit Service 4684c1
 *
Packit Service 4684c1
 * Permission is hereby granted, free of charge, to any person obtaining a
Packit Service 4684c1
 * copy of this software and associated documentation files (the
Packit Service 4684c1
 * "Software"), to deal in the Software without restriction, including
Packit Service 4684c1
 * without limitation the rights to use, copy, modify, merge, publish,
Packit Service 4684c1
 * distribute, sublicense, and/or sell copies of the Software, and to
Packit Service 4684c1
 * permit persons to whom the Software is furnished to do so, subject to
Packit Service 4684c1
 * the following conditions:
Packit Service 4684c1
 *
Packit Service 4684c1
 * The above copyright notice and this permission notice shall be included
Packit Service 4684c1
 * in all copies or substantial portions of the Software.
Packit Service 4684c1
 *
Packit Service 4684c1
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
Packit Service 4684c1
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit Service 4684c1
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Packit Service 4684c1
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
Packit Service 4684c1
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
Packit Service 4684c1
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
Packit Service 4684c1
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
#if HAVE_CONFIG_H
Packit Service 4684c1
#include "config.h"
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
#include <string.h>
Packit Service 4684c1
Packit Service 4684c1
#include "poly1305.h"
Packit Service 4684c1
#include "poly1305-internal.h"
Packit Service 4684c1
Packit Service 4684c1
#include <nettle/macros.h>
Packit Service 4684c1
Packit Service 4684c1
#define mul32x32_64(a,b) ((uint64_t)(a) * (b))
Packit Service 4684c1
Packit Service 4684c1
#define r0 r.r32[0]
Packit Service 4684c1
#define r1 r.r32[1]
Packit Service 4684c1
#define r2 r.r32[2]
Packit Service 4684c1
#define r3 r.r32[3]
Packit Service 4684c1
#define r4 r.r32[4]
Packit Service 4684c1
#define s1 r.r32[5]
Packit Service 4684c1
#define s2 s32[0]
Packit Service 4684c1
#define s3 s32[1]
Packit Service 4684c1
#define s4 s32[2]
Packit Service 4684c1
Packit Service 4684c1
#define h0 h.h32[0]
Packit Service 4684c1
#define h1 h.h32[1]
Packit Service 4684c1
#define h2 h.h32[2]
Packit Service 4684c1
#define h3 h.h32[3]
Packit Service 4684c1
#define h4 hh
Packit Service 4684c1
Packit Service 4684c1
void
Packit Service 4684c1
_poly1305_set_key(struct poly1305_ctx *ctx, const uint8_t key[16])
Packit Service 4684c1
{
Packit Service 4684c1
  uint32_t t0,t1,t2,t3;
Packit Service 4684c1
Packit Service 4684c1
  t0 = LE_READ_UINT32(key);
Packit Service 4684c1
  t1 = LE_READ_UINT32(key+4);
Packit Service 4684c1
  t2 = LE_READ_UINT32(key+8);
Packit Service 4684c1
  t3 = LE_READ_UINT32(key+12);
Packit Service 4684c1
Packit Service 4684c1
  ctx->r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
Packit Service 4684c1
  ctx->r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
Packit Service 4684c1
  ctx->r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
Packit Service 4684c1
  ctx->r3 = t2 & 0x3f03fff; t3 >>= 8;
Packit Service 4684c1
  ctx->r4 = t3 & 0x00fffff;
Packit Service 4684c1
Packit Service 4684c1
  ctx->s1 = ctx->r1 * 5;
Packit Service 4684c1
  ctx->s2 = ctx->r2 * 5;
Packit Service 4684c1
  ctx->s3 = ctx->r3 * 5;
Packit Service 4684c1
  ctx->s4 = ctx->r4 * 5;
Packit Service 4684c1
Packit Service 4684c1
  ctx->h0 = 0;
Packit Service 4684c1
  ctx->h1 = 0;
Packit Service 4684c1
  ctx->h2 = 0;
Packit Service 4684c1
  ctx->h3 = 0;
Packit Service 4684c1
  ctx->h4 = 0;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
void
Packit Service 4684c1
_poly1305_block (struct poly1305_ctx *ctx, const uint8_t *m, unsigned t4)
Packit Service 4684c1
{
Packit Service 4684c1
  uint32_t t0,t1,t2,t3;
Packit Service 4684c1
  uint32_t b;
Packit Service 4684c1
  uint64_t t[5];
Packit Service 4684c1
  uint64_t c;
Packit Service 4684c1
Packit Service 4684c1
  t0 = LE_READ_UINT32(m);
Packit Service 4684c1
  t1 = LE_READ_UINT32(m+4);
Packit Service 4684c1
  t2 = LE_READ_UINT32(m+8);
Packit Service 4684c1
  t3 = LE_READ_UINT32(m+12);
Packit Service 4684c1
Packit Service 4684c1
  ctx->h0 += t0 & 0x3ffffff;
Packit Service 4684c1
  ctx->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
Packit Service 4684c1
  ctx->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
Packit Service 4684c1
  ctx->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
Packit Service 4684c1
  ctx->h4 += (t3 >> 8) | ((uint32_t) t4 << 24);
Packit Service 4684c1
Packit Service 4684c1
  /* poly1305_donna_mul: */
Packit Service 4684c1
  t[0]  = mul32x32_64(ctx->h0,ctx->r0) + mul32x32_64(ctx->h1,ctx->s4) + mul32x32_64(ctx->h2,ctx->s3) + mul32x32_64(ctx->h3,ctx->s2) + mul32x32_64(ctx->h4,ctx->s1);
Packit Service 4684c1
  t[1]  = mul32x32_64(ctx->h0,ctx->r1) + mul32x32_64(ctx->h1,ctx->r0) + mul32x32_64(ctx->h2,ctx->s4) + mul32x32_64(ctx->h3,ctx->s3) + mul32x32_64(ctx->h4,ctx->s2);
Packit Service 4684c1
  t[2]  = mul32x32_64(ctx->h0,ctx->r2) + mul32x32_64(ctx->h1,ctx->r1) + mul32x32_64(ctx->h2,ctx->r0) + mul32x32_64(ctx->h3,ctx->s4) + mul32x32_64(ctx->h4,ctx->s3);
Packit Service 4684c1
  t[3]  = mul32x32_64(ctx->h0,ctx->r3) + mul32x32_64(ctx->h1,ctx->r2) + mul32x32_64(ctx->h2,ctx->r1) + mul32x32_64(ctx->h3,ctx->r0) + mul32x32_64(ctx->h4,ctx->s4);
Packit Service 4684c1
  t[4]  = mul32x32_64(ctx->h0,ctx->r4) + mul32x32_64(ctx->h1,ctx->r3) + mul32x32_64(ctx->h2,ctx->r2) + mul32x32_64(ctx->h3,ctx->r1) + mul32x32_64(ctx->h4,ctx->r0);
Packit Service 4684c1
Packit Service 4684c1
  ctx->h0 = (uint32_t)t[0] & 0x3ffffff; c =           (t[0] >> 26);
Packit Service 4684c1
  t[1] += c;      ctx->h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26);
Packit Service 4684c1
  t[2] += b;      ctx->h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26);
Packit Service 4684c1
  t[3] += b;      ctx->h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26);
Packit Service 4684c1
  t[4] += b;      ctx->h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26);
Packit Service 4684c1
  ctx->h0 += b * 5;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Adds digest to the nonce */
Packit Service 4684c1
void
Packit Service 4684c1
_poly1305_digest (struct poly1305_ctx *ctx, union nettle_block16 *s)
Packit Service 4684c1
{
Packit Service 4684c1
  uint32_t b, nb;
Packit Service 4684c1
  uint64_t f0,f1,f2,f3;
Packit Service 4684c1
  uint32_t g0,g1,g2,g3,g4;
Packit Service 4684c1
Packit Service 4684c1
  b = ctx->h0 >> 26; ctx->h0 = ctx->h0 & 0x3ffffff;
Packit Service 4684c1
  ctx->h1 +=     b; b = ctx->h1 >> 26; ctx->h1 = ctx->h1 & 0x3ffffff;
Packit Service 4684c1
  ctx->h2 +=     b; b = ctx->h2 >> 26; ctx->h2 = ctx->h2 & 0x3ffffff;
Packit Service 4684c1
  ctx->h3 +=     b; b = ctx->h3 >> 26; ctx->h3 = ctx->h3 & 0x3ffffff;
Packit Service 4684c1
  ctx->h4 +=     b; b = ctx->h4 >> 26; ctx->h4 = ctx->h4 & 0x3ffffff;
Packit Service 4684c1
  ctx->h0 += b * 5; b = ctx->h0 >> 26; ctx->h0 = ctx->h0 & 0x3ffffff;
Packit Service 4684c1
  ctx->h1 +=     b;
Packit Service 4684c1
Packit Service 4684c1
  g0 = ctx->h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff;
Packit Service 4684c1
  g1 = ctx->h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
Packit Service 4684c1
  g2 = ctx->h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
Packit Service 4684c1
  g3 = ctx->h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
Packit Service 4684c1
  g4 = ctx->h4 + b - (1 << 26);
Packit Service 4684c1
Packit Service 4684c1
  b = (g4 >> 31) - 1;
Packit Service 4684c1
  nb = ~b;
Packit Service 4684c1
  ctx->h0 = (ctx->h0 & nb) | (g0 & b);
Packit Service 4684c1
  ctx->h1 = (ctx->h1 & nb) | (g1 & b);
Packit Service 4684c1
  ctx->h2 = (ctx->h2 & nb) | (g2 & b);
Packit Service 4684c1
  ctx->h3 = (ctx->h3 & nb) | (g3 & b);
Packit Service 4684c1
  ctx->h4 = (ctx->h4 & nb) | (g4 & b);
Packit Service 4684c1
Packit Service 4684c1
  /* FIXME: Take advantage of s being aligned as an unsigned long. */
Packit Service 4684c1
  f0 = ((ctx->h0    )|(ctx->h1<<26)) + (uint64_t)LE_READ_UINT32(s->b);
Packit Service 4684c1
  f1 = ((ctx->h1>> 6)|(ctx->h2<<20)) + (uint64_t)LE_READ_UINT32(s->b+4);
Packit Service 4684c1
  f2 = ((ctx->h2>>12)|(ctx->h3<<14)) + (uint64_t)LE_READ_UINT32(s->b+8);
Packit Service 4684c1
  f3 = ((ctx->h3>>18)|(ctx->h4<< 8)) + (uint64_t)LE_READ_UINT32(s->b+12);
Packit Service 4684c1
Packit Service 4684c1
  LE_WRITE_UINT32(s->b, f0);
Packit Service 4684c1
  f1 += (f0 >> 32);
Packit Service 4684c1
  LE_WRITE_UINT32(s->b+4, f1);
Packit Service 4684c1
  f2 += (f1 >> 32);
Packit Service 4684c1
  LE_WRITE_UINT32(s->b+8, f2);
Packit Service 4684c1
  f3 += (f2 >> 32);
Packit Service 4684c1
  LE_WRITE_UINT32(s->b+12, f3);
Packit Service 4684c1
Packit Service 4684c1
  ctx->h0 = 0;
Packit Service 4684c1
  ctx->h1 = 0;
Packit Service 4684c1
  ctx->h2 = 0;
Packit Service 4684c1
  ctx->h3 = 0;
Packit Service 4684c1
  ctx->h4 = 0;
Packit Service 4684c1
}