Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-fastmath/wolfcrypt/src/poly1305.c
Line
Count
Source
1
/* poly1305.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
/*
22
23
DESCRIPTION
24
This library contains implementation for the Poly1305 authenticator.
25
26
Based off the public domain implementations by Andrew Moon
27
and Daniel J. Bernstein
28
29
*/
30
31
32
/*
33
 * WOLFSSL_W64_WRAPPER Uses wrappers around word64 types for a system that does
34
 *                     not have word64 available. As expected it reduces
35
 *                     performance. Benchmarks collected July 2024 show
36
 *                     303.004 MiB/s with and 1874.194 MiB/s without.
37
 */
38
39
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
40
41
/*
42
 * Poly1305 Build Options:
43
 *
44
 * HAVE_POLY1305:            Enable Poly1305 authenticator          default: off
45
 * POLY130564:               Use 64-bit Poly1305 implementation    default: auto
46
 * USE_INTEL_POLY1305_SPEEDUP: Intel AVX/AVX2 Poly1305 accel      default: off
47
 */
48
49
#ifdef HAVE_POLY1305
50
#include <wolfssl/wolfcrypt/poly1305.h>
51
#include <wolfssl/wolfcrypt/cpuid.h>
52
#ifdef NO_INLINE
53
    #include <wolfssl/wolfcrypt/misc.h>
54
#else
55
    #define WOLFSSL_MISC_INCLUDED
56
    #include <wolfcrypt/src/misc.c>
57
#endif
58
#ifdef CHACHA_AEAD_TEST
59
    #include <stdio.h>
60
#endif
61
62
#ifdef _MSC_VER
63
    /* 4127 warning constant while(1)  */
64
    #pragma warning(disable: 4127)
65
#endif
66
67
#ifdef USE_INTEL_POLY1305_SPEEDUP
68
    #include <emmintrin.h>
69
    #include <immintrin.h>
70
71
    #if defined(__GNUC__) && ((__GNUC__ < 4) || \
72
                              (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
73
        #undef  NO_AVX2_SUPPORT
74
        #define NO_AVX2_SUPPORT
75
    #endif
76
    #if defined(__clang__) && ((__clang_major__ < 3) || \
77
                               (__clang_major__ == 3 && __clang_minor__ <= 5))
78
        #define NO_AVX2_SUPPORT
79
    #elif defined(__clang__) && defined(NO_AVX2_SUPPORT)
80
        #undef NO_AVX2_SUPPORT
81
    #endif
82
    #if defined(_MSC_VER) && (_MSC_VER <= 1900)
83
        #undef  NO_AVX2_SUPPORT
84
        #define NO_AVX2_SUPPORT
85
    #endif
86
87
    #define HAVE_INTEL_AVX1
88
    #ifndef NO_AVX2_SUPPORT
89
        #define HAVE_INTEL_AVX2
90
    #endif
91
    /* 8-way path; the struct carries r^5..r^8 only when this is on. */
92
    #if defined(WOLFSSL_POLY1305_AVX512) && !defined(NO_AVX512_SUPPORT)
93
        #define HAVE_INTEL_AVX512
94
    #endif
95
#endif
96
97
#ifdef USE_INTEL_POLY1305_SPEEDUP
98
static cpuid_flags_t intel_flags = WC_CPUID_INITIALIZER;
99
100
/* The fused ChaCha20-Poly1305 kernel drives the 4-way path; when it is active
101
 * this flag pins Update/Final to the 4-way path so the state layout matches. */
102
#ifdef WOLFSSL_CHACHA20_POLY1305_FUSED
103
    #define POLY1305_FORCE_AVX2(ctx) ((ctx)->forceAvx2 != 0)
104
#else
105
    #define POLY1305_FORCE_AVX2(ctx) 0
106
#endif
107
108
/* The fused IFMA stitch drives the scalar path; when it is active this flag
109
 * pins Update/Final to the scalar (poly1305_blocks_avx / _final_avx) path so
110
 * the state layout matches. */
111
#ifdef WOLFSSL_CHACHA20_POLY1305_FUSED_IFMA
112
    #define POLY1305_FORCE_SCALAR(ctx) ((ctx)->forceScalar != 0)
113
#else
114
    #define POLY1305_FORCE_SCALAR(ctx) 0
115
#endif
116
117
#ifdef HAVE_INTEL_AVX512
118
/* Whether to use the 8-way (512-bit) Poly1305 over the 4-way AVX2 path.
119
 *
120
 * The zmm path does eight 16-byte blocks per iteration and is the fastest
121
 * option where 512-bit code runs at full clock: AMD Zen 4/5 (no AVX-512
122
 * license) and Intel Ice Lake and later.  On Intel Skylake-SP / Cascade
123
 * Lake-class parts, sustained 512-bit instructions trip the AVX-512 frequency
124
 * license and downclock the core; the penalty is milder here than for the
125
 * FP-heavy ChaCha, but the 256-bit AVX2 path can still be the safer default on
126
 * those parts.  As with the ChaCha gate, VAES presence is used as a
127
 * generational proxy: the throttling parts predate VAES, whereas every
128
 * microarchitecture that runs 512-bit without penalty implements it.  A missing
129
 * VAES only costs a little throughput (fall back to AVX2), never correctness.
130
 *
131
 * Override the heuristic with:
132
 *   WOLFSSL_POLY1305_AVX512_ALWAYS - use zmm whenever AVX-512 is present
133
 *   WOLFSSL_POLY1305_AVX512_NEVER  - never use zmm (always AVX2 or below)
134
 */
135
static WC_INLINE int poly1305_use_avx512(cpuid_flags_t flags)
136
{
137
#if defined(WOLFSSL_POLY1305_AVX512_NEVER)
138
    (void)flags;
139
    return 0;
140
#elif defined(WOLFSSL_POLY1305_AVX512_ALWAYS)
141
    return IS_INTEL_AVX512(flags) != 0;
142
#else
143
    return (IS_INTEL_AVX512(flags) != 0) && (IS_INTEL_VAES(flags) != 0);
144
#endif
145
}
146
147
/* The radix-2^44 IFMA path is preferred on Intel cores with AVX-512 IFMA
148
 * (Ice Lake and later), where it beats the 26-bit vpmuludq 8-way.  On AMD
149
 * Zen 4/5 - which also implement IFMA - the vpmuludq 8-way is measurably faster
150
 * (stronger vector-integer throughput), so IFMA is gated to an Intel vendor.
151
 * Define WOLFSSL_POLY1305_IFMA_ALWAYS to use it on any IFMA CPU, or
152
 * WOLFSSL_POLY1305_NO_IFMA to disable it. */
153
static WC_INLINE int poly1305_use_ifma(cpuid_flags_t flags)
154
{
155
#if defined(WOLFSSL_POLY1305_NO_IFMA)
156
    (void)flags;
157
    return 0;
158
#elif defined(WOLFSSL_POLY1305_IFMA_ALWAYS)
159
    return IS_INTEL_AVX512_IFMA(flags) != 0;
160
#else
161
    return (IS_INTEL_AVX512_IFMA(flags) != 0) && (IS_CPU_INTEL(flags) != 0);
162
#endif
163
}
164
#endif /* HAVE_INTEL_AVX512 */
165
#endif
166
167
#if defined(USE_INTEL_POLY1305_SPEEDUP) || defined(POLY130564)
168
    #if defined(__WATCOMC__)
169
        #error "POLY130564 || USE_INTEL_POLY1305_SPEEDUP Watcom not supported"
170
    #elif defined(_MSC_VER)
171
        #define POLY1305_NOINLINE __declspec(noinline)
172
    #elif defined(__GNUC__)
173
        #define POLY1305_NOINLINE __attribute__((noinline))
174
    #else
175
        #define POLY1305_NOINLINE
176
    #endif
177
178
    #if defined(_MSC_VER) && !(__WATCOMC__)
179
        #include <intrin.h>
180
181
        typedef struct poly1305_word128 {
182
            word64 lo;
183
            word64 hi;
184
        } poly1305_word128;
185
186
        #define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi)
187
        #define ADD(out, in) { word64 t = out.lo; out.lo += in.lo; \
188
                               out.hi += (out.lo < t) + in.hi; }
189
        #define ADDLO(out, in) { word64 t = out.lo; out.lo += in; \
