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
poly1305_update(poly1305_state_internal_t * st,const unsigned char * m,unsigned long long bytes)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
crypto_onetimeauth_poly1305_donna(unsigned char * out,const unsigned char * m,unsigned long long inlen,const unsigned char * key)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
crypto_onetimeauth_poly1305_donna_init(crypto_onetimeauth_poly1305_state * state,const unsigned char * key)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
crypto_onetimeauth_poly1305_donna_update(crypto_onetimeauth_poly1305_state * state,const unsigned char * in,unsigned long long inlen)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
crypto_onetimeauth_poly1305_donna_final(crypto_onetimeauth_poly1305_state * state,unsigned char * out)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
crypto_onetimeauth_poly1305_donna_verify(const unsigned char * h,const unsigned char * in,unsigned long long inlen,const unsigned char * k)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