Coverage Report

Created: 2025-03-01 06:26

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