Coverage Report

Created: 2025-07-01 06:54

/work/mbedtls-2.28.8/library/poly1305.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * \file poly1305.c
3
 *
4
 * \brief Poly1305 authentication algorithm.
5
 *
6
 *  Copyright The Mbed TLS Contributors
7
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
8
 */
9
#include "common.h"
10
11
#if defined(MBEDTLS_POLY1305_C)
12
13
#include "mbedtls/poly1305.h"
14
#include "mbedtls/platform_util.h"
15
#include "mbedtls/error.h"
16
17
#include <string.h>
18
19
#include "mbedtls/platform.h"
20
21
#if !defined(MBEDTLS_POLY1305_ALT)
22
23
/* Parameter validation macros */
24
#define POLY1305_VALIDATE_RET(cond)                                       \
25
0
    MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA)
26
#define POLY1305_VALIDATE(cond)                                           \
27
0
    MBEDTLS_INTERNAL_VALIDATE(cond)
28
29
0
#define POLY1305_BLOCK_SIZE_BYTES (16U)
30
31
/*
32
 * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier.
33
 * However we provided an alternative for platforms without such a multiplier.
34
 */
35
#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
36
static uint64_t mul64(uint32_t a, uint32_t b)
37
{
38
    /* a = al + 2**16 ah, b = bl + 2**16 bh */
39
    const uint16_t al = (uint16_t) a;
40
    const uint16_t bl = (uint16_t) b;
41
    const uint16_t ah = a >> 16;
42
    const uint16_t bh = b >> 16;
43
44
    /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */
45
    const uint32_t lo = (uint32_t) al * bl;
46
    const uint64_t me = (uint64_t) ((uint32_t) ah * bl) + (uint32_t) al * bh;
47
    const uint32_t hi = (uint32_t) ah * bh;
48
49
    return lo + (me << 16) + ((uint64_t) hi << 32);
50
}
51
#else
52
static inline uint64_t mul64(uint32_t a, uint32_t b)
53
0
{
54
0
    return (uint64_t) a * b;
55
0
}
56
#endif
57
58
59
/**
60
 * \brief                   Process blocks with Poly1305.
61
 *
62
 * \param ctx               The Poly1305 context.
63
 * \param nblocks           Number of blocks to process. Note that this
64
 *                          function only processes full blocks.
65
 * \param input             Buffer containing the input block(s).
66
 * \param needs_padding     Set to 0 if the padding bit has already been
67
 *                          applied to the input data before calling this
68
 *                          function.  Otherwise, set this parameter to 1.
69
 */
70
static void poly1305_process(mbedtls_poly1305_context *ctx,
71
                             size_t nblocks,
72
                             const unsigned char *input,
73
                             uint32_t needs_padding)
