wolfSSL SSL/TLS library, support up to TLS1.3

Dependents:   CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more

Committer:
wolfSSL
Date:
Fri Jun 26 00:39:20 2015 +0000
Revision:
0:d92f9d21154c
wolfSSL 3.6.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wolfSSL 0:d92f9d21154c 1 /* poly1305.c
wolfSSL 0:d92f9d21154c 2 *
wolfSSL 0:d92f9d21154c 3 * Copyright (C) 2006-2015 wolfSSL Inc.
wolfSSL 0:d92f9d21154c 4 *
wolfSSL 0:d92f9d21154c 5 * This file is part of wolfSSL. (formerly known as CyaSSL)
wolfSSL 0:d92f9d21154c 6 *
wolfSSL 0:d92f9d21154c 7 * wolfSSL is free software; you can redistribute it and/or modify
wolfSSL 0:d92f9d21154c 8 * it under the terms of the GNU General Public License as published by
wolfSSL 0:d92f9d21154c 9 * the Free Software Foundation; either version 2 of the License, or
wolfSSL 0:d92f9d21154c 10 * (at your option) any later version.
wolfSSL 0:d92f9d21154c 11 *
wolfSSL 0:d92f9d21154c 12 * wolfSSL is distributed in the hope that it will be useful,
wolfSSL 0:d92f9d21154c 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
wolfSSL 0:d92f9d21154c 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wolfSSL 0:d92f9d21154c 15 * GNU General Public License for more details.
wolfSSL 0:d92f9d21154c 16 *
wolfSSL 0:d92f9d21154c 17 * You should have received a copy of the GNU General Public License
wolfSSL 0:d92f9d21154c 18 * along with this program; if not, write to the Free Software
wolfSSL 0:d92f9d21154c 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
wolfSSL 0:d92f9d21154c 20 *
wolfSSL 0:d92f9d21154c 21 * Based off the public domain implementations by Andrew Moon
wolfSSL 0:d92f9d21154c 22 * and Daniel J. Bernstein
wolfSSL 0:d92f9d21154c 23 */
wolfSSL 0:d92f9d21154c 24
wolfSSL 0:d92f9d21154c 25 #ifdef HAVE_CONFIG_H
wolfSSL 0:d92f9d21154c 26 #include <config.h>
wolfSSL 0:d92f9d21154c 27 #endif
wolfSSL 0:d92f9d21154c 28
wolfSSL 0:d92f9d21154c 29 #include <wolfssl/wolfcrypt/settings.h>
wolfSSL 0:d92f9d21154c 30
wolfSSL 0:d92f9d21154c 31 #ifdef HAVE_POLY1305
wolfSSL 0:d92f9d21154c 32 #include <wolfssl/wolfcrypt/poly1305.h>
wolfSSL 0:d92f9d21154c 33 #include <wolfssl/wolfcrypt/error-crypt.h>
wolfSSL 0:d92f9d21154c 34 #include <wolfssl/wolfcrypt/logging.h>
wolfSSL 0:d92f9d21154c 35 #ifdef NO_INLINE
wolfSSL 0:d92f9d21154c 36 #include <wolfssl/wolfcrypt/misc.h>
wolfSSL 0:d92f9d21154c 37 #else
wolfSSL 0:d92f9d21154c 38 #include <wolfcrypt/src/misc.c>
wolfSSL 0:d92f9d21154c 39 #endif
wolfSSL 0:d92f9d21154c 40 #ifdef CHACHA_AEAD_TEST
wolfSSL 0:d92f9d21154c 41 #include <stdio.h>
wolfSSL 0:d92f9d21154c 42 #endif
wolfSSL 0:d92f9d21154c 43
wolfSSL 0:d92f9d21154c 44 #ifdef _MSC_VER
wolfSSL 0:d92f9d21154c 45 /* 4127 warning constant while(1) */
wolfSSL 0:d92f9d21154c 46 #pragma warning(disable: 4127)
wolfSSL 0:d92f9d21154c 47 #endif
wolfSSL 0:d92f9d21154c 48
wolfSSL 0:d92f9d21154c 49 #if defined(POLY130564)
wolfSSL 0:d92f9d21154c 50
wolfSSL 0:d92f9d21154c 51 #if defined(_MSC_VER)
wolfSSL 0:d92f9d21154c 52 #define POLY1305_NOINLINE __declspec(noinline)
wolfSSL 0:d92f9d21154c 53 #elif defined(__GNUC__)
wolfSSL 0:d92f9d21154c 54 #define POLY1305_NOINLINE __attribute__((noinline))
wolfSSL 0:d92f9d21154c 55 #else
wolfSSL 0:d92f9d21154c 56 #define POLY1305_NOINLINE
wolfSSL 0:d92f9d21154c 57 #endif
wolfSSL 0:d92f9d21154c 58
wolfSSL 0:d92f9d21154c 59 #if defined(_MSC_VER)
wolfSSL 0:d92f9d21154c 60 #include <intrin.h>
wolfSSL 0:d92f9d21154c 61
wolfSSL 0:d92f9d21154c 62 typedef struct word128 {
wolfSSL 0:d92f9d21154c 63 word64 lo;
wolfSSL 0:d92f9d21154c 64 word64 hi;
wolfSSL 0:d92f9d21154c 65 } word128;
wolfSSL 0:d92f9d21154c 66
wolfSSL 0:d92f9d21154c 67 #define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi)
wolfSSL 0:d92f9d21154c 68 #define ADD(out, in) { word64 t = out.lo; out.lo += in.lo;
wolfSSL 0:d92f9d21154c 69 out.hi += (out.lo < t) + in.hi; }
wolfSSL 0:d92f9d21154c 70 #define ADDLO(out, in) { word64 t = out.lo; out.lo += in;
wolfSSL 0:d92f9d21154c 71 out.hi += (out.lo < t); }
wolfSSL 0:d92f9d21154c 72 #define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift)))
wolfSSL 0:d92f9d21154c 73 #define LO(in) (in.lo)
wolfSSL 0:d92f9d21154c 74
wolfSSL 0:d92f9d21154c 75 #elif defined(__GNUC__)
wolfSSL 0:d92f9d21154c 76 #if defined(__SIZEOF_INT128__)
wolfSSL 0:d92f9d21154c 77 typedef unsigned __int128 word128;
wolfSSL 0:d92f9d21154c 78 #else
wolfSSL 0:d92f9d21154c 79 typedef unsigned word128 __attribute__((mode(TI)));
wolfSSL 0:d92f9d21154c 80 #endif
wolfSSL 0:d92f9d21154c 81
wolfSSL 0:d92f9d21154c 82 #define MUL(out, x, y) out = ((word128)x * y)
wolfSSL 0:d92f9d21154c 83 #define ADD(out, in) out += in
wolfSSL 0:d92f9d21154c 84 #define ADDLO(out, in) out += in
wolfSSL 0:d92f9d21154c 85 #define SHR(in, shift) (word64)(in >> (shift))
wolfSSL 0:d92f9d21154c 86 #define LO(in) (word64)(in)
wolfSSL 0:d92f9d21154c 87 #endif
wolfSSL 0:d92f9d21154c 88
wolfSSL 0:d92f9d21154c 89 static word64 U8TO64(const byte* p) {
wolfSSL 0:d92f9d21154c 90 return
wolfSSL 0:d92f9d21154c 91 (((word64)(p[0] & 0xff) ) |
wolfSSL 0:d92f9d21154c 92 ((word64)(p[1] & 0xff) << 8) |
wolfSSL 0:d92f9d21154c 93 ((word64)(p[2] & 0xff) << 16) |
wolfSSL 0:d92f9d21154c 94 ((word64)(p[3] & 0xff) << 24) |
wolfSSL 0:d92f9d21154c 95 ((word64)(p[4] & 0xff) << 32) |
wolfSSL 0:d92f9d21154c 96 ((word64)(p[5] & 0xff) << 40) |
wolfSSL 0:d92f9d21154c 97 ((word64)(p[6] & 0xff) << 48) |
wolfSSL 0:d92f9d21154c 98 ((word64)(p[7] & 0xff) << 56));
wolfSSL 0:d92f9d21154c 99 }
wolfSSL 0:d92f9d21154c 100
wolfSSL 0:d92f9d21154c 101 static void U64TO8(byte* p, word64 v) {
wolfSSL 0:d92f9d21154c 102 p[0] = (v ) & 0xff;
wolfSSL 0:d92f9d21154c 103 p[1] = (v >> 8) & 0xff;
wolfSSL 0:d92f9d21154c 104 p[2] = (v >> 16) & 0xff;
wolfSSL 0:d92f9d21154c 105 p[3] = (v >> 24) & 0xff;
wolfSSL 0:d92f9d21154c 106 p[4] = (v >> 32) & 0xff;
wolfSSL 0:d92f9d21154c 107 p[5] = (v >> 40) & 0xff;
wolfSSL 0:d92f9d21154c 108 p[6] = (v >> 48) & 0xff;
wolfSSL 0:d92f9d21154c 109 p[7] = (v >> 56) & 0xff;
wolfSSL 0:d92f9d21154c 110 }
wolfSSL 0:d92f9d21154c 111
wolfSSL 0:d92f9d21154c 112 #else /* if not 64 bit then use 32 bit */
wolfSSL 0:d92f9d21154c 113
wolfSSL 0:d92f9d21154c 114 static word32 U8TO32(const byte *p) {
wolfSSL 0:d92f9d21154c 115 return
wolfSSL 0:d92f9d21154c 116 (((word32)(p[0] & 0xff) ) |
wolfSSL 0:d92f9d21154c 117 ((word32)(p[1] & 0xff) << 8) |
wolfSSL 0:d92f9d21154c 118 ((word32)(p[2] & 0xff) << 16) |
wolfSSL 0:d92f9d21154c 119 ((word32)(p[3] & 0xff) << 24));
wolfSSL 0:d92f9d21154c 120 }
wolfSSL 0:d92f9d21154c 121
wolfSSL 0:d92f9d21154c 122 static void U32TO8(byte *p, word32 v) {
wolfSSL 0:d92f9d21154c 123 p[0] = (v ) & 0xff;
wolfSSL 0:d92f9d21154c 124 p[1] = (v >> 8) & 0xff;
wolfSSL 0:d92f9d21154c 125 p[2] = (v >> 16) & 0xff;
wolfSSL 0:d92f9d21154c 126 p[3] = (v >> 24) & 0xff;
wolfSSL 0:d92f9d21154c 127 }
wolfSSL 0:d92f9d21154c 128 #endif
wolfSSL 0:d92f9d21154c 129
wolfSSL 0:d92f9d21154c 130 static void poly1305_blocks(Poly1305* ctx, const unsigned char *m,
wolfSSL 0:d92f9d21154c 131 size_t bytes) {
wolfSSL 0:d92f9d21154c 132
wolfSSL 0:d92f9d21154c 133 #ifdef POLY130564
wolfSSL 0:d92f9d21154c 134
wolfSSL 0:d92f9d21154c 135 const word64 hibit = (ctx->final) ? 0 : ((word64)1 << 40); /* 1 << 128 */
wolfSSL 0:d92f9d21154c 136 word64 r0,r1,r2;
wolfSSL 0:d92f9d21154c 137 word64 s1,s2;
wolfSSL 0:d92f9d21154c 138 word64 h0,h1,h2;
wolfSSL 0:d92f9d21154c 139 word64 c;
wolfSSL 0:d92f9d21154c 140 word128 d0,d1,d2,d;
wolfSSL 0:d92f9d21154c 141
wolfSSL 0:d92f9d21154c 142 #else
wolfSSL 0:d92f9d21154c 143
wolfSSL 0:d92f9d21154c 144 const word32 hibit = (ctx->final) ? 0 : (1 << 24); /* 1 << 128 */
wolfSSL 0:d92f9d21154c 145 word32 r0,r1,r2,r3,r4;
wolfSSL 0:d92f9d21154c 146 word32 s1,s2,s3,s4;
wolfSSL 0:d92f9d21154c 147 word32 h0,h1,h2,h3,h4;
wolfSSL 0:d92f9d21154c 148 word64 d0,d1,d2,d3,d4;
wolfSSL 0:d92f9d21154c 149 word32 c;
wolfSSL 0:d92f9d21154c 150
wolfSSL 0:d92f9d21154c 151 #endif
wolfSSL 0:d92f9d21154c 152
wolfSSL 0:d92f9d21154c 153 #ifdef POLY130564
wolfSSL 0:d92f9d21154c 154
wolfSSL 0:d92f9d21154c 155 r0 = ctx->r[0];
wolfSSL 0:d92f9d21154c 156 r1 = ctx->r[1];
wolfSSL 0:d92f9d21154c 157 r2 = ctx->r[2];
wolfSSL 0:d92f9d21154c 158
wolfSSL 0:d92f9d21154c 159 h0 = ctx->h[0];
wolfSSL 0:d92f9d21154c 160 h1 = ctx->h[1];
wolfSSL 0:d92f9d21154c 161 h2 = ctx->h[2];
wolfSSL 0:d92f9d21154c 162
wolfSSL 0:d92f9d21154c 163 s1 = r1 * (5 << 2);
wolfSSL 0:d92f9d21154c 164 s2 = r2 * (5 << 2);
wolfSSL 0:d92f9d21154c 165
wolfSSL 0:d92f9d21154c 166 while (bytes >= POLY1305_BLOCK_SIZE) {
wolfSSL 0:d92f9d21154c 167 word64 t0,t1;
wolfSSL 0:d92f9d21154c 168
wolfSSL 0:d92f9d21154c 169 /* h += m[i] */
wolfSSL 0:d92f9d21154c 170 t0 = U8TO64(&m[0]);
wolfSSL 0:d92f9d21154c 171 t1 = U8TO64(&m[8]);
wolfSSL 0:d92f9d21154c 172
wolfSSL 0:d92f9d21154c 173 h0 += (( t0 ) & 0xfffffffffff);
wolfSSL 0:d92f9d21154c 174 h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
wolfSSL 0:d92f9d21154c 175 h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit;
wolfSSL 0:d92f9d21154c 176
wolfSSL 0:d92f9d21154c 177 /* h *= r */
wolfSSL 0:d92f9d21154c 178 MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d);
wolfSSL 0:d92f9d21154c 179 MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d);
wolfSSL 0:d92f9d21154c 180 MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d);
wolfSSL 0:d92f9d21154c 181
wolfSSL 0:d92f9d21154c 182 /* (partial) h %= p */
wolfSSL 0:d92f9d21154c 183 c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff;
wolfSSL 0:d92f9d21154c 184 ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff;
wolfSSL 0:d92f9d21154c 185 ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff;
wolfSSL 0:d92f9d21154c 186 h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff;
wolfSSL 0:d92f9d21154c 187 h1 += c;
wolfSSL 0:d92f9d21154c 188
wolfSSL 0:d92f9d21154c 189 m += POLY1305_BLOCK_SIZE;
wolfSSL 0:d92f9d21154c 190 bytes -= POLY1305_BLOCK_SIZE;
wolfSSL 0:d92f9d21154c 191 }
wolfSSL 0:d92f9d21154c 192
wolfSSL 0:d92f9d21154c 193 ctx->h[0] = h0;
wolfSSL 0:d92f9d21154c 194 ctx->h[1] = h1;
wolfSSL 0:d92f9d21154c 195 ctx->h[2] = h2;
wolfSSL 0:d92f9d21154c 196
wolfSSL 0:d92f9d21154c 197 #else /* if not 64 bit then use 32 bit */
wolfSSL 0:d92f9d21154c 198
wolfSSL 0:d92f9d21154c 199 r0 = ctx->r[0];
wolfSSL 0:d92f9d21154c 200 r1 = ctx->r[1];
wolfSSL 0:d92f9d21154c 201 r2 = ctx->r[2];
wolfSSL 0:d92f9d21154c 202 r3 = ctx->r[3];
wolfSSL 0:d92f9d21154c 203 r4 = ctx->r[4];
wolfSSL 0:d92f9d21154c 204
wolfSSL 0:d92f9d21154c 205 s1 = r1 * 5;
wolfSSL 0:d92f9d21154c 206 s2 = r2 * 5;
wolfSSL 0:d92f9d21154c 207 s3 = r3 * 5;
wolfSSL 0:d92f9d21154c 208 s4 = r4 * 5;
wolfSSL 0:d92f9d21154c 209
wolfSSL 0:d92f9d21154c 210 h0 = ctx->h[0];
wolfSSL 0:d92f9d21154c 211 h1 = ctx->h[1];
wolfSSL 0:d92f9d21154c 212 h2 = ctx->h[2];
wolfSSL 0:d92f9d21154c 213 h3 = ctx->h[3];
wolfSSL 0:d92f9d21154c 214 h4 = ctx->h[4];
wolfSSL 0:d92f9d21154c 215
wolfSSL 0:d92f9d21154c 216 while (bytes >= POLY1305_BLOCK_SIZE) {
wolfSSL 0:d92f9d21154c 217 /* h += m[i] */
wolfSSL 0:d92f9d21154c 218 h0 += (U8TO32(m+ 0) ) & 0x3ffffff;
wolfSSL 0:d92f9d21154c 219 h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff;
wolfSSL 0:d92f9d21154c 220 h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff;
wolfSSL 0:d92f9d21154c 221 h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff;
wolfSSL 0:d92f9d21154c 222 h4 += (U8TO32(m+12) >> 8) | hibit;
wolfSSL 0:d92f9d21154c 223
wolfSSL 0:d92f9d21154c 224 /* h *= r */
wolfSSL 0:d92f9d21154c 225 d0 = ((word64)h0 * r0) + ((word64)h1 * s4) + ((word64)h2 * s3) +
wolfSSL 0:d92f9d21154c 226 ((word64)h3 * s2) + ((word64)h4 * s1);
wolfSSL 0:d92f9d21154c 227 d1 = ((word64)h0 * r1) + ((word64)h1 * r0) + ((word64)h2 * s4) +
wolfSSL 0:d92f9d21154c 228 ((word64)h3 * s3) + ((word64)h4 * s2);
wolfSSL 0:d92f9d21154c 229 d2 = ((word64)h0 * r2) + ((word64)h1 * r1) + ((word64)h2 * r0) +
wolfSSL 0:d92f9d21154c 230 ((word64)h3 * s4) + ((word64)h4 * s3);
wolfSSL 0:d92f9d21154c 231 d3 = ((word64)h0 * r3) + ((word64)h1 * r2) + ((word64)h2 * r1) +
wolfSSL 0:d92f9d21154c 232 ((word64)h3 * r0) + ((word64)h4 * s4);
wolfSSL 0:d92f9d21154c 233 d4 = ((word64)h0 * r4) + ((word64)h1 * r3) + ((word64)h2 * r2) +
wolfSSL 0:d92f9d21154c 234 ((word64)h3 * r1) + ((word64)h4 * r0);
wolfSSL 0:d92f9d21154c 235
wolfSSL 0:d92f9d21154c 236 /* (partial) h %= p */
wolfSSL 0:d92f9d21154c 237 c = (word32)(d0 >> 26); h0 = (word32)d0 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 238 d1 += c; c = (word32)(d1 >> 26); h1 = (word32)d1 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 239 d2 += c; c = (word32)(d2 >> 26); h2 = (word32)d2 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 240 d3 += c; c = (word32)(d3 >> 26); h3 = (word32)d3 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 241 d4 += c; c = (word32)(d4 >> 26); h4 = (word32)d4 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 242 h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 243 h1 += c;
wolfSSL 0:d92f9d21154c 244
wolfSSL 0:d92f9d21154c 245 m += POLY1305_BLOCK_SIZE;
wolfSSL 0:d92f9d21154c 246 bytes -= POLY1305_BLOCK_SIZE;
wolfSSL 0:d92f9d21154c 247 }
wolfSSL 0:d92f9d21154c 248
wolfSSL 0:d92f9d21154c 249 ctx->h[0] = h0;
wolfSSL 0:d92f9d21154c 250 ctx->h[1] = h1;
wolfSSL 0:d92f9d21154c 251 ctx->h[2] = h2;
wolfSSL 0:d92f9d21154c 252 ctx->h[3] = h3;
wolfSSL 0:d92f9d21154c 253 ctx->h[4] = h4;
wolfSSL 0:d92f9d21154c 254
wolfSSL 0:d92f9d21154c 255 #endif /* end of 64 bit cpu blocks or 32 bit cpu */
wolfSSL 0:d92f9d21154c 256 }
wolfSSL 0:d92f9d21154c 257
wolfSSL 0:d92f9d21154c 258
wolfSSL 0:d92f9d21154c 259 int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) {
wolfSSL 0:d92f9d21154c 260
wolfSSL 0:d92f9d21154c 261 #if defined(POLY130564)
wolfSSL 0:d92f9d21154c 262 word64 t0,t1;
wolfSSL 0:d92f9d21154c 263 #endif
wolfSSL 0:d92f9d21154c 264
wolfSSL 0:d92f9d21154c 265 #ifdef CHACHA_AEAD_TEST
wolfSSL 0:d92f9d21154c 266 word32 k;
wolfSSL 0:d92f9d21154c 267 printf("Poly key used:\n");
wolfSSL 0:d92f9d21154c 268 for (k = 0; k < keySz; k++) {
wolfSSL 0:d92f9d21154c 269 printf("%02x", key[k]);
wolfSSL 0:d92f9d21154c 270 if ((k+1) % 8 == 0)
wolfSSL 0:d92f9d21154c 271 printf("\n");
wolfSSL 0:d92f9d21154c 272 }
wolfSSL 0:d92f9d21154c 273 printf("\n");
wolfSSL 0:d92f9d21154c 274 #endif
wolfSSL 0:d92f9d21154c 275
wolfSSL 0:d92f9d21154c 276 if (keySz != 32 || ctx == NULL)
wolfSSL 0:d92f9d21154c 277 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 278
wolfSSL 0:d92f9d21154c 279 #if defined(POLY130564)
wolfSSL 0:d92f9d21154c 280
wolfSSL 0:d92f9d21154c 281 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
wolfSSL 0:d92f9d21154c 282 t0 = U8TO64(key + 0);
wolfSSL 0:d92f9d21154c 283 t1 = U8TO64(key + 8);
wolfSSL 0:d92f9d21154c 284
wolfSSL 0:d92f9d21154c 285 ctx->r[0] = ( t0 ) & 0xffc0fffffff;
wolfSSL 0:d92f9d21154c 286 ctx->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
wolfSSL 0:d92f9d21154c 287 ctx->r[2] = ((t1 >> 24) ) & 0x00ffffffc0f;
wolfSSL 0:d92f9d21154c 288
wolfSSL 0:d92f9d21154c 289 /* h (accumulator) = 0 */
wolfSSL 0:d92f9d21154c 290 ctx->h[0] = 0;
wolfSSL 0:d92f9d21154c 291 ctx->h[1] = 0;
wolfSSL 0:d92f9d21154c 292 ctx->h[2] = 0;
wolfSSL 0:d92f9d21154c 293
wolfSSL 0:d92f9d21154c 294 /* save pad for later */
wolfSSL 0:d92f9d21154c 295 ctx->pad[0] = U8TO64(key + 16);
wolfSSL 0:d92f9d21154c 296 ctx->pad[1] = U8TO64(key + 24);
wolfSSL 0:d92f9d21154c 297
wolfSSL 0:d92f9d21154c 298 #else /* if not 64 bit then use 32 bit */
wolfSSL 0:d92f9d21154c 299
wolfSSL 0:d92f9d21154c 300 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
wolfSSL 0:d92f9d21154c 301 ctx->r[0] = (U8TO32(key + 0) ) & 0x3ffffff;
wolfSSL 0:d92f9d21154c 302 ctx->r[1] = (U8TO32(key + 3) >> 2) & 0x3ffff03;
wolfSSL 0:d92f9d21154c 303 ctx->r[2] = (U8TO32(key + 6) >> 4) & 0x3ffc0ff;
wolfSSL 0:d92f9d21154c 304 ctx->r[3] = (U8TO32(key + 9) >> 6) & 0x3f03fff;
wolfSSL 0:d92f9d21154c 305 ctx->r[4] = (U8TO32(key + 12) >> 8) & 0x00fffff;
wolfSSL 0:d92f9d21154c 306
wolfSSL 0:d92f9d21154c 307 /* h = 0 */
wolfSSL 0:d92f9d21154c 308 ctx->h[0] = 0;
wolfSSL 0:d92f9d21154c 309 ctx->h[1] = 0;
wolfSSL 0:d92f9d21154c 310 ctx->h[2] = 0;
wolfSSL 0:d92f9d21154c 311 ctx->h[3] = 0;
wolfSSL 0:d92f9d21154c 312 ctx->h[4] = 0;
wolfSSL 0:d92f9d21154c 313
wolfSSL 0:d92f9d21154c 314 /* save pad for later */
wolfSSL 0:d92f9d21154c 315 ctx->pad[0] = U8TO32(key + 16);
wolfSSL 0:d92f9d21154c 316 ctx->pad[1] = U8TO32(key + 20);
wolfSSL 0:d92f9d21154c 317 ctx->pad[2] = U8TO32(key + 24);
wolfSSL 0:d92f9d21154c 318 ctx->pad[3] = U8TO32(key + 28);
wolfSSL 0:d92f9d21154c 319
wolfSSL 0:d92f9d21154c 320 #endif
wolfSSL 0:d92f9d21154c 321
wolfSSL 0:d92f9d21154c 322 ctx->leftover = 0;
wolfSSL 0:d92f9d21154c 323 ctx->final = 0;
wolfSSL 0:d92f9d21154c 324
wolfSSL 0:d92f9d21154c 325 return 0;
wolfSSL 0:d92f9d21154c 326 }
wolfSSL 0:d92f9d21154c 327
wolfSSL 0:d92f9d21154c 328
wolfSSL 0:d92f9d21154c 329 int wc_Poly1305Final(Poly1305* ctx, byte* mac) {
wolfSSL 0:d92f9d21154c 330
wolfSSL 0:d92f9d21154c 331 #if defined(POLY130564)
wolfSSL 0:d92f9d21154c 332
wolfSSL 0:d92f9d21154c 333 word64 h0,h1,h2,c;
wolfSSL 0:d92f9d21154c 334 word64 g0,g1,g2;
wolfSSL 0:d92f9d21154c 335 word64 t0,t1;
wolfSSL 0:d92f9d21154c 336
wolfSSL 0:d92f9d21154c 337 #else
wolfSSL 0:d92f9d21154c 338
wolfSSL 0:d92f9d21154c 339 word32 h0,h1,h2,h3,h4,c;
wolfSSL 0:d92f9d21154c 340 word32 g0,g1,g2,g3,g4;
wolfSSL 0:d92f9d21154c 341 word64 f;
wolfSSL 0:d92f9d21154c 342 word32 mask;
wolfSSL 0:d92f9d21154c 343
wolfSSL 0:d92f9d21154c 344 #endif
wolfSSL 0:d92f9d21154c 345
wolfSSL 0:d92f9d21154c 346 if (ctx == NULL)
wolfSSL 0:d92f9d21154c 347 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 348
wolfSSL 0:d92f9d21154c 349 #if defined(POLY130564)
wolfSSL 0:d92f9d21154c 350
wolfSSL 0:d92f9d21154c 351 /* process the remaining block */
wolfSSL 0:d92f9d21154c 352 if (ctx->leftover) {
wolfSSL 0:d92f9d21154c 353 size_t i = ctx->leftover;
wolfSSL 0:d92f9d21154c 354 ctx->buffer[i] = 1;
wolfSSL 0:d92f9d21154c 355 for (i = i + 1; i < POLY1305_BLOCK_SIZE; i++)
wolfSSL 0:d92f9d21154c 356 ctx->buffer[i] = 0;
wolfSSL 0:d92f9d21154c 357 ctx->final = 1;
wolfSSL 0:d92f9d21154c 358 poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE);
wolfSSL 0:d92f9d21154c 359 }
wolfSSL 0:d92f9d21154c 360
wolfSSL 0:d92f9d21154c 361 /* fully carry h */
wolfSSL 0:d92f9d21154c 362 h0 = ctx->h[0];
wolfSSL 0:d92f9d21154c 363 h1 = ctx->h[1];
wolfSSL 0:d92f9d21154c 364 h2 = ctx->h[2];
wolfSSL 0:d92f9d21154c 365
wolfSSL 0:d92f9d21154c 366 c = (h1 >> 44); h1 &= 0xfffffffffff;
wolfSSL 0:d92f9d21154c 367 h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
wolfSSL 0:d92f9d21154c 368 h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
wolfSSL 0:d92f9d21154c 369 h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff;
wolfSSL 0:d92f9d21154c 370 h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
wolfSSL 0:d92f9d21154c 371 h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
wolfSSL 0:d92f9d21154c 372 h1 += c;
wolfSSL 0:d92f9d21154c 373
wolfSSL 0:d92f9d21154c 374 /* compute h + -p */
wolfSSL 0:d92f9d21154c 375 g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
wolfSSL 0:d92f9d21154c 376 g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
wolfSSL 0:d92f9d21154c 377 g2 = h2 + c - ((word64)1 << 42);
wolfSSL 0:d92f9d21154c 378
wolfSSL 0:d92f9d21154c 379 /* select h if h < p, or h + -p if h >= p */
wolfSSL 0:d92f9d21154c 380 c = (g2 >> ((sizeof(word64) * 8) - 1)) - 1;
wolfSSL 0:d92f9d21154c 381 g0 &= c;
wolfSSL 0:d92f9d21154c 382 g1 &= c;
wolfSSL 0:d92f9d21154c 383 g2 &= c;
wolfSSL 0:d92f9d21154c 384 c = ~c;
wolfSSL 0:d92f9d21154c 385 h0 = (h0 & c) | g0;
wolfSSL 0:d92f9d21154c 386 h1 = (h1 & c) | g1;
wolfSSL 0:d92f9d21154c 387 h2 = (h2 & c) | g2;
wolfSSL 0:d92f9d21154c 388
wolfSSL 0:d92f9d21154c 389 /* h = (h + pad) */
wolfSSL 0:d92f9d21154c 390 t0 = ctx->pad[0];
wolfSSL 0:d92f9d21154c 391 t1 = ctx->pad[1];
wolfSSL 0:d92f9d21154c 392
wolfSSL 0:d92f9d21154c 393 h0 += (( t0 ) & 0xfffffffffff) ;
wolfSSL 0:d92f9d21154c 394 c = (h0 >> 44); h0 &= 0xfffffffffff;
wolfSSL 0:d92f9d21154c 395 h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
wolfSSL 0:d92f9d21154c 396 c = (h1 >> 44); h1 &= 0xfffffffffff;
wolfSSL 0:d92f9d21154c 397 h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c;
wolfSSL 0:d92f9d21154c 398 h2 &= 0x3ffffffffff;
wolfSSL 0:d92f9d21154c 399
wolfSSL 0:d92f9d21154c 400 /* mac = h % (2^128) */
wolfSSL 0:d92f9d21154c 401 h0 = ((h0 ) | (h1 << 44));
wolfSSL 0:d92f9d21154c 402 h1 = ((h1 >> 20) | (h2 << 24));
wolfSSL 0:d92f9d21154c 403
wolfSSL 0:d92f9d21154c 404 U64TO8(mac + 0, h0);
wolfSSL 0:d92f9d21154c 405 U64TO8(mac + 8, h1);
wolfSSL 0:d92f9d21154c 406
wolfSSL 0:d92f9d21154c 407 /* zero out the state */
wolfSSL 0:d92f9d21154c 408 ctx->h[0] = 0;
wolfSSL 0:d92f9d21154c 409 ctx->h[1] = 0;
wolfSSL 0:d92f9d21154c 410 ctx->h[2] = 0;
wolfSSL 0:d92f9d21154c 411 ctx->r[0] = 0;
wolfSSL 0:d92f9d21154c 412 ctx->r[1] = 0;
wolfSSL 0:d92f9d21154c 413 ctx->r[2] = 0;
wolfSSL 0:d92f9d21154c 414 ctx->pad[0] = 0;
wolfSSL 0:d92f9d21154c 415 ctx->pad[1] = 0;
wolfSSL 0:d92f9d21154c 416
wolfSSL 0:d92f9d21154c 417 #else /* if not 64 bit then use 32 bit */
wolfSSL 0:d92f9d21154c 418
wolfSSL 0:d92f9d21154c 419 /* process the remaining block */
wolfSSL 0:d92f9d21154c 420 if (ctx->leftover) {
wolfSSL 0:d92f9d21154c 421 size_t i = ctx->leftover;
wolfSSL 0:d92f9d21154c 422 ctx->buffer[i++] = 1;
wolfSSL 0:d92f9d21154c 423 for (; i < POLY1305_BLOCK_SIZE; i++)
wolfSSL 0:d92f9d21154c 424 ctx->buffer[i] = 0;
wolfSSL 0:d92f9d21154c 425 ctx->final = 1;
wolfSSL 0:d92f9d21154c 426 poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE);
wolfSSL 0:d92f9d21154c 427 }
wolfSSL 0:d92f9d21154c 428
wolfSSL 0:d92f9d21154c 429 /* fully carry h */
wolfSSL 0:d92f9d21154c 430 h0 = ctx->h[0];
wolfSSL 0:d92f9d21154c 431 h1 = ctx->h[1];
wolfSSL 0:d92f9d21154c 432 h2 = ctx->h[2];
wolfSSL 0:d92f9d21154c 433 h3 = ctx->h[3];
wolfSSL 0:d92f9d21154c 434 h4 = ctx->h[4];
wolfSSL 0:d92f9d21154c 435
wolfSSL 0:d92f9d21154c 436 c = h1 >> 26; h1 = h1 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 437 h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 438 h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 439 h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 440 h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
wolfSSL 0:d92f9d21154c 441 h1 += c;
wolfSSL 0:d92f9d21154c 442
wolfSSL 0:d92f9d21154c 443 /* compute h + -p */
wolfSSL 0:d92f9d21154c 444 g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
wolfSSL 0:d92f9d21154c 445 g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
wolfSSL 0:d92f9d21154c 446 g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
wolfSSL 0:d92f9d21154c 447 g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
wolfSSL 0:d92f9d21154c 448 g4 = h4 + c - (1 << 26);
wolfSSL 0:d92f9d21154c 449
wolfSSL 0:d92f9d21154c 450 /* select h if h < p, or h + -p if h >= p */
wolfSSL 0:d92f9d21154c 451 mask = (g4 >> ((sizeof(word32) * 8) - 1)) - 1;
wolfSSL 0:d92f9d21154c 452 g0 &= mask;
wolfSSL 0:d92f9d21154c 453 g1 &= mask;
wolfSSL 0:d92f9d21154c 454 g2 &= mask;
wolfSSL 0:d92f9d21154c 455 g3 &= mask;
wolfSSL 0:d92f9d21154c 456 g4 &= mask;
wolfSSL 0:d92f9d21154c 457 mask = ~mask;
wolfSSL 0:d92f9d21154c 458 h0 = (h0 & mask) | g0;
wolfSSL 0:d92f9d21154c 459 h1 = (h1 & mask) | g1;
wolfSSL 0:d92f9d21154c 460 h2 = (h2 & mask) | g2;
wolfSSL 0:d92f9d21154c 461 h3 = (h3 & mask) | g3;
wolfSSL 0:d92f9d21154c 462 h4 = (h4 & mask) | g4;
wolfSSL 0:d92f9d21154c 463
wolfSSL 0:d92f9d21154c 464 /* h = h % (2^128) */
wolfSSL 0:d92f9d21154c 465 h0 = ((h0 ) | (h1 << 26)) & 0xffffffff;
wolfSSL 0:d92f9d21154c 466 h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
wolfSSL 0:d92f9d21154c 467 h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
wolfSSL 0:d92f9d21154c 468 h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
wolfSSL 0:d92f9d21154c 469
wolfSSL 0:d92f9d21154c 470 /* mac = (h + pad) % (2^128) */
wolfSSL 0:d92f9d21154c 471 f = (word64)h0 + ctx->pad[0] ; h0 = (word32)f;
wolfSSL 0:d92f9d21154c 472 f = (word64)h1 + ctx->pad[1] + (f >> 32); h1 = (word32)f;
wolfSSL 0:d92f9d21154c 473 f = (word64)h2 + ctx->pad[2] + (f >> 32); h2 = (word32)f;
wolfSSL 0:d92f9d21154c 474 f = (word64)h3 + ctx->pad[3] + (f >> 32); h3 = (word32)f;
wolfSSL 0:d92f9d21154c 475
wolfSSL 0:d92f9d21154c 476 U32TO8(mac + 0, h0);
wolfSSL 0:d92f9d21154c 477 U32TO8(mac + 4, h1);
wolfSSL 0:d92f9d21154c 478 U32TO8(mac + 8, h2);
wolfSSL 0:d92f9d21154c 479 U32TO8(mac + 12, h3);
wolfSSL 0:d92f9d21154c 480
wolfSSL 0:d92f9d21154c 481 /* zero out the state */
wolfSSL 0:d92f9d21154c 482 ctx->h[0] = 0;
wolfSSL 0:d92f9d21154c 483 ctx->h[1] = 0;
wolfSSL 0:d92f9d21154c 484 ctx->h[2] = 0;
wolfSSL 0:d92f9d21154c 485 ctx->h[3] = 0;
wolfSSL 0:d92f9d21154c 486 ctx->h[4] = 0;
wolfSSL 0:d92f9d21154c 487 ctx->r[0] = 0;
wolfSSL 0:d92f9d21154c 488 ctx->r[1] = 0;
wolfSSL 0:d92f9d21154c 489 ctx->r[2] = 0;
wolfSSL 0:d92f9d21154c 490 ctx->r[3] = 0;
wolfSSL 0:d92f9d21154c 491 ctx->r[4] = 0;
wolfSSL 0:d92f9d21154c 492 ctx->pad[0] = 0;
wolfSSL 0:d92f9d21154c 493 ctx->pad[1] = 0;
wolfSSL 0:d92f9d21154c 494 ctx->pad[2] = 0;
wolfSSL 0:d92f9d21154c 495 ctx->pad[3] = 0;
wolfSSL 0:d92f9d21154c 496
wolfSSL 0:d92f9d21154c 497 #endif
wolfSSL 0:d92f9d21154c 498
wolfSSL 0:d92f9d21154c 499 return 0;
wolfSSL 0:d92f9d21154c 500 }
wolfSSL 0:d92f9d21154c 501
wolfSSL 0:d92f9d21154c 502
wolfSSL 0:d92f9d21154c 503 int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) {
wolfSSL 0:d92f9d21154c 504
wolfSSL 0:d92f9d21154c 505 size_t i;
wolfSSL 0:d92f9d21154c 506
wolfSSL 0:d92f9d21154c 507 #ifdef CHACHA_AEAD_TEST
wolfSSL 0:d92f9d21154c 508 word32 k;
wolfSSL 0:d92f9d21154c 509 printf("Raw input to poly:\n");
wolfSSL 0:d92f9d21154c 510 for (k = 0; k < bytes; k++) {
wolfSSL 0:d92f9d21154c 511 printf("%02x", m[k]);
wolfSSL 0:d92f9d21154c 512 if ((k+1) % 16 == 0)
wolfSSL 0:d92f9d21154c 513 printf("\n");
wolfSSL 0:d92f9d21154c 514 }
wolfSSL 0:d92f9d21154c 515 printf("\n");
wolfSSL 0:d92f9d21154c 516 #endif
wolfSSL 0:d92f9d21154c 517
wolfSSL 0:d92f9d21154c 518 if (ctx == NULL)
wolfSSL 0:d92f9d21154c 519 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 520
wolfSSL 0:d92f9d21154c 521 /* handle leftover */
wolfSSL 0:d92f9d21154c 522 if (ctx->leftover) {
wolfSSL 0:d92f9d21154c 523 size_t want = (POLY1305_BLOCK_SIZE - ctx->leftover);
wolfSSL 0:d92f9d21154c 524 if (want > bytes)
wolfSSL 0:d92f9d21154c 525 want = bytes;
wolfSSL 0:d92f9d21154c 526 for (i = 0; i < want; i++)
wolfSSL 0:d92f9d21154c 527 ctx->buffer[ctx->leftover + i] = m[i];
wolfSSL 0:d92f9d21154c 528 bytes -= want;
wolfSSL 0:d92f9d21154c 529 m += want;
wolfSSL 0:d92f9d21154c 530 ctx->leftover += want;
wolfSSL 0:d92f9d21154c 531 if (ctx->leftover < POLY1305_BLOCK_SIZE)
wolfSSL 0:d92f9d21154c 532 return 0;
wolfSSL 0:d92f9d21154c 533 poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE);
wolfSSL 0:d92f9d21154c 534 ctx->leftover = 0;
wolfSSL 0:d92f9d21154c 535 }
wolfSSL 0:d92f9d21154c 536
wolfSSL 0:d92f9d21154c 537 /* process full blocks */
wolfSSL 0:d92f9d21154c 538 if (bytes >= POLY1305_BLOCK_SIZE) {
wolfSSL 0:d92f9d21154c 539 size_t want = (bytes & ~(POLY1305_BLOCK_SIZE - 1));
wolfSSL 0:d92f9d21154c 540 poly1305_blocks(ctx, m, want);
wolfSSL 0:d92f9d21154c 541 m += want;
wolfSSL 0:d92f9d21154c 542 bytes -= want;
wolfSSL 0:d92f9d21154c 543 }
wolfSSL 0:d92f9d21154c 544
wolfSSL 0:d92f9d21154c 545 /* store leftover */
wolfSSL 0:d92f9d21154c 546 if (bytes) {
wolfSSL 0:d92f9d21154c 547 for (i = 0; i < bytes; i++)
wolfSSL 0:d92f9d21154c 548 ctx->buffer[ctx->leftover + i] = m[i];
wolfSSL 0:d92f9d21154c 549 ctx->leftover += bytes;
wolfSSL 0:d92f9d21154c 550 }
wolfSSL 0:d92f9d21154c 551 return 0;
wolfSSL 0:d92f9d21154c 552 }
wolfSSL 0:d92f9d21154c 553 #endif /* HAVE_POLY1305 */
wolfSSL 0:d92f9d21154c 554
wolfSSL 0:d92f9d21154c 555