Coverage Report

Created: 2026-08-15 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-heapmath/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
193k
        #define MUL(out, x, y) out = ((poly1305_word128)(x) * (y))
202
128k
        #define ADD(out, in) (out) += (in)
203
42.9k
        #define ADDLO(out, in) (out) += (in)
204
64.4k
        #define SHR(in, shift) (word64)((in) >> (shift))
205
64.4k
        #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
44.9k
    {
304
44.9k
        return
305
44.9k
            (((word64)(p[0] & 0xff)      ) |
306
44.9k
             ((word64)(p[1] & 0xff) <<  8) |
307
44.9k
             ((word64)(p[2] & 0xff) << 16) |
308
44.9k
             ((word64)(p[3] & 0xff) << 24) |
309
44.9k
             ((word64)(p[4] & 0xff) << 32) |
310
44.9k
             ((word64)(p[5] & 0xff) << 40) |
311
44.9k
             ((word64)(p[6] & 0xff) << 48) |
312
44.9k
             ((word64)(p[7] & 0xff) << 56));
313
44.9k
    }
314
315
988
    static void U64TO8(byte* p, word64 v) {
316
988
        p[0] = (byte)v;
317
988
        p[1] = (byte)(v >>  8);
318
988
        p[2] = (byte)(v >> 16);
319
988
        p[3] = (byte)(v >> 24);
320
988
        p[4] = (byte)(v >> 32);
321
988
        p[5] = (byte)(v >> 40);
322
988
        p[6] = (byte)(v >> 48);
323
988
        p[7] = (byte)(v >> 56);
324
988
    }
325
#endif/* !WOLFSSL_ARMASM && !WOLFSSL_RISCV_ASM */
326
/* if not 64 bit then use 32 bit */
327
#elif !defined(WOLFSSL_ARMASM)
328
329
    static word32 U8TO32(const byte *p)
330
    {
331
        return
332
            (((word32)(p[0] & 0xff)      ) |
333
             ((word32)(p[1] & 0xff) <<  8) |
334
             ((word32)(p[2] & 0xff) << 16) |
335
             ((word32)(p[3] & 0xff) << 24));
336
    }
337
338
    static void U32TO8(byte *p, word32 v) {
339
        p[0] = (byte)((v      ) & 0xff);
340
        p[1] = (byte)((v >>  8) & 0xff);
341
        p[2] = (byte)((v >> 16) & 0xff);
342
        p[3] = (byte)((v >> 24) & 0xff);
343
    }
344
#endif
345
346
/* convert 32-bit unsigned to little endian 64 bit type as byte array */
347
static WC_INLINE void u32tole64(const word32 inLe32, byte outLe64[8])
348
968
{
349
#ifndef WOLFSSL_X86_64_BUILD
350
    outLe64[0] = (byte)(inLe32  & 0x000000FF);
351
    outLe64[1] = (byte)((inLe32 & 0x0000FF00) >> 8);
352
    outLe64[2] = (byte)((inLe32 & 0x00FF0000) >> 16);
353
    outLe64[3] = (byte)((inLe32 & 0xFF000000) >> 24);
354
    outLe64[4] = 0;
355
    outLe64[5] = 0;
356
    outLe64[6] = 0;
357
    outLe64[7] = 0;
358
#else
359
968
    *(word64*)outLe64 = inLe32;
360
968
#endif
361
968
}
362
363
364
/* The portable C Poly1305 implementation is needed for builds without an
365
 * assembly back end, and as the runtime fallback on aarch64 when NEON is
366
 * unavailable. */
367
#if (!defined(USE_INTEL_POLY1305_SPEEDUP) && !defined(WOLFSSL_ARMASM) && \
368
     !defined(WOLFSSL_RISCV_ASM)) || defined(WOLFSSL_ARM_POLY1305_NEED_C)
369
    #define WOLFSSL_POLY1305_C
370
#endif
371
372
#ifdef WOLFSSL_POLY1305_C
373
374
/* On aarch64 the assembly owns the r/h/pad context fields, so the C state lives
375
 * in the appended c_* fields; every other build uses the standard fields. */
376
#ifdef WOLFSSL_ARM_POLY1305_NEED_C
377
    #define POLY1305_CTX_R    c_r
378
    #define POLY1305_CTX_H    c_h
379
    #define POLY1305_CTX_PAD  c_pad
380
#else
381
8.66k
    #define POLY1305_CTX_R    r
382
15.8k
    #define POLY1305_CTX_H    h
383
2.96k
    #define POLY1305_CTX_PAD  pad