190
                                 out.hi += (out.lo < t); }
191
        #define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift)))
192
        #define LO(in) (in.lo)
193
194
    #elif defined(__GNUC__)
195
        #if defined(__SIZEOF_INT128__)
196
            PEDANTIC_EXTENSION typedef unsigned __int128 poly1305_word128;
197
        #else
198
            typedef unsigned poly1305_word128 __attribute__((mode(TI)));
199
        #endif
200
201
29.7k
        #define MUL(out, x, y) out = ((poly1305_word128)(x) * (y))
202
19.8k
        #define ADD(out, in) (out) += (in)
203
6.61k
        #define ADDLO(out, in) (out) += (in)
204
9.91k
        #define SHR(in, shift) (word64)((in) >> (shift))
205
9.91k
        #define LO(in) (word64)(in)
206
    #endif
207
#endif
208
209
#ifdef USE_INTEL_POLY1305_SPEEDUP
210
#ifdef __cplusplus
211
    extern "C" {
212
#endif
213
214
#ifdef HAVE_INTEL_AVX1
215
/* Process one block (16 bytes) of data.
216
 *
217
 * ctx  Poly1305 context.
218
 * m    One block of message data.
219
 */
220
WOLFSSL_LOCAL void poly1305_block_avx(Poly1305* ctx, const unsigned char *m);
221
/* Process multiple blocks (n * 16 bytes) of data.
222
 *
223
 * ctx    Poly1305 context.
224
 * m      Blocks of message data.
225
 * bytes  The number of bytes to process.
226
 */
227
WOLFSSL_LOCAL void poly1305_blocks_avx(Poly1305* ctx, const unsigned char* m,
228
                                size_t bytes);
229
/* Set the key to use when processing data.
230
 * Initialize the context.
231
 *
232
 * ctx  Poly1305 context.
233
 * key  The key data (16 bytes).
234
 */
235
WOLFSSL_LOCAL void poly1305_setkey_avx(Poly1305* ctx, const byte* key);
236
/* Calculate the final result - authentication data.
237
 * Zeros out the private data in the context.
238
 *
239
 * ctx  Poly1305 context.
240
 * mac  Buffer to hold 16 bytes.
241
 */
242
WOLFSSL_LOCAL void poly1305_final_avx(Poly1305* ctx, byte* mac);
243
#endif
244
245
#ifdef HAVE_INTEL_AVX2
246
/* Process multiple blocks (n * 16 bytes) of data.
247
 *
248
 * ctx    Poly1305 context.
249
 * m      Blocks of message data.
250
 * bytes  The number of bytes to process.
251
 */
252
WOLFSSL_LOCAL void poly1305_blocks_avx2(Poly1305* ctx, const unsigned char* m,
253
                                 size_t bytes);
254
/* Calculate R^1, R^2, R^3 and R^4 and store them in the context.
255
 *
256
 * ctx    Poly1305 context.
257
 */
258
WOLFSSL_LOCAL void poly1305_calc_powers_avx2(Poly1305* ctx);
259
/* Set the key to use when processing data.
260
 * Initialize the context.
261
 * Calls AVX set key function as final function calls AVX code.
262
 *
263
 * ctx  Poly1305 context.
264
 * key  The key data (16 bytes).
265
 */
266
WOLFSSL_LOCAL void poly1305_setkey_avx2(Poly1305* ctx, const byte* key);
267
/* Calculate the final result - authentication data.
268
 * Zeros out the private data in the context.
269
 * Calls AVX final function to quickly process last blocks.
270
 *
271
 * ctx  Poly1305 context.
272
 * mac  Buffer to hold 16 bytes - authentication data.
273
 */
274
WOLFSSL_LOCAL void poly1305_final_avx2(Poly1305* ctx, byte* mac);
275
#endif
276
277
#ifdef HAVE_INTEL_AVX512
278
/* Process multiple 128-byte (8 block) groups of data eight lanes wide. */
279
WOLFSSL_LOCAL void poly1305_blocks_avx512(Poly1305* ctx,
280
                                 const unsigned char* m, size_t bytes);
281
/* Calculate R^1 .. R^8 and store them in the context. */
282
WOLFSSL_LOCAL void poly1305_calc_powers_avx512(Poly1305* ctx);
283
/* Calculate the final result - authentication data.  Collapses the eight
284
 * lanes and finishes any leftover with the AVX final function. */
285
WOLFSSL_LOCAL void poly1305_final_avx512(Poly1305* ctx, byte* mac);
286
287
/* AVX-512 IFMA (radix 2^44) 8-way variants - used when the CPU has IFMA. */
288
WOLFSSL_LOCAL void poly1305_blocks_avx512ifma(Poly1305* ctx,
289
                                 const unsigned char* m, size_t bytes);
290
WOLFSSL_LOCAL void poly1305_calc_powers_avx512ifma(Poly1305* ctx);
291
WOLFSSL_LOCAL void poly1305_setkey_avx512ifma(Poly1305* ctx, const byte* key);
292
WOLFSSL_LOCAL void poly1305_final_avx512ifma(Poly1305* ctx, byte* mac);
293
#endif
294
295
#ifdef __cplusplus
296
    }  /* extern "C" */
297
#endif
298
299
#elif defined(POLY130564)
300
#if (!defined(WOLFSSL_ARMASM) || defined(WOLFSSL_ARM_POLY1305_NEED_C)) && \
301
    !defined(WOLFSSL_RISCV_ASM)
302
    static word64 U8TO64(const byte* p)
303
7.13k
    {
304
7.13k
        return
305
7.13k
            (((word64)(p[0] & 0xff)      ) |
306
7.13k
             ((word64)(p[1] & 0xff) <<  8) |
307
7.13k
             ((word64)(p[2] & 0xff) << 16) |
308
7.13k
             ((word64)(p[3] & 0xff) << 24) |
309
7.13k
             ((word64)(p[4] & 0xff) << 32) |
310
7.13k
             ((word64)(p[5] & 0xff) << 40) |
311
7.13k
             ((word64)(p[6] & 0xff) << 48) |
312
7.13k
             ((word64)(p[7] & 0xff) << 56));
313
7.13k
    }
314
315
260
    static void U64TO8(byte* p, word64 v) {
316
260
        p[0] = (byte)v;
317
260
        p[1] = (byte)(v >>  8);
318
260
        p[2] = (byte)(v >> 16);
319
260
        p[3] = (byte)(v >> 24);
320
260
        p[4] = (byte)(v >> 32);
321
260
        p[5] = (byte)(v >> 40);
322
260
        p[6] = (byte)(v >> 48);
323
260
        p[7] = (byte)(v >> 56);
324
260
    }
325
#endif/* !WOLFSSL_ARMASM && !WOLFSSL_RISCV_ASM */
326
/* if not 64 bit then use 32 bit (also the aarch64 assembly's software
327
 * fallback when there is no 128-bit integer for POLY130564) */
328
#elif !defined(WOLFSSL_ARMASM) || defined(WOLFSSL_ARM_POLY1305_NEED_C)
329
330
    static word32 U8TO32(const byte *p)
331
    {
332
        return
333
            (((word32)(p[0] & 0xff)      ) |
334
             ((word32)(p[1] & 0xff) <<  8) |
335
             ((word32)(p[2] & 0xff) << 16) |
336
             ((word32)(p[3] & 0xff) << 24));
337
    }
338
339
    static void U32TO8(byte *p, word32 v) {
340
        p[0] = (byte)((v      ) & 0xff);
341
        p[1] = (byte)((v >>  8) & 0xff);
342
        p[2] = (byte)((v >> 16) & 0xff);
343
        p[3] = (byte)((v >> 24) & 0xff);
344
    }
345
#endif
346
347
/* convert 32-bit unsigned to little endian 64 bit type as byte array */
348
static WC_INLINE void u32tole64(const word32 inLe32, byte outLe64[8])
349
240
{
350
#ifndef WOLFSSL_X86_64_BUILD
351
    outLe64[0] = (byte)(inLe32  & 0x000000FF);
352
    outLe64[1] = (byte)((inLe32 & 0x0000FF00) >> 8);
353
    outLe64[2] = (byte)((inLe32 & 0x00FF0000) >> 16);
354
    outLe64[3] = (byte)((inLe32 & 0xFF000000) >> 24);
355
    outLe64[4] = 0;
356
    outLe64[5] = 0;
357
    outLe64[6] = 0;
358
    outLe64[7] = 0;
359
#else
360
240
    *(word64*)outLe64 = inLe32;
361
240
#endif
362
240
}
363
364
365
/* The portable C Poly1305 implementation is needed for builds without an
366
 * assembly back end, and as the runtime fallback on aarch64 when NEON is
367
 * unavailable. */
