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 
14 static void
15 poly1305_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 
58 static int
59 crypto_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 
72 static int
73 crypto_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 
83 static int
84 crypto_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 
93 static int
94 crypto_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 
102 static int
103 crypto_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 
115 struct 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