384
#endif
385
386
static void poly1305_c_setkey(Poly1305* ctx, const byte* key)
387
494
{
388
494
#if defined(POLY130564)
389
494
    word64 t0,t1;
390
391
    /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
392
494
    t0 = U8TO64(key + 0);
393
494
    t1 = U8TO64(key + 8);
394
395
494
    ctx->POLY1305_CTX_R[0] = ( t0                    ) & 0xffc0fffffff;
396
494
    ctx->POLY1305_CTX_R[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
397
494
    ctx->POLY1305_CTX_R[2] = ((t1 >> 24)             ) & 0x00ffffffc0f;
398
399
494
    ctx->POLY1305_CTX_H[0] = 0;
400
494
    ctx->POLY1305_CTX_H[1] = 0;
401
494
    ctx->POLY1305_CTX_H[2] = 0;
402
403
494
    ctx->POLY1305_CTX_PAD[0] = U8TO64(key + 16);
404
494
    ctx->POLY1305_CTX_PAD[1] = U8TO64(key + 24);
405
#else
406
    /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
407
    ctx->r[0] = (U8TO32(key +  0)     ) & 0x3ffffff;
408
    ctx->r[1] = (U8TO32(key +  3) >> 2) & 0x3ffff03;
409
    ctx->r[2] = (U8TO32(key +  6) >> 4) & 0x3ffc0ff;
410
    ctx->r[3] = (U8TO32(key +  9) >> 6) & 0x3f03fff;
411
    ctx->r[4] = (U8TO32(key + 12) >> 8) & 0x00fffff;
412
413
    ctx->h[0] = 0;
414
    ctx->h[1] = 0;
415
    ctx->h[2] = 0;
416
    ctx->h[3] = 0;
417
    ctx->h[4] = 0;
418
419
    ctx->pad[0] = U8TO32(key + 16);
420
    ctx->pad[1] = U8TO32(key + 20);
421
    ctx->pad[2] = U8TO32(key + 24);
422
    ctx->pad[3] = U8TO32(key + 28);
423
#endif
424
425
494
    ctx->leftover = 0;
426
494
    ctx->finished = 0;
427
494
}
428
429
static int poly1305_c_blocks(Poly1305* ctx, const byte* m, size_t bytes)
430
1.90k
{
431
1.90k
#if defined(POLY130564)
432
1.90k
    const word64 hibit = (ctx->finished) ? 0 : ((word64)1 << 40); /* 1 << 128 */
433
1.90k
    word64 r0,r1,r2;
434
1.90k
    word64 s1,s2;
435
1.90k
    word64 h0,h1,h2;
436
1.90k
    word64 c;
437
1.90k
    poly1305_word128 d0,d1,d2,d;
438
439
1.90k
    r0 = ctx->POLY1305_CTX_R[0];
440
1.90k
    r1 = ctx->POLY1305_CTX_R[1];
441
1.90k
    r2 = ctx->POLY1305_CTX_R[2];
442
443
1.90k
    h0 = ctx->POLY1305_CTX_H[0];
444
1.90k
    h1 = ctx->POLY1305_CTX_H[1];
445
1.90k
    h2 = ctx->POLY1305_CTX_H[2];
446
447
1.90k
    s1 = r1 * (5 << 2);
448
1.90k
    s2 = r2 * (5 << 2);
449
450
23.3k
    while (bytes >= POLY1305_BLOCK_SIZE) {
451
21.4k
        word64 t0,t1;
452
453
        /* h += m[i] */
454
21.4k
        t0 = U8TO64(&m[0]);
455
21.4k
        t1 = U8TO64(&m[8]);
456
457
21.4k
        h0 += (( t0                    ) & 0xfffffffffff);
458
21.4k
        h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
459
21.4k
        h2 += (((t1 >> 24)             ) & 0x3ffffffffff) | hibit;
460
461
        /* h *= r */
462
21.4k
        MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d);
463
21.4k
        MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d);
464
21.4k
        MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d);
465
466
        /* (partial) h %= p */
467
21.4k
                      c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff;
468
21.4k
        ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff;
469
21.4k
        ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff;
470
21.4k
        h0  += c * 5; c = (h0 >> 44);  h0 =    h0  & 0xfffffffffff;
471
21.4k
        h1  += c;
472
473
21.4k
        m += POLY1305_BLOCK_SIZE;
474
21.4k
        bytes -= POLY1305_BLOCK_SIZE;
475
21.4k
    }
476
477
1.90k
    ctx->POLY1305_CTX_H[0] = h0;
478
1.90k
    ctx->POLY1305_CTX_H[1] = h1;
479
1.90k
    ctx->POLY1305_CTX_H[2] = h2;
480
481
1.90k
    return 0;
482
483
#else /* if not 64 bit then use 32 bit */
484
    const word32 hibit = (ctx->finished) ? 0 : ((word32)1 << 24); /* 1 << 128 */
485
    word32 r0,r1,r2,r3,r4;
486
    word32 s1,s2,s3,s4;
487
    word32 h0,h1,h2,h3,h4;
488
    word32 c;
489
#ifdef WOLFSSL_W64_WRAPPER
490
    #ifdef WOLFSSL_SMALL_STACK
491
    w64wrapper* d;
492
493
    d = (w64wrapper*)XMALLOC(5 * sizeof(w64wrapper), NULL,
494
        DYNAMIC_TYPE_TMP_BUFFER);
495
    if (d == NULL) {
496
        return MEMORY_E;
497
    }
498
    #else
499
    w64wrapper d[5];
500
    #endif
501
#else
502
    word64 d0,d1,d2,d3,d4;
503
#endif
504
505
506
    r0 = ctx->r[0];
507
    r1 = ctx->r[1];
508
    r2 = ctx->r[2];
509
    r3 = ctx->r[3];
510
    r4 = ctx->r[4];
511
512
    s1 = r1 * 5;
513
    s2 = r2 * 5;
514
    s3 = r3 * 5;
515
    s4 = r4 * 5;
516
517
    h0 = ctx->h[0];
518
    h1 = ctx->h[1];
519
    h2 = ctx->h[2];
520
    h3 = ctx->h[3];
521
    h4 = ctx->h[4];