74
0
{
75
0
    uint64_t d0, d1, d2, d3;
76
0
    uint32_t acc0, acc1, acc2, acc3, acc4;
77
0
    uint32_t r0, r1, r2, r3;
78
0
    uint32_t rs1, rs2, rs3;
79
0
    size_t offset  = 0U;
80
0
    size_t i;
81
82
0
    r0 = ctx->r[0];
83
0
    r1 = ctx->r[1];
84
0
    r2 = ctx->r[2];
85
0
    r3 = ctx->r[3];
86
87
0
    rs1 = r1 + (r1 >> 2U);
88
0
    rs2 = r2 + (r2 >> 2U);
89
0
    rs3 = r3 + (r3 >> 2U);
90
91
0
    acc0 = ctx->acc[0];
92
0
    acc1 = ctx->acc[1];
93
0
    acc2 = ctx->acc[2];
94
0
    acc3 = ctx->acc[3];
95
0
    acc4 = ctx->acc[4];
96
97
    /* Process full blocks */
98
0
    for (i = 0U; i < nblocks; i++) {
99
        /* The input block is treated as a 128-bit little-endian integer */
100
0
        d0   = MBEDTLS_GET_UINT32_LE(input, offset + 0);
101
0
        d1   = MBEDTLS_GET_UINT32_LE(input, offset + 4);
102
0
        d2   = MBEDTLS_GET_UINT32_LE(input, offset + 8);
103
0
        d3   = MBEDTLS_GET_UINT32_LE(input, offset + 12);
104
105
        /* Compute: acc += (padded) block as a 130-bit integer */
106
0
        d0  += (uint64_t) acc0;
107
0
        d1  += (uint64_t) acc1 + (d0 >> 32U);
108
0
        d2  += (uint64_t) acc2 + (d1 >> 32U);
109
0
        d3  += (uint64_t) acc3 + (d2 >> 32U);
110
0
        acc0 = (uint32_t) d0;
111
0
        acc1 = (uint32_t) d1;
112
0
        acc2 = (uint32_t) d2;
113
0
        acc3 = (uint32_t) d3;
114
0
        acc4 += (uint32_t) (d3 >> 32U) + needs_padding;
115
116
        /* Compute: acc *= r */
117
0
        d0 = mul64(acc0, r0) +
118
0
             mul64(acc1, rs3) +
119
0
             mul64(acc2, rs2) +
120
0
             mul64(acc3, rs1);
121
0
        d1 = mul64(acc0, r1) +
122
0
             mul64(acc1, r0) +
123
0
             mul64(acc2, rs3) +
124
0
             mul64(acc3, rs2) +
125
0
             mul64(acc4, rs1);
126
0
        d2 = mul64(acc0, r2) +
127
0
             mul64(acc1, r1) +
128
0
             mul64(acc2, r0) +
129
0
             mul64(acc3, rs3) +
130
0
             mul64(acc4, rs2);
131
0
        d3 = mul64(acc0, r3) +
132
0
             mul64(acc1, r2) +
133
0
             mul64(acc2, r1) +
134
0
             mul64(acc3, r0) +
135
0
             mul64(acc4, rs3);
136
0
        acc4 *= r0;
137
138
        /* Compute: acc %= (2^130 - 5) (partial remainder) */
139
0
        d1 += (d0 >> 32);
140
0
        d2 += (d1 >> 32);
141
0
        d3 += (d2 >> 32);
142
0
        acc0 = (uint32_t) d0;
143
0
        acc1 = (uint32_t) d1;
144
0
        acc2 = (uint32_t) d2;
145
0
        acc3 = (uint32_t) d3;
146
0
        acc4 = (uint32_t) (d3 >> 32) + acc4;
147
148
0
        d0 = (uint64_t) acc0 + (acc4 >> 2) + (acc4 & 0xFFFFFFFCU);
149
0
        acc4 &= 3U;
150
0
        acc0 = (uint32_t) d0;
151
0
        d0 = (uint64_t) acc1 + (d0 >> 32U);
152
0
        acc1 = (uint32_t) d0;
153
0
        d0 = (uint64_t) acc2 + (d0 >> 32U);
154
0
        acc2 = (uint32_t) d0;
155
0
        d0 = (uint64_t) acc3 + (d0 >> 32U);
156
0
        acc3 = (uint32_t) d0;
157
0
        d0 = (uint64_t) acc4 + (d0 >> 32U);
158
0
        acc4 = (uint32_t) d0;
159
160
0
        offset    += POLY1305_BLOCK_SIZE_BYTES;
161
0
    }
162
163
0
    ctx->acc[0] = acc0;
164
0
    ctx->acc[1] = acc1;
165
0
    ctx->acc[2] = acc2;
166
0
    ctx->acc[3] = acc3;
167
0
    ctx->acc[4] = acc4;
168
0
}
169
170
/**
171
 * \brief                   Compute the Poly1305 MAC
172
 *
173
 * \param ctx               The Poly1305 context.
174
 * \param mac               The buffer to where the MAC is written. Must be
175
 *                          big enough to contain the 16-byte MAC.
176
 */
177
static void poly1305_compute_mac(const mbedtls_poly1305_context *ctx,
178
                                 unsigned char mac[16])