368
#if (!defined(USE_INTEL_POLY1305_SPEEDUP) && !defined(WOLFSSL_ARMASM) && \
369
     !defined(WOLFSSL_RISCV_ASM)) || defined(WOLFSSL_ARM_POLY1305_NEED_C)
370
    #define WOLFSSL_POLY1305_C
371
#endif
372
373
#ifdef WOLFSSL_POLY1305_C
374
375
/* On aarch64 the assembly owns the r/h/pad context fields, so the C state lives
376
 * in the appended c_* fields; every other build uses the standard fields. */
377
#ifdef WOLFSSL_ARM_POLY1305_NEED_C
378
    #define POLY1305_CTX_R    c_r
379
    #define POLY1305_CTX_H    c_h
380
    #define POLY1305_CTX_PAD  c_pad
381
#else
382
2.25k
    #define POLY1305_CTX_R    r
383
4.11k
    #define POLY1305_CTX_H    h
384
780
    #define POLY1305_CTX_PAD  pad
385
#endif
386
387
static void poly1305_c_setkey(Poly1305* ctx, const byte* key)
388
130
{
389
130
#if defined(POLY130564)
390
130
    word64 t0,t1;
391
392
    /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
393
130
    t0 = U8TO64(key + 0);
394
130
    t1 = U8TO64(key + 8);
395
396
130
    ctx->POLY1305_CTX_R[0] = ( t0                    ) & 0xffc0fffffff;
397
130
    ctx->POLY1305_CTX_R[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
398
130
    ctx->POLY1305_CTX_R[2] = ((t1 >> 24)             ) & 0x00ffffffc0f;
399
400
130
    ctx->POLY1305_CTX_H[0] = 0;
401
130
    ctx->POLY1305_CTX_H[1] = 0;
402
130
    ctx->POLY1305_CTX_H[2] = 0;
403
404
130
    ctx->POLY1305_CTX_PAD[0] = U8TO64(key + 16);
405
130
    ctx->POLY1305_CTX_PAD[1] = U8TO64(key + 24);
406
#else
407
    /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
408
    ctx->POLY1305_CTX_R[0] = (U8TO32(key +  0)     ) & 0x3ffffff;
409
    ctx->POLY1305_CTX_R[1] = (U8TO32(key +  3) >> 2) & 0x3ffff03;
410
    ctx->POLY1305_CTX_R[2] = (U8TO32(key +  6) >> 4) & 0x3ffc0ff;
411
    ctx->POLY1305_CTX_R[3] = (U8TO32(key +  9) >> 6) & 0x3f03fff;
412
    ctx->POLY1305_CTX_R[4] = (U8TO32(key + 12) >> 8) & 0x00fffff;
413
414
    ctx->POLY1305_CTX_H[0] = 0;
415
    ctx->POLY1305_CTX_H[1] = 0;
416
    ctx->POLY1305_CTX_H[2] = 0;
417
    ctx->POLY1305_CTX_H[3] = 0;
418
    ctx->POLY1305_CTX_H[4] = 0;
419
420
    ctx->POLY1305_CTX_PAD[0] = U8TO32(key + 16);
421
    ctx->POLY1305_CTX_PAD[1] = U8TO32(key + 20);
422
    ctx->POLY1305_CTX_PAD[2] = U8TO32(key + 24);
423
    ctx->POLY1305_CTX_PAD[3] = U8TO32(key + 28);
424
#endif
425
426
130
    ctx->leftover = 0;
427
130
    ctx->finished = 0;
428
130
}
429
430
static int poly1305_c_blocks(Poly1305* ctx, const byte* m, size_t bytes)
431
491
{
432
491
#if defined(POLY130564)
433
491
    const word64 hibit = (ctx->finished) ? 0 : ((word64)1 << 40); /* 1 << 128 */
434
491
    word64 r0,r1,r2;
435
491
    word64 s1,s2;
436
491
    word64 h0,h1,h2;
437
491
    word64 c;
438
491
    poly1305_word128 d0,d1,d2,d;
439
440
491
    r0 = ctx->POLY1305_CTX_R[0];
441
491
    r1 = ctx->POLY1305_CTX_R[1];
442
491
    r2 = ctx->POLY1305_CTX_R[2];
443
444
491
    h0 = ctx->POLY1305_CTX_H[0];
445
491
    h1 = ctx->POLY1305_CTX_H[1];
446
491
    h2 = ctx->POLY1305_CTX_H[2];
447
448
491
    s1 = r1 * (5 << 2);
449
491
    s2 = r2 * (5 << 2);
450
451
3.79k
    while (bytes >= POLY1305_BLOCK_SIZE) {
452
3.30k
        word64 t0,t1;
453
454
        /* h += m[i] */
455
3.30k
        t0 = U8TO64(&m[0]);
456
3.30k
        t1 = U8TO64(&m[8]);
457
458
3.30k
        h0 += (( t0                    ) & 0xfffffffffff);
459
3.30k
        h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
460
3.30k
        h2 += (((t1 >> 24)             ) & 0x3ffffffffff) | hibit;
461
462
        /* h *= r */
463
3.30k
        MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d);
464
3.30k
        MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d);
465
3.30k
        MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d);
466
467
        /* (partial) h %= p */
468
3.30k
                      c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff;
469
3.30k
        ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff;
470
3.30k
        ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff;
471
3.30k
        h0  += c * 5; c = (h0 >> 44);  h0 =    h0  & 0xfffffffffff;
472
3.30k
        h1  += c;
473
474
3.30k
        m += POLY1305_BLOCK_SIZE;
475
3.30k
        bytes -= POLY1305_BLOCK_SIZE;
476
3.30k
    }
477
478
491
    ctx->POLY1305_CTX_H[0] = h0;
479
491
    ctx->POLY1305_CTX_H[1] = h1;
480
491
    ctx->POLY1305_CTX_H[2] = h2;
481
482
491
    return 0;
483
484
#else /* if not 64 bit then use 32 bit */
485
    const word32 hibit = (ctx->finished) ? 0 : ((word32)1 << 24); /* 1 << 128 */
486
    word32 r0,r1,r2,r3,r4;
487
    word32 s1,s2,s3,s4;
488
    word32 h0,h1,h2,h3,h4;
489
    word32 c;
490
#ifdef WOLFSSL_W64_WRAPPER
491
    #ifdef WOLFSSL_SMALL_STACK
492
    w64wrapper* d;
493
494
    d = (w64wrapper*)XMALLOC(5 * sizeof(w64wrapper), NULL,
495
        DYNAMIC_TYPE_TMP_BUFFER);
496
    if (d == NULL) {
497
        return MEMORY_E;
498
    }
499
    #else
500
    w64wrapper d[5];
501
    #endif
502
#else
503
    word64 d0,d1,d2,d3,d4;
504
#endif
505
506
507
    r0 = ctx->POLY1305_CTX_R[0];
508
    r1 = ctx->POLY1305_CTX_R[1];
509
    r2 = ctx->POLY1305_CTX_R[2];
510
    r3 = ctx->POLY1305_CTX_R[3];
511
    r4 = ctx->POLY1305_CTX_R[4];
512
513
    s1 = r1 * 5;
514
    s2 = r2 * 5;
515
    s3 = r3 * 5;
516
    s4 = r4 * 5;
517
518
    h0 = ctx->POLY1305_CTX_H[0];
519
    h1 = ctx->POLY1305_CTX_H[1];
520
    h2 = ctx->POLY1305_CTX_H[2];
521
    h3 = ctx->POLY1305_CTX_H[3];
522
    h4 = ctx->POLY1305_CTX_H[4];