522
523
    while (bytes >= POLY1305_BLOCK_SIZE) {
524
        /* h += m[i] */
525
        h0 += (U8TO32(m+ 0)     ) & 0x3ffffff;
526
        h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff;
527
        h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff;
528
        h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff;
529
        h4 += (U8TO32(m+12) >> 8) | hibit;
530
531
        /* h *= r */
532
#ifdef WOLFSSL_W64_WRAPPER
533
        {
534
            w64wrapper tmp;
535
536
            d[0] = w64Mul(h0, r0); tmp = w64Mul(h1, s4);
537
            d[0] = w64Add(d[0], tmp, NULL); tmp = w64Mul(h2, s3);
538
            d[0] = w64Add(d[0], tmp, NULL); tmp = w64Mul(h3, s2);
539
            d[0] = w64Add(d[0], tmp, NULL); tmp = w64Mul(h4, s1);
540
            d[0] = w64Add(d[0], tmp, NULL);
541
542
            d[1] = w64Mul(h0, r1); tmp = w64Mul(h1, r0);
543
            d[1] = w64Add(d[1], tmp, NULL); tmp = w64Mul(h2, s4);
544
            d[1] = w64Add(d[1], tmp, NULL); tmp = w64Mul(h3, s3);
545
            d[1] = w64Add(d[1], tmp, NULL); tmp = w64Mul(h4, s2);
546
            d[1] = w64Add(d[1], tmp, NULL);
547
548
            d[2] = w64Mul(h0, r2); tmp = w64Mul(h1, r1);
549
            d[2] = w64Add(d[2], tmp, NULL); tmp = w64Mul(h2, r0);
550
            d[2] = w64Add(d[2], tmp, NULL); tmp = w64Mul(h3, s4);
551
            d[2] = w64Add(d[2], tmp, NULL); tmp = w64Mul(h4, s3);
552
            d[2] = w64Add(d[2], tmp, NULL);
553
554
            d[3] = w64Mul(h0, r3); tmp = w64Mul(h1, r2);
555
            d[3] = w64Add(d[3], tmp, NULL); tmp = w64Mul(h2, r1);
556
            d[3] = w64Add(d[3], tmp, NULL); tmp = w64Mul(h3, r0);
557
            d[3] = w64Add(d[3], tmp, NULL); tmp = w64Mul(h4, s4);
558
            d[3] = w64Add(d[3], tmp, NULL);
559
560
            d[4] = w64Mul(h0, r4); tmp = w64Mul(h1, r3);
561
            d[4] = w64Add(d[4], tmp, NULL); tmp = w64Mul(h2, r2);
562
            d[4] = w64Add(d[4], tmp, NULL); tmp = w64Mul(h3, r1);
563
            d[4] = w64Add(d[4], tmp, NULL); tmp = w64Mul(h4, r0);
564
            d[4] = w64Add(d[4], tmp, NULL);
565
        }
566
#else
567
        d0 = ((word64)h0 * r0) + ((word64)h1 * s4) + ((word64)h2 * s3) +
568
             ((word64)h3 * s2) + ((word64)h4 * s1);
569
        d1 = ((word64)h0 * r1) + ((word64)h1 * r0) + ((word64)h2 * s4) +
570
             ((word64)h3 * s3) + ((word64)h4 * s2);
571
        d2 = ((word64)h0 * r2) + ((word64)h1 * r1) + ((word64)h2 * r0) +
572
             ((word64)h3 * s4) + ((word64)h4 * s3);
573
        d3 = ((word64)h0 * r3) + ((word64)h1 * r2) + ((word64)h2 * r1) +
574
             ((word64)h3 * r0) + ((word64)h4 * s4);
575
        d4 = ((word64)h0 * r4) + ((word64)h1 * r3) + ((word64)h2 * r2) +
576
             ((word64)h3 * r1) + ((word64)h4 * r0);
577
#endif
578
579
        /* (partial) h %= p */
580
#ifdef WOLFSSL_W64_WRAPPER
581
        c = w64GetLow32(w64ShiftRight(d[0], 26));
582
        h0 = w64GetLow32(d[0]) & 0x3ffffff;
583
        d[1] = w64Add32(d[1], c, NULL);
584
        c = w64GetLow32(w64ShiftRight(d[1], 26));
585
        h1 = w64GetLow32(d[1]) & 0x3ffffff;
586
        d[2] = w64Add32(d[2], c, NULL);
587
        c = w64GetLow32(w64ShiftRight(d[2], 26));
588
        h2 = w64GetLow32(d[2]) & 0x3ffffff;
589
        d[3] = w64Add32(d[3], c, NULL);
590
        c = w64GetLow32(w64ShiftRight(d[3], 26));
591
        h3 = w64GetLow32(d[3]) & 0x3ffffff;
592
        d[4] = w64Add32(d[4], c, NULL);
593
        c = w64GetLow32(w64ShiftRight(d[4], 26));
594
        h4 = w64GetLow32(d[4]) & 0x3ffffff;
595
#else
596
                      c = (word32)(d0 >> 26); h0 = (word32)d0 & 0x3ffffff;
597
        d1 += c;      c = (word32)(d1 >> 26); h1 = (word32)d1 & 0x3ffffff;
598
        d2 += c;      c = (word32)(d2 >> 26); h2 = (word32)d2 & 0x3ffffff;
599
        d3 += c;      c = (word32)(d3 >> 26); h3 = (word32)d3 & 0x3ffffff;
600
        d4 += c;      c = (word32)(d4 >> 26); h4 = (word32)d4 & 0x3ffffff;
601
#endif
602
        h0 += c * 5;  c =  (h0 >> 26); h0 =                h0 & 0x3ffffff;
603
        h1 += c;
604
605
        m += POLY1305_BLOCK_SIZE;
606
        bytes -= POLY1305_BLOCK_SIZE;
607
    }
608
609
    ctx->h[0] = h0;
610
    ctx->h[1] = h1;
611
    ctx->h[2] = h2;
612
    ctx->h[3] = h3;
613
    ctx->h[4] = h4;
614
615
#if defined(WOLFSSL_W64_WRAPPER) && defined(WOLFSSL_SMALL_STACK)
616
    XFREE(d, NULL, DYNAMIC_TYPE_TMP_BUFFER);
617
#endif
618
619
    return 0;