179
0
{
180
0
    uint64_t d;
181
0
    uint32_t g0, g1, g2, g3, g4;
182
0
    uint32_t acc0, acc1, acc2, acc3, acc4;
183
0
    uint32_t mask;
184
0
    uint32_t mask_inv;
185
186
0
    acc0 = ctx->acc[0];
187
0
    acc1 = ctx->acc[1];
188
0
    acc2 = ctx->acc[2];
189
0
    acc3 = ctx->acc[3];
190
0
    acc4 = ctx->acc[4];
191
192
    /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5.
193
     * We do this by calculating acc - (2^130 - 5), then checking if
194
     * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5)
195
     */
196
197
    /* Calculate acc + -(2^130 - 5) */
198
0
    d  = ((uint64_t) acc0 + 5U);
199
0
    g0 = (uint32_t) d;
200
0
    d  = ((uint64_t) acc1 + (d >> 32));
201
0
    g1 = (uint32_t) d;
202
0
    d  = ((uint64_t) acc2 + (d >> 32));
203
0
    g2 = (uint32_t) d;
204
0
    d  = ((uint64_t) acc3 + (d >> 32));
205
0
    g3 = (uint32_t) d;
206
0
    g4 = acc4 + (uint32_t) (d >> 32U);
207
208
    /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */
209
0
    mask = (uint32_t) 0U - (g4 >> 2U);
210
0
    mask_inv = ~mask;
211
212
    /* If 131st bit is set then acc=g, otherwise, acc is unmodified */
213
0
    acc0 = (acc0 & mask_inv) | (g0 & mask);
214
0
    acc1 = (acc1 & mask_inv) | (g1 & mask);
215
0
    acc2 = (acc2 & mask_inv) | (g2 & mask);
216
0
    acc3 = (acc3 & mask_inv) | (g3 & mask);
217
218
    /* Add 's' */
219
0
    d = (uint64_t) acc0 + ctx->s[0];
220
0
    acc0 = (uint32_t) d;
221
0
    d = (uint64_t) acc1 + ctx->s[1] + (d >> 32U);
222
0
    acc1 = (uint32_t) d;
223
0
    d = (uint64_t) acc2 + ctx->s[2] + (d >> 32U);
224
0
    acc2 = (uint32_t) d;
225
0
    acc3 += ctx->s[3] + (uint32_t) (d >> 32U);
226
227
    /* Compute MAC (128 least significant bits of the accumulator) */
228
0
    MBEDTLS_PUT_UINT32_LE(acc0, mac,  0);
229
0
    MBEDTLS_PUT_UINT32_LE(acc1, mac,  4);
230
0
    MBEDTLS_PUT_UINT32_LE(acc2, mac,  8);
231
0
    MBEDTLS_PUT_UINT32_LE(acc3, mac, 12);
232
0
}
233
234
void mbedtls_poly1305_init(mbedtls_poly1305_context *ctx)
235
0
{
236
0
    POLY1305_VALIDATE(ctx != NULL);
237
238
0
    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context));
239
0
}
240
241
void mbedtls_poly1305_free(mbedtls_poly1305_context *ctx)
242
0
{
243
0
    if (ctx == NULL) {
244
0
        return;
245
0
    }
246
247
0
    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context));
248
0
}
249
250
int mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx,
251
                            const unsigned char key[32])