523
524
    while (bytes >= POLY1305_BLOCK_SIZE) {
525
        /* h += m[i] */
526
        h0 += (U8TO32(m+ 0)     ) & 0x3ffffff;
527
        h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff;
528
        h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff;
529
        h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff;
530
        h4 += (U8TO32(m+12) >> 8) | hibit;
531
532
        /* h *= r */
533
#ifdef WOLFSSL_W64_WRAPPER
534
        {
535
            w64wrapper tmp;
536
537
            d[0] = w64Mul(h0, r0); tmp = w64Mul(h1, s4);
538
            d[0] = w64Add(d[0], tmp, NULL); tmp = w64Mul(h2, s3);
539
            d[0] = w64Add(d[0], tmp, NULL); tmp = w64Mul(h3, s2);
540
            d[0] = w64Add(d[0], tmp, NULL); tmp = w64Mul(h4, s1);
541
            d[0] = w64Add(d[0], tmp, NULL);
542
543
            d[1] = w64Mul(h0, r1); tmp = w64Mul(h1, r0);
544
            d[1] = w64Add(d[1], tmp, NULL); tmp = w64Mul(h2, s4);
545
            d[1] = w64Add(d[1], tmp, NULL); tmp = w64Mul(h3, s3);
546
            d[1] = w64Add(d[1], tmp, NULL); tmp = w64Mul(h4, s2);
547
            d[1] = w64Add(d[1], tmp, NULL);
548
549
            d[2] = w64Mul(h0, r2); tmp = w64Mul(h1, r1);
550
            d[2] = w64Add(d[2], tmp, NULL); tmp = w64Mul(h2, r0);
551
            d[2] = w64Add(d[2], tmp, NULL); tmp = w64Mul(h3, s4);
552
            d[2] = w64Add(d[2], tmp, NULL); tmp = w64Mul(h4, s3);
553
            d[2] = w64Add(d[2], tmp, NULL);
554
555
            d[3] = w64Mul(h0, r3); tmp = w64Mul(h1, r2);
556
            d[3] = w64Add(d[3], tmp, NULL); tmp = w64Mul(h2, r1);
557
            d[3] = w64Add(d[3], tmp, NULL); tmp = w64Mul(h3, r0);
558
            d[3] = w64Add(d[3], tmp, NULL); tmp = w64Mul(h4, s4);
559
            d[3] = w64Add(d[3], tmp, NULL);
560
561
            d[4] = w64Mul(h0, r4); tmp = w64Mul(h1, r3);
562
            d[4] = w64Add(d[4], tmp, NULL); tmp = w64Mul(h2, r2);
563
            d[4] = w64Add(d[4], tmp, NULL); tmp = w64Mul(h3, r1);
564
            d[4] = w64Add(d[4], tmp, NULL); tmp = w64Mul(h4, r0);
565
            d[4] = w64Add(d[4], tmp, NULL);
566
        }
567
#else
568
        d0 = ((word64)h0 * r0) + ((word64)h1 * s4) + ((word64)h2 * s3) +
569
             ((word64)h3 * s2) + ((word64)h4 * s1);
570
        d1 = ((word64)h0 * r1) + ((word64)h1 * r0) + ((word64)h2 * s4) +
571
             ((word64)h3 * s3) + ((word64)h4 * s2);
572
        d2 = ((word64)h0 * r2) + ((word64)h1 * r1) + ((word64)h2 * r0) +
573
             ((word64)h3 * s4) + ((word64)h4 * s3);
574
        d3 = ((word64)h0 * r3) + ((word64)h1 * r2) + ((word64)h2 * r1) +
575
             ((word64)h3 * r0) + ((word64)h4 * s4);
576
        d4 = ((word64)h0 * r4) + ((word64)h1 * r3) + ((word64)h2 * r2) +
577
             ((word64)h3 * r1) + ((word64)h4 * r0);
578
#endif
579
580
        /* (partial) h %= p */
581
#ifdef WOLFSSL_W64_WRAPPER
582
        c = w64GetLow32(w64ShiftRight(d[0], 26));
583
        h0 = w64GetLow32(d[0]) & 0x3ffffff;
584
        d[1] = w64Add32(d[1], c, NULL);
585
        c = w64GetLow32(w64ShiftRight(d[1], 26));
586
        h1 = w64GetLow32(d[1]) & 0x3ffffff;
587
        d[2] = w64Add32(d[2], c, NULL);
588
        c = w64GetLow32(w64ShiftRight(d[2], 26));
589
        h2 = w64GetLow32(d[2]) & 0x3ffffff;
590
        d[3] = w64Add32(d[3], c, NULL);
591
        c = w64GetLow32(w64ShiftRight(d[3], 26));
592
        h3 = w64GetLow32(d[3]) & 0x3ffffff;
593
        d[4] = w64Add32(d[4], c, NULL);
594
        c = w64GetLow32(w64ShiftRight(d[4], 26));
595
        h4 = w64GetLow32(d[4]) & 0x3ffffff;
596
#else
597
                      c = (word32)(d0 >> 26); h0 = (word32)d0 & 0x3ffffff;
598
        d1 += c;      c = (word32)(d1 >> 26); h1 = (word32)d1 & 0x3ffffff;
599
        d2 += c;      c = (word32)(d2 >> 26); h2 = (word32)d2 & 0x3ffffff;
600
        d3 += c;      c = (word32)(d3 >> 26); h3 = (word32)d3 & 0x3ffffff;
601
        d4 += c;      c = (word32)(d4 >> 26); h4 = (word32)d4 & 0x3ffffff;
602
#endif
603
        h0 += c * 5;  c =  (h0 >> 26); h0 =                h0 & 0x3ffffff;
604
        h1 += c;
605
606
        m += POLY1305_BLOCK_SIZE;
607
        bytes -= POLY1305_BLOCK_SIZE;
608
    }
609
610
    ctx->POLY1305_CTX_H[0] = h0;
611
    ctx->POLY1305_CTX_H[1] = h1;
612
    ctx->POLY1305_CTX_H[2] = h2;
613
    ctx->POLY1305_CTX_H[3] = h3;
614
    ctx->POLY1305_CTX_H[4] = h4;
615
616
#if defined(WOLFSSL_W64_WRAPPER) && defined(WOLFSSL_SMALL_STACK)
617
    XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
618
#endif
619
620
    return 0;