620
#endif /* end of 64 bit cpu blocks or 32 bit cpu */
621
1.90k
}
622
623
static void poly1305_c_final(Poly1305* ctx, byte* mac)
624
494
{
625
494
#if defined(POLY130564)
626
494
    word64 h0,h1,h2,c;
627
494
    word64 g0,g1,g2;
628
494
    word64 t0,t1;
629
630
    /* fully carry h */
631
494
    h0 = ctx->POLY1305_CTX_H[0];
632
494
    h1 = ctx->POLY1305_CTX_H[1];
633
494
    h2 = ctx->POLY1305_CTX_H[2];
634
635
494
                 c = (h1 >> 44); h1 &= 0xfffffffffff;
636
494
    h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
637
494
    h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
638
494
    h1 += c;     c = (h1 >> 44); h1 &= 0xfffffffffff;
639
494
    h2 += c;     c = (h2 >> 42); h2 &= 0x3ffffffffff;
640
494
    h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
641
494
    h1 += c;
642
643
    /* compute h + -p */
644
494
    g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
645
494
    g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
646
494
    g2 = h2 + c - ((word64)1 << 42);
647
648
    /* select h if h < p, or h + -p if h >= p */
649
494
    c = (g2 >> ((sizeof(word64) * CHAR_BIT) - 1)) - 1;
650
494
    g0 &= c;
651
494
    g1 &= c;
652
494
    g2 &= c;
653
494
    c = ~c;
654
494
    h0 = (h0 & c) | g0;
655
494
    h1 = (h1 & c) | g1;
656
494
    h2 = (h2 & c) | g2;
657
658
    /* h = (h + pad) */
659
494
    t0 = ctx->POLY1305_CTX_PAD[0];
660
494
    t1 = ctx->POLY1305_CTX_PAD[1];
661
662
494
    h0 += (( t0                    ) & 0xfffffffffff)    ;
663
494
    c = (h0 >> 44); h0 &= 0xfffffffffff;
664
494
    h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
665
494
    c = (h1 >> 44); h1 &= 0xfffffffffff;
666
494
    h2 += (((t1 >> 24)             ) & 0x3ffffffffff) + c;
667
494
    h2 &= 0x3ffffffffff;
668
669
    /* mac = h % (2^128) */
670
494
    h0 = ((h0      ) | (h1 << 44));
671
494
    h1 = ((h1 >> 20) | (h2 << 24));
672
673
494
    U64TO8(mac + 0, h0);
674
494
    U64TO8(mac + 8, h1);
675
676
    /* zero out the state */
677
494
    ctx->POLY1305_CTX_H[0] = 0;
678
494
    ctx->POLY1305_CTX_H[1] = 0;
679
494
    ctx->POLY1305_CTX_H[2] = 0;
680
494
    ctx->POLY1305_CTX_R[0] = 0;
681
494
    ctx->POLY1305_CTX_R[1] = 0;
682
494
    ctx->POLY1305_CTX_R[2] = 0;
683
494
    ctx->POLY1305_CTX_PAD[0] = 0;
684
494
    ctx->POLY1305_CTX_PAD[1] = 0;
685
686
#else /* if not 64 bit then use 32 bit */
687
688
    word32 h0,h1,h2,h3,h4,c;
689
    word32 g0,g1,g2,g3,g4;
690
#ifdef WOLFSSL_W64_WRAPPER
691
    w64wrapper f;
692
#else
693
    word64 f;
694
#endif
695
    word32 mask;
696
697
    /* fully carry h */
698
    h0 = ctx->h[0];
699
    h1 = ctx->h[1];
700
    h2 = ctx->h[2];
701
    h3 = ctx->h[3];
702
    h4 = ctx->h[4];
703
704
                 c = h1 >> 26; h1 = h1 & 0x3ffffff;
705
    h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
706
    h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
707
    h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
708
    h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
709
    h1 +=     c;
710
711
    /* compute h + -p */
712
    g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
713
    g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
714
    g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
715
    g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
716
    g4 = h4 + c - ((word32)1 << 26);
717
718
    /* select h if h < p, or h + -p if h >= p */
719
    mask = ((word32)g4 >> ((sizeof(word32) * CHAR_BIT) - 1)) - 1;
720
    g0 &= mask;
721
    g1 &= mask;
722
    g2 &= mask;
723
    g3 &= mask;
724
    g4 &= mask;
725
    mask = ~mask;
726
    h0 = (h0 & mask) | g0;
727
    h1 = (h1 & mask) | g1;
728
    h2 = (h2 & mask) | g2;
729
    h3 = (h3 & mask) | g3;
730
    h4 = (h4 & mask) | g4;
731
732
    /* h = h % (2^128) */
733
    h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;
734
    h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
735
    h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
736
    h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;
737
738
    /* mac = (h + pad) % (2^128) */
739
#ifdef WOLFSSL_W64_WRAPPER
740
    f = w64From32(0, h0);
741
    f = w64Add32(f, ctx->pad[0], NULL);
742
    h0 = w64GetLow32(f);
743
744
    f = w64ShiftRight(f, 32);
745
    f = w64Add32(f, h1, NULL);
746
    f = w64Add32(f, ctx->pad[1], NULL);
747
    h1 = w64GetLow32(f);
748
749
    f = w64ShiftRight(f, 32);
750
    f = w64Add32(f, h2, NULL);
751
    f = w64Add32(f, ctx->pad[2], NULL);
752
    h2 = w64GetLow32(f);
753
754
    f = w64ShiftRight(f, 32);
755
    f = w64Add32(f, h3, NULL);
756
    f = w64Add32(f, ctx->pad[3], NULL);
757
    h3 = w64GetLow32(f);
758
#else
759
    f = (word64)h0 + ctx->pad[0]            ; h0 = (word32)f;
760
    f = (word64)h1 + ctx->pad[1] + (f >> 32); h1 = (word32)f;
761
    f = (word64)h2 + ctx->pad[2] + (f >> 32); h2 = (word32)f;
762
    f = (word64)h3 + ctx->pad[3] + (f >> 32); h3 = (word32)f;
763
#endif
764
765
    U32TO8(mac + 0, h0);
766
    U32TO8(mac + 4, h1);
767
    U32TO8(mac + 8, h2);
768
    U32TO8(mac + 12, h3);
769
770
    /* zero out the state */
771
    ctx->h[0] = 0;
772
    ctx->h[1] = 0;
773
    ctx->h[2] = 0;
774
    ctx->h[3] = 0;
775
    ctx->h[4] = 0;
776
    ctx->r[0] = 0;
777
    ctx->r[1] = 0;
778
    ctx->r[2] = 0;
779
    ctx->r[3] = 0;
780
    ctx->r[4] = 0;
781
    ctx->pad[0] = 0;
782
    ctx->pad[1] = 0;
783
    ctx->pad[2] = 0;
784
    ctx->pad[3] = 0;
785
#endif
786
494
}
787
788
#undef POLY1305_CTX_R
789
#undef POLY1305_CTX_H
790
#undef POLY1305_CTX_PAD
791
792
#endif /* WOLFSSL_POLY1305_C */
793
794
#ifdef WOLFSSL_ARM_POLY1305_NEED_C
795
#ifdef WOLFSSL_ARM_POLY1305_NEON_FALLBACK
796
static cpuid_flags_t poly1305_cpuid_flags = WC_CPUID_INITIALIZER;
797
/* Return non-zero when NEON/ASIMD is present and the asm path should run. */
798
static WC_INLINE int poly1305_use_neon(void)
799
{
800
    cpuid_get_flags_ex(&poly1305_cpuid_flags);
801
    return IS_AARCH64_ASIMD(poly1305_cpuid_flags);
802
}
803
#endif
804
805
/* Dispatch each Poly1305 operation to the NEON assembly or the C
806
 * implementation, choosing at runtime when both are available. */
807
static void poly1305_blocks_aarch64(Poly1305* ctx, const unsigned char* m,
808
    size_t bytes)
