1
2#include "poly1305_donna.h"
3#include "crypto_verify_16.h"
4#include "private/common.h"
5#include "utils.h"
6
7#ifdef HAVE_TI_MODE
8#include "poly1305_donna64.h"
9#else
10#include "poly1305_donna32.h"
11#endif
12#include "../onetimeauth_poly1305.h"
13
14static void
15poly1305_update(poly1305_state_internal_t *st, const unsigned char *m,
16                unsigned long long bytes)
17{
18    unsigned long long i;
19
20    /* handle leftover */
21    if (st->leftover) {
22        unsigned long long want = (poly1305_block_size - st->leftover);
23
24        if (want > bytes) {
25            want = bytes;
26        }
27        for (i = 0; i < want; i++) {
28            st->buffer[st->leftover + i] = m[i];
29        }
30        bytes -= want;
31        m += want;
32        st->leftover += want;
33        if (st->leftover < poly1305_block_size) {
34            return;
35        }
36        poly1305_blocks(st, st->buffer, poly1305_block_size);
37        st->leftover = 0;
38    }
39
40    /* process full blocks */
41    if (bytes >= poly1305_block_size) {
42        unsigned long long want = (bytes & ~(poly1305_block_size - 1));
43
44        poly1305_blocks(st, m, want);
45        m += want;
46        bytes -= want;
47    }
48
49    /* store leftover */
50    if (bytes) {
51        for (i = 0; i < bytes; i++) {
52            st->buffer[st->leftover + i] = m[i];
53        }
54        st->leftover += bytes;
55    }
56}
57
58static int
59crypto_onetimeauth_poly1305_donna(unsigned char *out, const unsigned char *m,
60                                  unsigned long long   inlen,
61                                  const unsigned char *key)
62{
63    CRYPTO_ALIGN(64) poly1305_state_internal_t state;
64
65    poly1305_init(&state, key);
66    poly1305_update(&state, m, inlen);
67    poly1305_finish(&state, out);
68
69    return 0;
70}
71
72static int
73crypto_onetimeauth_poly1305_donna_init(crypto_onetimeauth_poly1305_state *state,
74                                       const unsigned char *key)
75{
76    COMPILER_ASSERT(sizeof(crypto_onetimeauth_poly1305_state) >=
77        sizeof(poly1305_state_internal_t));
78    poly1305_init((poly1305_state_internal_t *) (void *) state, key);
79
80    return 0;
81}
82
83static int
84crypto_onetimeauth_poly1305_donna_update(
85    crypto_onetimeauth_poly1305_state *state, const unsigned char *in,
86    unsigned long long inlen)
87{
88    poly1305_update((poly1305_state_internal_t *) (void *) state, in, inlen);
89
90    return 0;
91}
92
93static int
94crypto_onetimeauth_poly1305_donna_final(
95    crypto_onetimeauth_poly1305_state *state, unsigned char *out)
96{
97    poly1305_finish((poly1305_state_internal_t *) (void *) state, out);
98
99    return 0;
100}
101
102static int
103crypto_onetimeauth_poly1305_donna_verify(const unsigned char *h,
104                                         const unsigned char *in,
105                                         unsigned long long   inlen,
106                                         const unsigned char *k)
107{
108    unsigned char correct[16];
109
110    crypto_onetimeauth_poly1305_donna(correct, in, inlen, k);
111
112    return crypto_verify_16(h, correct);
113}
114
115struct crypto_onetimeauth_poly1305_implementation
116    crypto_onetimeauth_poly1305_donna_implementation = {
117        SODIUM_C99(.onetimeauth =) crypto_onetimeauth_poly1305_donna,
118        SODIUM_C99(.onetimeauth_verify =)
119            crypto_onetimeauth_poly1305_donna_verify,
120        SODIUM_C99(.onetimeauth_init =) crypto_onetimeauth_poly1305_donna_init,
121        SODIUM_C99(.onetimeauth_update =)
122            crypto_onetimeauth_poly1305_donna_update,
123        SODIUM_C99(.onetimeauth_final =) crypto_onetimeauth_poly1305_donna_final
124    };
125