621
#endif /* end of 64 bit cpu blocks or 32 bit cpu */
622
491
}
623
624
static void poly1305_c_final(Poly1305* ctx, byte* mac)
625
130
{
626
130
#if defined(POLY130564)
627
130
    word64 h0,h1,h2,c;
628
130
    word64 g0,g1,g2;
629
130
    word64 t0,t1;
630
631
    /* fully carry h */
632
130
    h0 = ctx->POLY1305_CTX_H[0];
633
130
    h1 = ctx->POLY1305_CTX_H[1];
634
130
    h2 = ctx->POLY1305_CTX_H[2];
635
636
130
                 c = (h1 >> 44); h1 &= 0xfffffffffff;
637
130
    h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
638
130
    h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
639
130
    h1 += c;     c = (h1 >> 44); h1 &= 0xfffffffffff;
640
130
    h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
641
130
    h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
642
130
    h1 += c;
643
644
    /* compute h + -p */
645
130
    g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
646
130
    g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
647
130
    g2 = h2 + c - ((word64)1 << 42);
648
649
    /* select h if h < p, or h + -p if h >= p */
650
130
    c = (g2 >> ((sizeof(word64) * CHAR_BIT) - 1)) - 1;
651
130
    g0 &= c;
652
130
    g1 &= c;
653
130
    g2 &= c;
654
130
    c = ~c;
655
130
    h0 = (h0 & c) | g0;
656
130
    h1 = (h1 & c) | g1;
657
130
    h2 = (h2 & c) | g2;
658
659
    /* h = (h + pad) */
660
130
    t0 = ctx->POLY1305_CTX_PAD[0];
661
130
    t1 = ctx->POLY1305_CTX_PAD[1];
662
663
130
    h0 += (( t0                    ) & 0xfffffffffff)    ;
664
130
    c = (h0 >> 44); h0 &= 0xfffffffffff;
665
130
    h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
666
130
    c = (h1 >> 44); h1 &= 0xfffffffffff;
667
130
    h2 += (((t1 >> 24)             ) & 0x3ffffffffff) + c;
668
130
    h2 &= 0x3ffffffffff;
669
670
    /* mac = h % (2^128) */
671
130
    h0 = ((h0      ) | (h1 << 44));
672
130
    h1 = ((h1 >> 20) | (h2 << 24));
673
674
130
    U64TO8(mac + 0, h0);
675
130
    U64TO8(mac + 8, h1);
676
677
    /* zero out the state */
678
130
    ctx->POLY1305_CTX_H[0] = 0;
679
130
    ctx->POLY1305_CTX_H[1] = 0;
680
130
    ctx->POLY1305_CTX_H[2] = 0;
681
130
    ctx->POLY1305_CTX_R[0] = 0;
682
130
    ctx->POLY1305_CTX_R[1] = 0;
683
130
    ctx->POLY1305_CTX_R[2] = 0;
684
130
    ctx->POLY1305_CTX_PAD[0] = 0;
685
130
    ctx->POLY1305_CTX_PAD[1] = 0;
686
687
#else /* if not 64 bit then use 32 bit */
688
689
    word32 h0,h1,h2,h3,h4,c;
690
    word32 g0,g1,g2,g3,g4;
691
#ifdef WOLFSSL_W64_WRAPPER
692
    w64wrapper f;
693
#else
694
    word64 f;
695
#endif
696
    word32 mask;
697
698
    /* fully carry h */
699
    h0 = ctx->POLY1305_CTX_H[0];
700
    h1 = ctx->POLY1305_CTX_H[1];
701
    h2 = ctx->POLY1305_CTX_H[2];
702
    h3 = ctx->POLY1305_CTX_H[3];
703
    h4 = ctx->POLY1305_CTX_H[4];
704
705
                 c = h1 >> 26; h1 = h1 & 0x3ffffff;
706
    h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
707
    h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
708
    h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
709
    h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
710
    h1 +=     c;
711
712
    /* compute h + -p */
713
    g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
714
    g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
715
    g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
716
    g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
717
    g4 = h4 + c - ((word32)1 << 26);
718
719
    /* select h if h < p, or h + -p if h >= p */
720
    mask = ((word32)g4 >> ((sizeof(word32) * CHAR_BIT) - 1)) - 1;
721
    g0 &= mask;
722
    g1 &= mask;
723
    g2 &= mask;
724
    g3 &= mask;
725
    g4 &= mask;
726
    mask = ~mask;
727
    h0 = (h0 & mask) | g0;
728
    h1 = (h1 & mask) | g1;
729
    h2 = (h2 & mask) | g2;
730
    h3 = (h3 & mask) | g3;
731
    h4 = (h4 & mask) | g4;
732
733
    /* h = h % (2^128) */
734
    h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;
735
    h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
736
    h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
737
    h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;
738
739
    /* mac = (h + pad) % (2^128) */
740
#ifdef WOLFSSL_W64_WRAPPER
741
    f = w64From32(0, h0);
742
    f = w64Add32(f, ctx->POLY1305_CTX_PAD[0], NULL);
743
    h0 = w64GetLow32(f);
744
745
    f = w64ShiftRight(f, 32);
746
    f = w64Add32(f, h1, NULL);
747
    f = w64Add32(f, ctx->POLY1305_CTX_PAD[1], NULL);
748
    h1 = w64GetLow32(f);
749
750
    f = w64ShiftRight(f, 32);
751
    f = w64Add32(f, h2, NULL);
752
    f = w64Add32(f, ctx->POLY1305_CTX_PAD[2], NULL);
753
    h2 = w64GetLow32(f);
754
755
    f = w64ShiftRight(f, 32);
756
    f = w64Add32(f, h3, NULL);
757
    f = w64Add32(f, ctx->POLY1305_CTX_PAD[3], NULL);
758
    h3 = w64GetLow32(f);
759
#else
760
    f = (word64)h0 + ctx->POLY1305_CTX_PAD[0]            ; h0 = (word32)f;
761
    f = (word64)h1 + ctx->POLY1305_CTX_PAD[1] + (f >> 32); h1 = (word32)f;
762
    f = (word64)h2 + ctx->POLY1305_CTX_PAD[2] + (f >> 32); h2 = (word32)f;
763
    f = (word64)h3 + ctx->POLY1305_CTX_PAD[3] + (f >> 32); h3 = (word32)f;
764
#endif
765
766
    U32TO8(mac + 0, h0);
767
    U32TO8(mac + 4, h1);
768
    U32TO8(mac + 8, h2);
769
    U32TO8(mac + 12, h3);
770
771
    /* zero out the state */
772
    ctx->POLY1305_CTX_H[0] = 0;
773
    ctx->POLY1305_CTX_H[1] = 0;
774
    ctx->POLY1305_CTX_H[2] = 0;
775
    ctx->POLY1305_CTX_H[3] = 0;
776
    ctx->POLY1305_CTX_H[4] = 0;
777
    ctx->POLY1305_CTX_R[0] = 0;
778
    ctx->POLY1305_CTX_R[1] = 0;
779
    ctx->POLY1305_CTX_R[2] = 0;
780
    ctx->POLY1305_CTX_R[3] = 0;
781
    ctx->POLY1305_CTX_R[4] = 0;
782
    ctx->POLY1305_CTX_PAD[0] = 0;
783
    ctx->POLY1305_CTX_PAD[1] = 0;
784
    ctx->POLY1305_CTX_PAD[2] = 0;
785
    ctx->POLY1305_CTX_PAD[3] = 0;
786
#endif
787
130
}
788
789
#undef POLY1305_CTX_R
790
#undef POLY1305_CTX_H
791
#undef POLY1305_CTX_PAD
792
793
#endif /* WOLFSSL_POLY1305_C */
794
795
#ifdef WOLFSSL_ARM_POLY1305_NEED_C
796
#ifdef WOLFSSL_ARM_POLY1305_NEON_FALLBACK
797
static cpuid_flags_t poly1305_cpuid_flags = WC_CPUID_INITIALIZER;
798
/* Return non-zero when NEON/ASIMD is present and the asm path should run. */
799
static WC_INLINE int poly1305_use_neon(void)
800
{
801
    cpuid_get_flags_ex(&poly1305_cpuid_flags);
802
    return IS_AARCH64_ASIMD(poly1305_cpuid_flags);
803
}
804
#endif
805
806
/* Dispatch each Poly1305 operation to the NEON assembly or the C
807
 * implementation, choosing at runtime when both are available. */
808
static void poly1305_blocks_aarch64(Poly1305* ctx, const unsigned char* m,
809
    size_t bytes)
810
{
811
#ifdef WOLFSSL_ARM_POLY1305_C_ONLY
812
    poly1305_c_blocks(ctx, m, bytes);
813
#else
814
    if (poly1305_use_neon())
815
        poly1305_arm64_blocks(ctx, m, bytes);
816
    else
817
        poly1305_c_blocks(ctx, m, bytes);
818
#endif
819
}
820
821
static void poly1305_block_aarch64(Poly1305* ctx, const unsigned char* m)
822
{
823
#ifdef WOLFSSL_ARM_POLY1305_C_ONLY
824
    poly1305_c_blocks(ctx, m, POLY1305_BLOCK_SIZE);
825
#else
826
    if (poly1305_use_neon())
827
        poly1305_arm64_block_16(ctx, m);
828
    else
829
        poly1305_c_blocks(ctx, m, POLY1305_BLOCK_SIZE);
830
#endif
831
}
832
833
static void poly1305_setkey_aarch64(Poly1305* ctx, const byte* key)
834
{
835
#ifdef WOLFSSL_ARM_POLY1305_C_ONLY
836
    poly1305_c_setkey(ctx, key);
837
#else
838
    if (poly1305_use_neon())
839
        poly1305_set_key(ctx, key);
840
    else
841
        poly1305_c_setkey(ctx, key);
842
#endif
843
}
844
845
static void poly1305_final_aarch64(Poly1305* ctx, byte* mac)
846
{
847
#ifdef WOLFSSL_ARM_POLY1305_C_ONLY
848
    poly1305_c_final(ctx, mac);
849
#else
850
    if (poly1305_use_neon())
851
        poly1305_final(ctx, mac);
852
    else
853
        poly1305_c_final(ctx, mac);
854
#endif
855
}
856
857
#endif /* WOLFSSL_ARM_POLY1305_NEED_C */
858
859
#if !defined(WOLFSSL_RISCV_ASM)
860
/*
861
This local function operates on a message with a given number of bytes
862
with a given ctx pointer to a Poly1305 structure.
863
*/
864
static int poly1305_blocks(Poly1305* ctx, const unsigned char *m,
865
                     size_t bytes)