809
{
810
#ifdef WOLFSSL_ARM_POLY1305_C_ONLY
811
    poly1305_c_blocks(ctx, m, bytes);
812
#else
813
    if (poly1305_use_neon())
814
        poly1305_arm64_blocks(ctx, m, bytes);
815
    else
816
        poly1305_c_blocks(ctx, m, bytes);
817
#endif
818
}
819
820
static void poly1305_block_aarch64(Poly1305* ctx, const unsigned char* m)
821
{
822
#ifdef WOLFSSL_ARM_POLY1305_C_ONLY
823
    poly1305_c_blocks(ctx, m, POLY1305_BLOCK_SIZE);
824
#else
825
    if (poly1305_use_neon())
826
        poly1305_arm64_block_16(ctx, m);
827
    else
828
        poly1305_c_blocks(ctx, m, POLY1305_BLOCK_SIZE);
829
#endif
830
}
831
832
static void poly1305_setkey_aarch64(Poly1305* ctx, const byte* key)
833
{
834
#ifdef WOLFSSL_ARM_POLY1305_C_ONLY
835
    poly1305_c_setkey(ctx, key);
836
#else
837
    if (poly1305_use_neon())
838
        poly1305_set_key(ctx, key);
839
    else
840
        poly1305_c_setkey(ctx, key);
841
#endif
842
}
843
844
static void poly1305_final_aarch64(Poly1305* ctx, byte* mac)
845
{
846
#ifdef WOLFSSL_ARM_POLY1305_C_ONLY
847
    poly1305_c_final(ctx, mac);
848
#else
849
    if (poly1305_use_neon())
850
        poly1305_final(ctx, mac);
851
    else
852
        poly1305_c_final(ctx, mac);
853
#endif
854
}
855
856
#endif /* WOLFSSL_ARM_POLY1305_NEED_C */
857
858
#if !defined(WOLFSSL_RISCV_ASM)
859
/*
860
This local function operates on a message with a given number of bytes
861
with a given ctx pointer to a Poly1305 structure.
862
*/
863
static int poly1305_blocks(Poly1305* ctx, const unsigned char *m,
864
                     size_t bytes)