252
0
{
253
0
    POLY1305_VALIDATE_RET(ctx != NULL);
254
0
    POLY1305_VALIDATE_RET(key != NULL);
255
256
    /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */
257
0
    ctx->r[0] = MBEDTLS_GET_UINT32_LE(key, 0)  & 0x0FFFFFFFU;
258
0
    ctx->r[1] = MBEDTLS_GET_UINT32_LE(key, 4)  & 0x0FFFFFFCU;
259
0
    ctx->r[2] = MBEDTLS_GET_UINT32_LE(key, 8)  & 0x0FFFFFFCU;
260
0
    ctx->r[3] = MBEDTLS_GET_UINT32_LE(key, 12) & 0x0FFFFFFCU;
261
262
0
    ctx->s[0] = MBEDTLS_GET_UINT32_LE(key, 16);
263
0
    ctx->s[1] = MBEDTLS_GET_UINT32_LE(key, 20);
264
0
    ctx->s[2] = MBEDTLS_GET_UINT32_LE(key, 24);
265
0
    ctx->s[3] = MBEDTLS_GET_UINT32_LE(key, 28);
266
267
    /* Initial accumulator state */
268
0
    ctx->acc[0] = 0U;
269
0
    ctx->acc[1] = 0U;
270
0
    ctx->acc[2] = 0U;
271
0
    ctx->acc[3] = 0U;
272
0
    ctx->acc[4] = 0U;
273
274
    /* Queue initially empty */
275
0
    mbedtls_platform_zeroize(ctx->queue, sizeof(ctx->queue));
276
0
    ctx->queue_len = 0U;
277
278
0
    return 0;
279
0
}
280
281
int mbedtls_poly1305_update(mbedtls_poly1305_context *ctx,
282
                            const unsigned char *input,
283
                            size_t ilen)
284
0
{
285
0
    size_t offset    = 0U;
286
0
    size_t remaining = ilen;
287
0
    size_t queue_free_len;
288
0
    size_t nblocks;
289
0
    POLY1305_VALIDATE_RET(ctx != NULL);
290
0
    POLY1305_VALIDATE_RET(ilen == 0 || input != NULL);
291
292
0
    if ((remaining > 0U) && (ctx->queue_len > 0U)) {
293
0
        queue_free_len = (POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len);
294
295
0
        if (ilen < queue_free_len) {
296
            /* Not enough data to complete the block.
297
             * Store this data with the other leftovers.
298
             */
299
0
            memcpy(&ctx->queue[ctx->queue_len],
300
0
                   input,
301
0
                   ilen);
302
303
0
            ctx->queue_len += ilen;
304
305
0
            remaining = 0U;
306
0
        } else {
307
            /* Enough data to produce a complete block */
308
0
            memcpy(&ctx->queue[ctx->queue_len],
309
0
                   input,
310
0
                   queue_free_len);
311
312
0
            ctx->queue_len = 0U;
313
314
0
            poly1305_process(ctx, 1U, ctx->queue, 1U);   /* add padding bit */
315
316
0
            offset    += queue_free_len;
317
0
            remaining -= queue_free_len;
318
0
        }
319
0
    }
320
321
0
    if (remaining >= POLY1305_BLOCK_SIZE_BYTES) {
322
0
        nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES;
323
324
0
        poly1305_process(ctx, nblocks, &input[offset], 1U);
325
326
0
        offset += nblocks * POLY1305_BLOCK_SIZE_BYTES;
327
0
        remaining %= POLY1305_BLOCK_SIZE_BYTES;
328
0
    }
329
330
0
    if (remaining > 0U) {
331
        /* Store partial block */
332
0
        ctx->queue_len = remaining;
333
0
        memcpy(ctx->queue, &input[offset], remaining);
334
0
    }
335
336
0
    return 0;
337
0
}
338
339
int mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx,
340
                            unsigned char mac[16])
341
0
{
342
0
    POLY1305_VALIDATE_RET(ctx != NULL);
343
0
    POLY1305_VALIDATE_RET(mac != NULL);
344
345
    /* Process any leftover data */
346
0
    if (ctx->queue_len > 0U) {
347
        /* Add padding bit */
348
0
        ctx->queue[ctx->queue_len] = 1U;
349
0
        ctx->queue_len++;
350
351
        /* Pad with zeroes */
352
0
        memset(&ctx->queue[ctx->queue_len],
353
0
               0,
354
0
               POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len);
355
356
0
        poly1305_process(ctx, 1U,           /* Process 1 block */
357
0
                         ctx->queue, 0U);   /* Already padded above */
358
0
    }
359
360
0
    poly1305_compute_mac(ctx, mac);
361
362
0
    return 0;
363
0
}
364
365
int mbedtls_poly1305_mac(const unsigned char key[32],
366
                         const unsigned char *input,
367
                         size_t ilen,
368
                         unsigned char mac[16])