866
491
{
867
#ifdef USE_INTEL_POLY1305_SPEEDUP
868
    /* AVX2 is handled in wc_Poly1305Update. */
869
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
870
    poly1305_blocks_avx(ctx, m, bytes);
871
    RESTORE_VECTOR_REGISTERS();
872
    return 0;
873
#elif defined(WOLFSSL_ARMASM) && defined(__aarch64__)
874
    poly1305_blocks_aarch64(ctx, m, bytes);
875
    return 0;
876
#elif defined(WOLFSSL_ARMASM) && defined(WOLFSSL_ARMASM_THUMB2)
877
    poly1305_blocks_thumb2_16(ctx, m, bytes, 1);
878
    return 0;
879
#elif defined(WOLFSSL_ARMASM)
880
#ifndef WOLFSSL_ARMASM_NO_NEON
881
    poly1305_arm32_blocks(ctx, m, bytes);
882
    return 0;
883
#else
884
    poly1305_arm32_blocks_16(ctx, m, bytes, 1);
885
    return 0;
886
#endif
887
#else
888
491
    return poly1305_c_blocks(ctx, m, bytes);
889
491
#endif
890
491
}
891
#endif /* !WOLFSSL_RISCV_ASM */
892
893
/*
894
This local function is used for the last call when a message with a given
895
number of bytes is less than the block size.
896
*/
897
static WC_INLINE int poly1305_block(Poly1305* ctx, const unsigned char *m)
898
263
{
899
#ifdef USE_INTEL_POLY1305_SPEEDUP
900
    /* No call to poly1305_block when AVX2, AVX2 does 4 blocks at a time. */
901
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
902
    poly1305_block_avx(ctx, m);
903
    RESTORE_VECTOR_REGISTERS();
904
    return 0;
905
#elif defined(WOLFSSL_ARMASM) && defined(WOLFSSL_ARMASM_THUMB2)
906
    poly1305_blocks_thumb2_16(ctx, m, POLY1305_BLOCK_SIZE, !ctx->finished);
907
    return 0;
908
#elif defined(WOLFSSL_ARMASM) && !defined(__aarch64__)
909
    poly1305_arm32_blocks_16(ctx, m, POLY1305_BLOCK_SIZE, !ctx->finished);
910
    return 0;
911
#elif defined(WOLFSSL_ARMASM)
912
    poly1305_block_aarch64(ctx, m);
913
    return 0;
914
#elif defined(WOLFSSL_RISCV_ASM)
915
    poly1305_block_16_riscv64(ctx, m);
916
    return 0;
917
#else
918
263
    return poly1305_blocks(ctx, m, POLY1305_BLOCK_SIZE);
919
263
#endif
920
263
}
921
922
int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz)
923
130
{
924
925
130
    if (key == NULL)
926
0
        return BAD_FUNC_ARG;
927
928
#ifdef CHACHA_AEAD_TEST
929
    word32 k;
930
    printf("Poly key used:\n");
931
    for (k = 0; k < keySz; k++) {
932
        printf("%02x", key[k]);
933
        if ((k+1) % 8 == 0)
934
            printf("\n");
935
    }
936
    printf("\n");
937
#endif
938
939
130
    if ((ctx == NULL) || (key == NULL) || (keySz != 32)) {
940
0
        return BAD_FUNC_ARG;
941
0
    }
942
943
#ifdef USE_INTEL_POLY1305_SPEEDUP
944
    cpuid_get_flags_ex(&intel_flags);
945
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
946
    #ifdef HAVE_INTEL_AVX512
947
    if (poly1305_use_ifma(intel_flags))
948
        poly1305_setkey_avx512ifma(ctx, key);
949
    else
950
    #endif
951
    #ifdef HAVE_INTEL_AVX2
952
    if (IS_INTEL_AVX2(intel_flags))
953
        poly1305_setkey_avx2(ctx, key);
954
    else
955
    #endif
956
        poly1305_setkey_avx(ctx, key);
957
    RESTORE_VECTOR_REGISTERS();
958
    ctx->started = 0;
959
#ifdef WOLFSSL_CHACHA20_POLY1305_FUSED
960
    ctx->forceAvx2 = 0;
961
#endif
962
#ifdef WOLFSSL_CHACHA20_POLY1305_FUSED_IFMA
963
    ctx->forceScalar = 0;
964
#endif
965
#elif defined(WOLFSSL_ARMASM)
966
#ifdef __aarch64__
967
    poly1305_setkey_aarch64(ctx, key);
968
#else
969
    poly1305_set_key(ctx, key);
970
#endif
971
    ctx->finished = 0;
972
#elif defined(WOLFSSL_RISCV_ASM)
973
    poly1305_set_key_riscv64(ctx, key);
974
#else
975
130
    poly1305_c_setkey(ctx, key);
976
130
#endif
977
978
130
    return 0;
979
130
}
980
981
int wc_Poly1305Final(Poly1305* ctx, byte* mac)
982
130
{
983
130
    if (ctx == NULL || mac == NULL)
984
0
        return BAD_FUNC_ARG;
985
986
#ifdef USE_INTEL_POLY1305_SPEEDUP
987
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
988
    #ifdef HAVE_INTEL_AVX512
989
    if (!POLY1305_FORCE_AVX2(ctx) && !POLY1305_FORCE_SCALAR(ctx) &&
990
            poly1305_use_ifma(intel_flags))
991
        poly1305_final_avx512ifma(ctx, mac);
992
    else
993
    if (!POLY1305_FORCE_AVX2(ctx) && !POLY1305_FORCE_SCALAR(ctx) &&
994
            poly1305_use_avx512(intel_flags))
995
        poly1305_final_avx512(ctx, mac);
996
    else
997
    #endif
998
    #ifdef HAVE_INTEL_AVX2
999
    if (!POLY1305_FORCE_SCALAR(ctx) && IS_INTEL_AVX2(intel_flags))
1000
        poly1305_final_avx2(ctx, mac);
1001
    else
1002
    #endif
1003
        poly1305_final_avx(ctx, mac);
1004
    RESTORE_VECTOR_REGISTERS();
1005
#elif defined(WOLFSSL_ARMASM)
1006
    #if !defined(WOLFSSL_ARMASM_THUMB2) && !defined(WOLFSSL_ARMASM_NO_NEON) && \
1007
        !defined(__aarch64__)
1008
        if (ctx->leftover >= POLY1305_BLOCK_SIZE) {
1009
             size_t len = ctx->leftover & (~(POLY1305_BLOCK_SIZE - 1));
1010
             poly1305_arm32_blocks(ctx, ctx->buffer, len);
1011
             ctx->leftover -= len;
1012
             if (ctx->leftover) {
1013
                 XMEMCPY(ctx->buffer, ctx->buffer + len, ctx->leftover);
1014
             }
1015
        }
1016
    #endif
1017
        if (ctx->leftover) {
1018
             size_t i = ctx->leftover;
1019
             ctx->buffer[i++] = 1;
1020
             for (; i < POLY1305_BLOCK_SIZE; i++) {
1021
                 ctx->buffer[i] = 0;
1022
             }
1023
            ctx->finished = 1;
1024
            poly1305_block(ctx, ctx->buffer);
1025
        }
1026
1027
#ifdef __aarch64__
1028
        poly1305_final_aarch64(ctx, mac);
1029
#else
1030
        poly1305_final(ctx, mac);
1031
#endif
1032
#elif defined(WOLFSSL_RISCV_ASM)
1033
    /* process the remaining block */
1034
    if (ctx->leftover) {
1035
        size_t i = ctx->leftover;
1036
        ctx->buffer[i] = 1;
1037
        for (i = i + 1; i < POLY1305_BLOCK_SIZE; i++)
1038
            ctx->buffer[i] = 0;
1039
        ctx->finished = 1;
1040
        poly1305_block_16_riscv64(ctx, ctx->buffer);
1041
    }
1042
1043
    poly1305_final_riscv64(ctx, mac);
1044
#else
1045
    /* process the remaining block */
1046
130
    if (ctx->leftover) {
1047
9
        size_t i = ctx->leftover;
1048
9
        ctx->buffer[i++] = 1;
1049
54
        for (; i < POLY1305_BLOCK_SIZE; i++)
1050
45
            ctx->buffer[i] = 0;
1051
9
        ctx->finished = 1;
1052
9
        poly1305_block(ctx, ctx->buffer);
1053
9
    }
1054
130
    poly1305_c_final(ctx, mac);
1055
130
#endif
1056
1057
130
    return 0;
1058
130
}
1059
1060
1061
int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes)
1062
635
{
1063
635
    size_t i;
1064
1065
635
    if (ctx == NULL || (m == NULL && bytes > 0))
1066
0
        return BAD_FUNC_ARG;
1067
1068
635
    if (bytes == 0) {
1069
        /* valid, but do nothing */
1070
1
        return 0;
1071
1
    }
1072
#ifdef CHACHA_AEAD_TEST
1073
    word32 k;
1074
    printf("Raw input to poly:\n");
1075
    for (k = 0; k < bytes; k++) {
1076
        printf("%02x", m[k]);
1077
        if ((k+1) % 16 == 0)
1078
            printf("\n");
1079
    }
1080
    printf("\n");
1081
#endif
1082
1083
#if defined(WOLFSSL_ARMASM) && !defined(WOLFSSL_ARMASM_THUMB2) && \
1084
    !defined(WOLFSSL_ARMASM_NO_NEON)
1085
    /* handle leftover */
1086
    if (ctx->leftover) {
1087
        size_t want = sizeof(ctx->buffer) - ctx->leftover;
1088
        if (want > bytes)
1089
            want = bytes;
1090
1091
        for (i = 0; i < want; i++)
1092
            ctx->buffer[ctx->leftover + i] = m[i];
1093
        bytes -= (word32)want;
1094
        m += want;
1095
        ctx->leftover += want;
1096
        if (ctx->leftover < sizeof(ctx->buffer)) {
1097
            return 0;
1098
        }
1099
1100
        poly1305_blocks(ctx, ctx->buffer, sizeof(ctx->buffer));
1101
        ctx->leftover = 0;
1102
    }
1103
1104
    /* process full blocks */
1105
    if (bytes >= sizeof(ctx->buffer)) {
1106
        size_t want = bytes & ~((size_t)POLY1305_BLOCK_SIZE - 1);
1107
1108
        poly1305_blocks(ctx, m, want);
1109
        m += want;
1110
        bytes -= (word32)want;
1111
    }
1112
1113
    /* store leftover */
1114
    if (bytes) {
1115
        for (i = 0; i < bytes; i++)
1116
            ctx->buffer[ctx->leftover + i] = m[i];
1117
        ctx->leftover += bytes;
1118
    }
1119
#else
1120
#ifdef USE_INTEL_POLY1305_SPEEDUP
1121
    #ifdef HAVE_INTEL_AVX512
1122
    if (!POLY1305_FORCE_AVX2(ctx) && !POLY1305_FORCE_SCALAR(ctx) &&
1123
            poly1305_use_ifma(intel_flags)) {
1124
        SAVE_VECTOR_REGISTERS(return _svr_ret;);
1125
1126
        /* handle leftover */
1127
        if (ctx->leftover) {
1128
            size_t want = sizeof(ctx->buffer) - ctx->leftover;
1129
            if (want > bytes)
1130
                want = bytes;
1131
1132
            for (i = 0; i < want; i++)
1133
                ctx->buffer[ctx->leftover + i] = m[i];
1134
            bytes -= (word32)want;
1135
            m += want;
1136
            ctx->leftover += want;
1137
            if (ctx->leftover < sizeof(ctx->buffer)) {
1138
                RESTORE_VECTOR_REGISTERS();
1139
                return 0;
1140
            }
1141
1142
            if (!ctx->started) {
1143
                poly1305_calc_powers_avx512ifma(ctx);
1144
                ctx->started = 1;
1145
            }
1146
            poly1305_blocks_avx512ifma(ctx, ctx->buffer, sizeof(ctx->buffer));
1147
            ctx->leftover = 0;
1148
        }
1149
1150
        /* process full blocks */
1151
        if (bytes >= sizeof(ctx->buffer)) {
1152
            size_t want = bytes & ~(sizeof(ctx->buffer) - 1);
1153
1154
            if (!ctx->started) {
1155
                poly1305_calc_powers_avx512ifma(ctx);
1156
                ctx->started = 1;
1157
            }
1158
            poly1305_blocks_avx512ifma(ctx, m, want);
1159
            m += want;
1160
            bytes -= (word32)want;
1161
        }
1162
1163
        /* store leftover */
1164
        if (bytes) {
1165
            for (i = 0; i < bytes; i++)
1166
                ctx->buffer[ctx->leftover + i] = m[i];
1167
            ctx->leftover += bytes;
1168
        }
1169
        RESTORE_VECTOR_REGISTERS();
1170
    }
1171
    else
1172
    if (!POLY1305_FORCE_AVX2(ctx) && !POLY1305_FORCE_SCALAR(ctx) &&
1173
            poly1305_use_avx512(intel_flags)) {
1174
        SAVE_VECTOR_REGISTERS(return _svr_ret;);
1175
1176
        /* handle leftover */
1177
        if (ctx->leftover) {
1178
            size_t want = sizeof(ctx->buffer) - ctx->leftover;
1179
            if (want > bytes)
1180
                want = bytes;
1181
1182
            for (i = 0; i < want; i++)
1183
                ctx->buffer[ctx->leftover + i] = m[i];
1184
            bytes -= (word32)want;
1185
            m += want;
1186
            ctx->leftover += want;
1187
            if (ctx->leftover < sizeof(ctx->buffer)) {
1188
                RESTORE_VECTOR_REGISTERS();
1189
                return 0;
1190
            }
1191
1192
            if (!ctx->started) {
1193
                poly1305_calc_powers_avx512(ctx);
1194
                ctx->started = 1;
1195
            }
1196
            poly1305_blocks_avx512(ctx, ctx->buffer, sizeof(ctx->buffer));
1197
            ctx->leftover = 0;
1198
        }
1199
1200
        /* process full blocks */
1201
        if (bytes >= sizeof(ctx->buffer)) {
1202
            size_t want = bytes & ~(sizeof(ctx->buffer) - 1);
1203
1204
            if (!ctx->started) {
1205
                poly1305_calc_powers_avx512(ctx);
1206
                ctx->started = 1;
1207
            }
1208
            poly1305_blocks_avx512(ctx, m, want);
1209
            m += want;
1210
            bytes -= (word32)want;
1211
        }
1212
1213
        /* store leftover */
1214
        if (bytes) {
1215
            for (i = 0; i < bytes; i++)
1216
                ctx->buffer[ctx->leftover + i] = m[i];
1217
            ctx->leftover += bytes;
1218
        }
1219
        RESTORE_VECTOR_REGISTERS();
1220
    }
1221
    else
1222
    #endif
1223
    #ifdef HAVE_INTEL_AVX2
1224
    if (!POLY1305_FORCE_SCALAR(ctx) && IS_INTEL_AVX2(intel_flags)) {
1225
        SAVE_VECTOR_REGISTERS(return _svr_ret;);
1226
1227
        /* handle leftover */
1228
        if (ctx->leftover) {
1229
            size_t want = sizeof(ctx->buffer) - ctx->leftover;
1230
            if (want > bytes)
1231
                want = bytes;
1232
1233
            for (i = 0; i < want; i++)
1234
                ctx->buffer[ctx->leftover + i] = m[i];
1235
            bytes -= (word32)want;
1236
            m += want;
1237
            ctx->leftover += want;
1238
            if (ctx->leftover < sizeof(ctx->buffer)) {
1239
                RESTORE_VECTOR_REGISTERS();
1240
                return 0;
1241
            }
1242
1243
            if (!ctx->started) {
1244
                poly1305_calc_powers_avx2(ctx);
1245
                ctx->started = 1;
1246
            }
1247
            poly1305_blocks_avx2(ctx, ctx->buffer, sizeof(ctx->buffer));
1248
            ctx->leftover = 0;
1249
        }
1250
1251
        /* process full blocks */
1252
        if (bytes >= sizeof(ctx->buffer)) {
1253
            size_t want = bytes & ~(sizeof(ctx->buffer) - 1);
1254
1255
            if (!ctx->started) {
1256
                poly1305_calc_powers_avx2(ctx);
1257
                ctx->started = 1;
1258
            }
1259
            poly1305_blocks_avx2(ctx, m, want);
1260
            m += want;
1261
            bytes -= (word32)want;
1262
        }
1263
1264
        /* store leftover */
1265
        if (bytes) {
1266
            for (i = 0; i < bytes; i++)
1267
                ctx->buffer[ctx->leftover + i] = m[i];
1268
            ctx->leftover += bytes;
1269
        }
1270
        RESTORE_VECTOR_REGISTERS();
1271
    }
1272
    else
1273
    #endif
1274
#endif
1275
634
    {
1276
        /* handle leftover */
1277
634
        if (ctx->leftover) {
1278
265
            size_t want = (POLY1305_BLOCK_SIZE - ctx->leftover);
1279
265
            if (want > bytes)
1280
11
                want = bytes;
1281
2.62k
            for (i = 0; i < want; i++)
1282
2.35k
                ctx->buffer[ctx->leftover + i] = m[i];
1283
265
            bytes -= (word32)want;
1284
265
            m += want;
1285
265
            ctx->leftover += want;
1286
265
            if (ctx->leftover < POLY1305_BLOCK_SIZE)
1287
11
                return 0;
1288
254
            poly1305_block(ctx, ctx->buffer);
1289
254
            ctx->leftover = 0;
1290
254
        }
1291
1292
        /* process full blocks */
1293
623
        if (bytes >= POLY1305_BLOCK_SIZE) {
1294
228
            size_t want = ((size_t)bytes & ~((size_t)POLY1305_BLOCK_SIZE - 1));
1295
228
#if !defined(WOLFSSL_ARMASM) && !defined(WOLFSSL_RISCV_ASM)
1296
228
            int ret;
1297
228
            ret = poly1305_blocks(ctx, m, want);
1298
228
            if (ret != 0)
1299
0
                return ret;
1300
#else
1301
            poly1305_blocks(ctx, m, want);
1302
#endif
1303
228
            m += want;
1304
228
            bytes -= (word32)want;
1305
228
        }
1306
1307
        /* store leftover */
1308
623
        if (bytes) {
1309
2.06k
            for (i = 0; i < bytes; i++)
1310
1.79k
                ctx->buffer[ctx->leftover + i] = m[i];
1311
263
            ctx->leftover += bytes;
1312
263
        }
1313
623
    }
1314
0
#endif
1315
1316
0
    return 0;
1317
623
}
1318
1319
/*  Takes a Poly1305 struct that has a key loaded and pads the provided length
1320
    ctx        : Initialized Poly1305 struct to use
1321
    lenToPad   : Current number of bytes updated that needs padding to 16
1322
 */