865
1.90k
{
866
#ifdef USE_INTEL_POLY1305_SPEEDUP
867
    /* AVX2 is handled in wc_Poly1305Update. */
868
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
869
    poly1305_blocks_avx(ctx, m, bytes);
870
    RESTORE_VECTOR_REGISTERS();
871
    return 0;
872
#elif defined(WOLFSSL_ARMASM) && defined(__aarch64__)
873
    poly1305_blocks_aarch64(ctx, m, bytes);
874
    return 0;
875
#elif defined(WOLFSSL_ARMASM) && defined(WOLFSSL_ARMASM_THUMB2)
876
    poly1305_blocks_thumb2_16(ctx, m, bytes, 1);
877
    return 0;
878
#elif defined(WOLFSSL_ARMASM)
879
#ifndef WOLFSSL_ARMASM_NO_NEON
880
    poly1305_arm32_blocks(ctx, m, bytes);
881
    return 0;
882
#else
883
    poly1305_arm32_blocks_16(ctx, m, bytes, 1);
884
    return 0;
885
#endif
886
#else
887
1.90k
    return poly1305_c_blocks(ctx, m, bytes);
888
1.90k
#endif
889
1.90k
}
890
#endif /* !WOLFSSL_RISCV_ASM */
891
892
/*
893
This local function is used for the last call when a message with a given
894
number of bytes is less than the block size.
895
*/
896
static WC_INLINE int poly1305_block(Poly1305* ctx, const unsigned char *m)
897
989
{
898
#ifdef USE_INTEL_POLY1305_SPEEDUP
899
    /* No call to poly1305_block when AVX2, AVX2 does 4 blocks at a time. */
900
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
901
    poly1305_block_avx(ctx, m);
902
    RESTORE_VECTOR_REGISTERS();
903
    return 0;
904
#elif defined(WOLFSSL_ARMASM) && defined(WOLFSSL_ARMASM_THUMB2)
905
    poly1305_blocks_thumb2_16(ctx, m, POLY1305_BLOCK_SIZE, !ctx->finished);
906
    return 0;
907
#elif defined(WOLFSSL_ARMASM) && !defined(__aarch64__)
908
    poly1305_arm32_blocks_16(ctx, m, POLY1305_BLOCK_SIZE, !ctx->finished);
909
    return 0;
910
#elif defined(WOLFSSL_ARMASM)
911
    poly1305_block_aarch64(ctx, m);
912
    return 0;
913
#elif defined(WOLFSSL_RISCV_ASM)
914
    poly1305_block_16_riscv64(ctx, m);
915
    return 0;
916
#else
917
989
    return poly1305_blocks(ctx, m, POLY1305_BLOCK_SIZE);
918
989
#endif
919
989
}
920
921
int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz)
922
494
{
923
924
494
    if (key == NULL)
925
0
        return BAD_FUNC_ARG;
926
927
#ifdef CHACHA_AEAD_TEST
928
    word32 k;
929
    printf("Poly key used:\n");
930
    for (k = 0; k < keySz; k++) {
931
        printf("%02x", key[k]);
932
        if ((k+1) % 8 == 0)
933
            printf("\n");
934
    }
935
    printf("\n");
936
#endif
937
938
494
    if ((ctx == NULL) || (key == NULL) || (keySz != 32)) {
939
0
        return BAD_FUNC_ARG;
940
0
    }
941
942
#ifdef USE_INTEL_POLY1305_SPEEDUP
943
    cpuid_get_flags_ex(&intel_flags);
944
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
945
    #ifdef HAVE_INTEL_AVX512
946
    if (poly1305_use_ifma(intel_flags))
947
        poly1305_setkey_avx512ifma(ctx, key);
948
    else
949
    #endif
950
    #ifdef HAVE_INTEL_AVX2
951
    if (IS_INTEL_AVX2(intel_flags))
952
        poly1305_setkey_avx2(ctx, key);
953
    else
954
    #endif
955
        poly1305_setkey_avx(ctx, key);
956
    RESTORE_VECTOR_REGISTERS();
957
    ctx->started = 0;
958
#ifdef WOLFSSL_CHACHA20_POLY1305_FUSED
959
    ctx->forceAvx2 = 0;
960
#endif
961
#ifdef WOLFSSL_CHACHA20_POLY1305_FUSED_IFMA
962
    ctx->forceScalar = 0;
963
#endif
964
#elif defined(WOLFSSL_ARMASM)
965
#ifdef __aarch64__
966
    poly1305_setkey_aarch64(ctx, key);
967
#else
968
    poly1305_set_key(ctx, key);
969
#endif
970
    ctx->finished = 0;
971
#elif defined(WOLFSSL_RISCV_ASM)
972
    poly1305_set_key_riscv64(ctx, key);
973
#else
974
494
    poly1305_c_setkey(ctx, key);
975
494
#endif
976
977
494
    return 0;
978
494
}
979
980
int wc_Poly1305Final(Poly1305* ctx, byte* mac)
981
494
{
982
494
    if (ctx == NULL || mac == NULL)
983
0
        return BAD_FUNC_ARG;
984
985
#ifdef USE_INTEL_POLY1305_SPEEDUP
986
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
987
    #ifdef HAVE_INTEL_AVX512
988
    if (!POLY1305_FORCE_AVX2(ctx) && !POLY1305_FORCE_SCALAR(ctx) &&
989
            poly1305_use_ifma(intel_flags))
990
        poly1305_final_avx512ifma(ctx, mac);
991
    else
992
    if (!POLY1305_FORCE_AVX2(ctx) && !POLY1305_FORCE_SCALAR(ctx) &&
993
            poly1305_use_avx512(intel_flags))
994
        poly1305_final_avx512(ctx, mac);
995
    else
996
    #endif
997
    #ifdef HAVE_INTEL_AVX2
998
    if (!POLY1305_FORCE_SCALAR(ctx) && IS_INTEL_AVX2(intel_flags))
999
        poly1305_final_avx2(ctx, mac);
1000
    else
1001
    #endif
1002
        poly1305_final_avx(ctx, mac);
1003
    RESTORE_VECTOR_REGISTERS();
1004
#elif defined(WOLFSSL_ARMASM)
1005
    #if !defined(WOLFSSL_ARMASM_THUMB2) && !defined(WOLFSSL_ARMASM_NO_NEON) && \
1006
        !defined(__aarch64__)
1007
        if (ctx->leftover >= POLY1305_BLOCK_SIZE) {
1008
             size_t len = ctx->leftover & (~(POLY1305_BLOCK_SIZE - 1));
1009
             poly1305_arm32_blocks(ctx, ctx->buffer, len);
1010
             ctx->leftover -= len;
1011
             if (ctx->leftover) {
1012
                 XMEMCPY(ctx->buffer, ctx->buffer + len, ctx->leftover);
1013
             }
1014
        }
1015
    #endif
1016
        if (ctx->leftover) {
1017
             size_t i = ctx->leftover;
1018
             ctx->buffer[i++] = 1;
1019
             for (; i < POLY1305_BLOCK_SIZE; i++) {
1020
                 ctx->buffer[i] = 0;
1021
             }
1022
            ctx->finished = 1;
1023
            poly1305_block(ctx, ctx->buffer);
1024
        }
1025
1026
#ifdef __aarch64__
1027
        poly1305_final_aarch64(ctx, mac);
1028
#else
1029
        poly1305_final(ctx, mac);
1030
#endif
1031
#elif defined(WOLFSSL_RISCV_ASM)
1032
    /* process the remaining block */
1033
    if (ctx->leftover) {
1034
        size_t i = ctx->leftover;
1035
        ctx->buffer[i] = 1;
1036
        for (i = i + 1; i < POLY1305_BLOCK_SIZE; i++)
1037
            ctx->buffer[i] = 0;
1038
        ctx->finished = 1;
1039
        poly1305_block_16_riscv64(ctx, ctx->buffer);
1040
    }
1041
1042
    poly1305_final_riscv64(ctx, mac);
1043
#else
1044
    /* process the remaining block */
1045
494
    if (ctx->leftover) {
1046
9
        size_t i = ctx->leftover;
1047
9
        ctx->buffer[i++] = 1;
1048
52
        for (; i < POLY1305_BLOCK_SIZE; i++)
1049
43
            ctx->buffer[i] = 0;
1050
9
        ctx->finished = 1;
1051
9
        poly1305_block(ctx, ctx->buffer);
1052
9
    }
1053
494
    poly1305_c_final(ctx, mac);
1054
494
#endif
1055
1056
494
    return 0;
1057
494
}
1058
1059
1060
int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes)
1061
2.45k
{
1062
2.45k
    size_t i;
1063
1064
2.45k
    if (ctx == NULL || (m == NULL && bytes > 0))
1065
0
        return BAD_FUNC_ARG;
1066
1067
2.45k
    if (bytes == 0) {
1068
        /* valid, but do nothing */
1069
2
        return 0;
1070
2
    }
1071
#ifdef CHACHA_AEAD_TEST
1072
    word32 k;
1073
    printf("Raw input to poly:\n");
1074
    for (k = 0; k < bytes; k++) {
1075
        printf("%02x", m[k]);
1076
        if ((k+1) % 16 == 0)
1077
            printf("\n");
1078
    }
1079
    printf("\n");
1080
#endif
1081
1082
#if defined(WOLFSSL_ARMASM) && !defined(WOLFSSL_ARMASM_THUMB2) && \
1083
    !defined(WOLFSSL_ARMASM_NO_NEON)
1084
    /* handle leftover */
1085
    if (ctx->leftover) {
1086
        size_t want = sizeof(ctx->buffer) - ctx->leftover;
1087
        if (want > bytes)
1088
            want = bytes;
1089
1090
        for (i = 0; i < want; i++)
1091
            ctx->buffer[ctx->leftover + i] = m[i];
1092
        bytes -= (word32)want;
1093
        m += want;
1094
        ctx->leftover += want;
1095
        if (ctx->leftover < sizeof(ctx->buffer)) {
1096
            return 0;
1097
        }
1098
1099
        poly1305_blocks(ctx, ctx->buffer, sizeof(ctx->buffer));
1100
        ctx->leftover = 0;
1101
    }
1102
1103
    /* process full blocks */
1104
    if (bytes >= sizeof(ctx->buffer)) {
1105
        size_t want = bytes & ~((size_t)POLY1305_BLOCK_SIZE - 1);
1106
1107
        poly1305_blocks(ctx, m, want);
1108
        m += want;
1109
        bytes -= (word32)want;
1110
    }
1111
1112
    /* store leftover */
1113
    if (bytes) {
1114
        for (i = 0; i < bytes; i++)
1115
            ctx->buffer[ctx->leftover + i] = m[i];
1116
        ctx->leftover += bytes;
1117
    }
1118
#else
1119
#ifdef USE_INTEL_POLY1305_SPEEDUP
1120
    #ifdef HAVE_INTEL_AVX512
1121
    if (!POLY1305_FORCE_AVX2(ctx) && !POLY1305_FORCE_SCALAR(ctx) &&
1122
            poly1305_use_ifma(intel_flags)) {
1123
        SAVE_VECTOR_REGISTERS(return _svr_ret;);
1124
1125
        /* handle leftover */
1126
        if (ctx->leftover) {
1127
            size_t want = sizeof(ctx->buffer) - ctx->leftover;
1128
            if (want > bytes)
1129
                want = bytes;
1130
1131
            for (i = 0; i < want; i++)
1132
                ctx->buffer[ctx->leftover + i] = m[i];
1133
            bytes -= (word32)want;
1134
            m += want;
1135
            ctx->leftover += want;
1136
            if (ctx->leftover < sizeof(ctx->buffer)) {
1137
                RESTORE_VECTOR_REGISTERS();
1138
                return 0;
1139
            }
1140
1141
            if (!ctx->started) {
1142
                poly1305_calc_powers_avx512ifma(ctx);
1143
                ctx->started = 1;
1144
            }
1145
            poly1305_blocks_avx512ifma(ctx, ctx->buffer, sizeof(ctx->buffer));
1146
            ctx->leftover = 0;
1147
        }
1148
1149
        /* process full blocks */
1150
        if (bytes >= sizeof(ctx->buffer)) {
1151
            size_t want = bytes & ~(sizeof(ctx->buffer) - 1);
1152
1153
            if (!ctx->started) {
1154
                poly1305_calc_powers_avx512ifma(ctx);
1155
                ctx->started = 1;
1156
            }
1157
            poly1305_blocks_avx512ifma(ctx, m, want);
1158
            m += want;
1159
            bytes -= (word32)want;
1160
        }
1161
1162
        /* store leftover */
1163
        if (bytes) {
1164
            for (i = 0; i < bytes; i++)
1165
                ctx->buffer[ctx->leftover + i] = m[i];
1166
            ctx->leftover += bytes;
1167
        }
1168
        RESTORE_VECTOR_REGISTERS();
1169
    }
1170
    else
1171
    if (!POLY1305_FORCE_AVX2(ctx) && !POLY1305_FORCE_SCALAR(ctx) &&
1172
            poly1305_use_avx512(intel_flags)) {
1173
        SAVE_VECTOR_REGISTERS(return _svr_ret;);
1174
1175
        /* handle leftover */
1176
        if (ctx->leftover) {
1177
            size_t want = sizeof(ctx->buffer) - ctx->leftover;
1178
            if (want > bytes)
1179
                want = bytes;
1180
1181
            for (i = 0; i < want; i++)
1182
                ctx->buffer[ctx->leftover + i] = m[i];
1183
            bytes -= (word32)want;
1184
            m += want;
1185
            ctx->leftover += want;
1186
            if (ctx->leftover < sizeof(ctx->buffer)) {
1187
                RESTORE_VECTOR_REGISTERS();
1188
                return 0;
1189
            }
1190
1191
            if (!ctx->started) {
1192
                poly1305_calc_powers_avx512(ctx);
1193
                ctx->started = 1;
1194
            }
1195
            poly1305_blocks_avx512(ctx, ctx->buffer, sizeof(ctx->buffer));
1196
            ctx->leftover = 0;
1197
        }
1198
1199
        /* process full blocks */
1200
        if (bytes >= sizeof(ctx->buffer)) {
1201
            size_t want = bytes & ~(sizeof(ctx->buffer) - 1);
1202
1203
            if (!ctx->started) {
1204
                poly1305_calc_powers_avx512(ctx);
1205
                ctx->started = 1;
1206
            }
1207
            poly1305_blocks_avx512(ctx, m, want);
1208
            m += want;
1209
            bytes -= (word32)want;
1210
        }
1211
1212
        /* store leftover */
1213
        if (bytes) {
1214
            for (i = 0; i < bytes; i++)
1215
                ctx->buffer[ctx->leftover + i] = m[i];
1216
            ctx->leftover += bytes;
1217
        }
1218
        RESTORE_VECTOR_REGISTERS();
1219
    }
1220
    else
1221
    #endif
1222
    #ifdef HAVE_INTEL_AVX2
1223
    if (!POLY1305_FORCE_SCALAR(ctx) && IS_INTEL_AVX2(intel_flags)) {
1224
        SAVE_VECTOR_REGISTERS(return _svr_ret;);
1225
1226
        /* handle leftover */
1227
        if (ctx->leftover) {
1228
            size_t want = sizeof(ctx->buffer) - ctx->leftover;
1229
            if (want > bytes)
1230
                want = bytes;
1231
1232
            for (i = 0; i < want; i++)
1233
                ctx->buffer[ctx->leftover + i] = m[i];
1234
            bytes -= (word32)want;
1235
            m += want;
1236
            ctx->leftover += want;
1237
            if (ctx->leftover < sizeof(ctx->buffer)) {
1238
                RESTORE_VECTOR_REGISTERS();
1239
                return 0;
1240
            }
1241
1242
            if (!ctx->started) {
1243
                poly1305_calc_powers_avx2(ctx);
1244
                ctx->started = 1;
1245
            }
1246
            poly1305_blocks_avx2(ctx, ctx->buffer, sizeof(ctx->buffer));
1247
            ctx->leftover = 0;
1248
        }
1249
1250
        /* process full blocks */
1251
        if (bytes >= sizeof(ctx->buffer)) {
1252
            size_t want = bytes & ~(sizeof(ctx->buffer) - 1);
1253
1254
            if (!ctx->started) {
1255
                poly1305_calc_powers_avx2(ctx);
1256
                ctx->started = 1;
1257
            }
1258
            poly1305_blocks_avx2(ctx, m, want);
1259
            m += want;
1260
            bytes -= (word32)want;
1261
        }
1262
1263
        /* store leftover */
1264
        if (bytes) {
1265
            for (i = 0; i < bytes; i++)
1266
                ctx->buffer[ctx->leftover + i] = m[i];
1267
            ctx->leftover += bytes;
1268
        }
1269
        RESTORE_VECTOR_REGISTERS();
1270
    }
1271
    else
1272
    #endif
1273
#endif
1274
2.45k
    {
1275
        /* handle leftover */
1276
2.45k
        if (ctx->leftover) {
1277
991
            size_t want = (POLY1305_BLOCK_SIZE - ctx->leftover);
1278
991
            if (want > bytes)
1279
11
                want = bytes;
1280
10.5k
            for (i = 0; i < want; i++)
1281
9.52k
                ctx->buffer[ctx->leftover + i] = m[i];
1282
991
            bytes -= (word32)want;
1283
991
            m += want;
1284
991
            ctx->leftover += want;
1285
991
            if (ctx->leftover < POLY1305_BLOCK_SIZE)
1286
11
                return 0;
1287
980
            poly1305_block(ctx, ctx->buffer);
1288
980
            ctx->leftover = 0;
1289
980
        }
1290
1291
        /* process full blocks */
1292
2.44k
        if (bytes >= POLY1305_BLOCK_SIZE) {
1293
912
            size_t want = ((size_t)bytes & ~((size_t)POLY1305_BLOCK_SIZE - 1));
1294
912
#if !defined(WOLFSSL_ARMASM) && !defined(WOLFSSL_RISCV_ASM)
1295
912
            int ret;
1296
912
            ret = poly1305_blocks(ctx, m, want);
1297
912
            if (ret != 0)
1298
0
                return ret;
1299
#else
1300
            poly1305_blocks(ctx, m, want);
1301
#endif
1302
912
            m += want;
1303
912
            bytes -= (word32)want;
1304
912
        }
1305
1306
        /* store leftover */
1307
2.44k
        if (bytes) {
1308
7.23k
            for (i = 0; i < bytes; i++)
1309
6.24k
                ctx->buffer[ctx->leftover + i] = m[i];
1310
989
            ctx->leftover += bytes;
1311
989
        }
1312
2.44k
    }
1313
0
#endif
1314
1315
0
    return 0;
1316
2.44k
}
1317
1318
/*  Takes a Poly1305 struct that has a key loaded and pads the provided length
1319
    ctx        : Initialized Poly1305 struct to use
1320
    lenToPad   : Current number of bytes updated that needs padding to 16
1321
 */