369
0
{
370
0
    mbedtls_poly1305_context ctx;
371
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
372
0
    POLY1305_VALIDATE_RET(key != NULL);
373
0
    POLY1305_VALIDATE_RET(mac != NULL);
374
0
    POLY1305_VALIDATE_RET(ilen == 0 || input != NULL);
375
376
0
    mbedtls_poly1305_init(&ctx);
377
378
0
    ret = mbedtls_poly1305_starts(&ctx, key);
379
0
    if (ret != 0) {
380
0
        goto cleanup;
381
0
    }
382
383
0
    ret = mbedtls_poly1305_update(&ctx, input, ilen);
384
0
    if (ret != 0) {
385
0
        goto cleanup;
386
0
    }
387
388
0
    ret = mbedtls_poly1305_finish(&ctx, mac);
389
390
0
cleanup:
391
0
    mbedtls_poly1305_free(&ctx);
392
0
    return ret;
393
0
}
394
395
#endif /* MBEDTLS_POLY1305_ALT */
396
397
#if defined(MBEDTLS_SELF_TEST)
398
399
static const unsigned char test_keys[2][32] =
400
{
401
    {
402
        0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33,
403
        0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8,
404
        0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd,
405
        0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b
406
    },
407
    {
408
        0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a,
409
        0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0,
410
        0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09,
411
        0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0
412
    }
413
};
414
415
static const unsigned char test_data[2][127] =
416
{
417
    {
418
        0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72,
419
        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f,
420
        0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65,
421
        0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f,
422
        0x75, 0x70
423
    },
424
    {
425
        0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72,
426
        0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61,
427
        0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
428
        0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f,
429
        0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20,
430
        0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64,
431
        0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20,
432
        0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
433
        0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c,
434
        0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77,
435
        0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
436
        0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65,
437
        0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
438
        0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20,
439
        0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75,
440
        0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e
441
    }
442
};
443
444
static const size_t test_data_len[2] =
445
{
446
    34U,
447
    127U
448
};
449
450
static const unsigned char test_mac[2][16] =
451
{
452
    {
453
        0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6,
454
        0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9
455
    },
456
    {
457
        0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61,
458
        0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62
459
    }
460
};
461
462
/* Make sure no other definition is already present. */
463
#undef ASSERT
464
465
#define ASSERT(cond, args)            \
466
0
    do                                  \
467
0
    {                                   \
468
0
        if (!(cond))                \
469
0
        {                               \
470
0
            if (verbose != 0)          \
471
0
            mbedtls_printf args;    \
472
0
                                        \
473
0
            return -1;               \
474
0
        }                               \
475
0
    }                                   \
476
0
    while (0)
477
478
int mbedtls_poly1305_self_test(int verbose)
479
0
{
480
0
    unsigned char mac[16];
481
0
    unsigned i;
482
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
483
484
0
    for (i = 0U; i < 2U; i++) {
485
0
        if (verbose != 0) {
486
0
            mbedtls_printf("  Poly1305 test %u ", i);
487
0
        }
488
489
0
        ret = mbedtls_poly1305_mac(test_keys[i],
490
0
                                   test_data[i],
491
0
                                   test_data_len[i],
492
0
                                   mac);
493
0
        ASSERT(0 == ret, ("error code: %i\n", ret));
494
495
0
        ASSERT(0 == memcmp(mac, test_mac[i], 16U), ("failed (mac)\n"));
496
497
0
        if (verbose != 0) {
498
0
            mbedtls_printf("passed\n");
499
0
        }
500
0
    }
501
502
0
    if (verbose != 0) {
503
0
        mbedtls_printf("\n");
504
0
    }
505
506
0
    return 0;
507
0
}
508
509
#endif /* MBEDTLS_SELF_TEST */
510
511
#endif /* MBEDTLS_POLY1305_C */