1323
int wc_Poly1305_Pad(Poly1305* ctx, word32 lenToPad)
1324
240
{
1325
240
    int ret = 0;
1326
240
    word32 paddingLen;
1327
240
    byte padding[WC_POLY1305_PAD_SZ - 1];
1328
1329
240
    if (ctx == NULL) {
1330
0
        return BAD_FUNC_ARG;
1331
0
    }
1332
240
    if (lenToPad == 0) {
1333
1
        return 0; /* nothing needs to be done */
1334
1
    }
1335
1336
239
    XMEMSET(padding, 0, sizeof(padding));
1337
1338
    /* Pad length to 16 bytes */
1339
239
    paddingLen = (-(int)lenToPad) & (WC_POLY1305_PAD_SZ - 1);
1340
239
    if ((paddingLen > 0) && (paddingLen < WC_POLY1305_PAD_SZ)) {
1341
235
        ret = wc_Poly1305Update(ctx, padding, paddingLen);
1342
235
    }
1343
239
    return ret;
1344
240
}
1345
1346
/*  Takes a Poly1305 struct that has a key loaded and adds the AEAD length
1347
    encoding in 64-bit little endian
1348
    aadSz      : Size of the additional authentication data
1349
    dataSz     : Size of the plaintext or ciphertext
1350
 */