1322
int wc_Poly1305_Pad(Poly1305* ctx, word32 lenToPad)
1323
968
{
1324
968
    int ret = 0;
1325
968
    word32 paddingLen;
1326
968
    byte padding[WC_POLY1305_PAD_SZ - 1];
1327
1328
968
    if (ctx == NULL) {
1329
0
        return BAD_FUNC_ARG;
1330
0
    }
1331
968
    if (lenToPad == 0) {
1332
2
        return 0; /* nothing needs to be done */
1333
2
    }
1334
1335
966
    XMEMSET(padding, 0, sizeof(padding));
1336
1337
    /* Pad length to 16 bytes */
1338
966
    paddingLen = (-(int)lenToPad) & (WC_POLY1305_PAD_SZ - 1);
1339
966
    if ((paddingLen > 0) && (paddingLen < WC_POLY1305_PAD_SZ)) {
1340
961
        ret = wc_Poly1305Update(ctx, padding, paddingLen);
1341
961
    }
1342
966
    return ret;
1343
968
}
1344
1345
/*  Takes a Poly1305 struct that has a key loaded and adds the AEAD length
1346
    encoding in 64-bit little endian
1347
    aadSz      : Size of the additional authentication data
1348
    dataSz     : Size of the plaintext or ciphertext
1349
 */
1350
int wc_Poly1305_EncodeSizes(Poly1305* ctx, word32 aadSz, word32 dataSz)
1351
484
{
1352
484
    int ret;
1353
484
    byte little64[16]; /* sizeof(word64) * 2 */
1354
1355
484
    if (ctx == NULL) {
1356
0
        return BAD_FUNC_ARG;
1357
0
    }
1358
1359
484
    XMEMSET(little64, 0, sizeof(little64));
1360
1361
    /* size of additional data and input data as little endian 64 bit types */
1362
484
    u32tole64(aadSz,  little64);
1363
484
    u32tole64(dataSz, little64 + 8);
1364
484
    ret = wc_Poly1305Update(ctx, little64, sizeof(little64));
1365
1366
484
    return ret;
1367
484
}
1368
1369
#ifdef WORD64_AVAILABLE
1370
int wc_Poly1305_EncodeSizes64(Poly1305* ctx, word64 aadSz, word64 dataSz)
1371
0
{
1372
0
    int ret;
1373
0
    word64 little64[2];
1374
1375
0
    if (ctx == NULL) {
1376
0
        return BAD_FUNC_ARG;
1377
0
    }
1378
1379
#ifdef BIG_ENDIAN_ORDER
1380
    little64[0] = ByteReverseWord64(aadSz);
1381
    little64[1] = ByteReverseWord64(dataSz);
1382
#else
1383
0
    little64[0] = aadSz;
1384
0
    little64[1] = dataSz;
1385
0
#endif
1386
1387
0
    ret = wc_Poly1305Update(ctx, (byte *)little64, sizeof(little64));
1388
1389
0
    return ret;
1390
0
}
1391
#endif
1392
1393
/*  Takes in an initialized Poly1305 struct that has a key loaded and creates
1394
    a MAC (tag) using recent TLS AEAD padding scheme.
1395
    ctx        : Initialized Poly1305 struct to use
1396
    additional : Additional data to use
1397
    addSz      : Size of additional buffer
1398
    input      : Input buffer to create tag from
1399
    sz         : Size of input buffer
1400
    tag        : Buffer to hold created tag
1401
    tagSz      : Size of input tag buffer (must be at least
1402
                 WC_POLY1305_MAC_SZ(16))
1403
 */
1404
int wc_Poly1305_MAC(Poly1305* ctx, const byte* additional, word32 addSz,
1405
                    const byte* input, word32 sz, byte* tag, word32 tagSz)
1406
484
{
1407
484
    int ret;
1408
1409
    /* sanity check on arguments */
1410
484
    if (ctx == NULL || input == NULL || tag == NULL ||
1411
484
                                                   tagSz < WC_POLY1305_MAC_SZ) {
1412
0
        return BAD_FUNC_ARG;
1413
0
    }
1414
1415
    /* additional allowed to be 0 */
1416
484
    if (addSz > 0) {
1417
484
        if (additional == NULL)
1418
0
            return BAD_FUNC_ARG;
1419
1420
        /* additional data plus padding */
1421
484
        if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) {
1422
0
            return ret;
1423
0
        }
1424
        /* pad additional data */
1425
484
        if ((ret = wc_Poly1305_Pad(ctx, addSz)) != 0) {
1426
0
            return ret;
1427
0
        }
1428
484
    }
1429
1430
    /* input plus padding */
1431
484
    if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) {
1432
0
        return ret;
1433
0
    }
1434
    /* pad input data */
1435
484
    if ((ret = wc_Poly1305_Pad(ctx, sz)) != 0) {
1436
0
        return ret;
1437
0
    }
1438
1439
    /* encode size of AAD and input data as little endian 64 bit types */
1440
484
    if ((ret = wc_Poly1305_EncodeSizes(ctx, addSz, sz)) != 0) {
1441
0
        return ret;
1442
0
    }
1443
1444
    /* Finalize the auth tag */
1445
484
    ret = wc_Poly1305Final(ctx, tag);
1446
1447
484
    return ret;
1448
1449
484
}
1450
#endif /* HAVE_POLY1305 */