1351
int wc_Poly1305_EncodeSizes(Poly1305* ctx, word32 aadSz, word32 dataSz)
1352
120
{
1353
120
    int ret;
1354
120
    byte little64[16]; /* sizeof(word64) * 2 */
1355
1356
120
    if (ctx == NULL) {
1357
0
        return BAD_FUNC_ARG;
1358
0
    }
1359
1360
120
    XMEMSET(little64, 0, sizeof(little64));
1361
1362
    /* size of additional data and input data as little endian 64 bit types */
1363
120
    u32tole64(aadSz,  little64);
1364
120
    u32tole64(dataSz, little64 + 8);
1365
120
    ret = wc_Poly1305Update(ctx, little64, sizeof(little64));
1366
1367
120
    return ret;
1368
120
}
1369
1370
#ifdef WORD64_AVAILABLE
1371
int wc_Poly1305_EncodeSizes64(Poly1305* ctx, word64 aadSz, word64 dataSz)
1372
0
{
1373
0
    int ret;
1374
0
    word64 little64[2];
1375
1376
0
    if (ctx == NULL) {
1377
0
        return BAD_FUNC_ARG;
1378
0
    }
1379
1380
#ifdef BIG_ENDIAN_ORDER
1381
    little64[0] = ByteReverseWord64(aadSz);
1382
    little64[1] = ByteReverseWord64(dataSz);
1383
#else
1384
0
    little64[0] = aadSz;
1385
0
    little64[1] = dataSz;
1386
0
#endif
1387
1388
0
    ret = wc_Poly1305Update(ctx, (byte *)little64, sizeof(little64));
1389
1390
0
    return ret;
1391
0
}
1392
#endif
1393
1394
/*  Takes in an initialized Poly1305 struct that has a key loaded and creates
1395
    a MAC (tag) using recent TLS AEAD padding scheme.
1396
    ctx        : Initialized Poly1305 struct to use
1397
    additional : Additional data to use
1398
    addSz      : Size of additional buffer
1399
    input      : Input buffer to create tag from
1400
    sz         : Size of input buffer
1401
    tag        : Buffer to hold created tag
1402
    tagSz      : Size of input tag buffer (must be at least
1403
                 WC_POLY1305_MAC_SZ(16))
1404
 */
1405
int wc_Poly1305_MAC(Poly1305* ctx, const byte* additional, word32 addSz,
1406
                    const byte* input, word32 sz, byte* tag, word32 tagSz)
1407
120
{
1408
120
    int ret;
1409
1410
    /* sanity check on arguments */
1411
120
    if (ctx == NULL || input == NULL || tag == NULL ||
1412
120
                                                   tagSz < WC_POLY1305_MAC_SZ) {
1413
0
        return BAD_FUNC_ARG;
1414
0
    }
1415
1416
    /* additional allowed to be 0 */
1417
120
    if (addSz > 0) {
1418
120
        if (additional == NULL)
1419
0
            return BAD_FUNC_ARG;
1420
1421
        /* additional data plus padding */
1422
120
        if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) {
1423
0
            return ret;
1424
0
        }
1425
        /* pad additional data */
1426
120
        if ((ret = wc_Poly1305_Pad(ctx, addSz)) != 0) {
1427
0
            return ret;
1428
0
        }
1429
120
    }
1430
1431
    /* input plus padding */
1432
120
    if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) {
1433
0
        return ret;
1434
0
    }
1435
    /* pad input data */
1436
120
    if ((ret = wc_Poly1305_Pad(ctx, sz)) != 0) {
1437
0
        return ret;
1438
0
    }
1439
1440
    /* encode size of AAD and input data as little endian 64 bit types */
1441
120
    if ((ret = wc_Poly1305_EncodeSizes(ctx, addSz, sz)) != 0) {
1442
0
        return ret;
1443
0
    }
1444
1445
    /* Finalize the auth tag */
1446
120
    ret = wc_Poly1305Final(ctx, tag);
1447
1448
120
    return ret;
1449
1450
120
}
1451
#endif /* HAVE_POLY1305 */