1 /* umac-l2.c
2
3 Copyright (C) 2013 Niels Möller
4
5 This file is part of GNU Nettle.
6
7 GNU Nettle is free software: you can redistribute it and/or
8 modify it under the terms of either:
9
10 * the GNU Lesser General Public License as published by the Free
11 Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13
14 or
15
16 * the GNU General Public License as published by the Free
17 Software Foundation; either version 2 of the License, or (at your
18 option) any later version.
19
20 or both in parallel, as here.
21
22 GNU Nettle is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 General Public License for more details.
26
27 You should have received copies of the GNU General Public License and
28 the GNU Lesser General Public License along with this program. If
29 not, see http://www.gnu.org/licenses/.
30 */
31
32 #if HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <assert.h>
37 #include <string.h>
38
39 #include "umac.h"
40 #include "umac-internal.h"
41
42 #include "macros.h"
43
44 /* Same mask applied to low and high halves */
45 #define KEY_MASK 0x01ffffffUL
46
47 #if WORDS_BIGENDIAN
48 #define BE_SWAP32(x) x
49 #else
50 #define BE_SWAP32(x) \
51 ((ROTL32(8, x) & 0x00FF00FFUL) | \
52 (ROTL32(24, x) & 0xFF00FF00UL))
53 #endif
54
55 void
_nettle_umac_l2_init(unsigned size,uint32_t * k)56 _nettle_umac_l2_init (unsigned size, uint32_t *k)
57 {
58 unsigned i;
59 for (i = 0; i < size; i++)
60 {
61 uint32_t w = k[i];
62 w = BE_SWAP32 (w);
63 k[i] = w & KEY_MASK;
64 }
65 }
66
67 void
_nettle_umac_l2(const uint32_t * key,uint64_t * state,unsigned n,uint64_t count,const uint64_t * m)68 _nettle_umac_l2(const uint32_t *key, uint64_t *state, unsigned n,
69 uint64_t count, const uint64_t *m)
70 {
71 uint64_t *prev = state + 2*n;
72 unsigned i;
73
74 if (count == 0)
75 memcpy (prev, m, n * sizeof(*m));
76 else if (count == 1)
77 for (i = 0; i < n; i++, key += 6)
78 {
79 uint64_t y = _nettle_umac_poly64 (key[0], key[1], 1, prev[i]);
80 state[2*i+1] = _nettle_umac_poly64 (key[0], key[1], y, m[i]);
81 }
82 else if (count < UMAC_POLY64_BLOCKS)
83 for (i = 0; i < n; i++, key += 6)
84 state[2*i+1] = _nettle_umac_poly64 (key[0], key[1], state[2*i+1], m[i]);
85 else if (count % 2 == 0)
86 {
87 if (count == UMAC_POLY64_BLOCKS)
88 for (i = 0, key += 2; i < n; i++, key += 6)
89 {
90 uint64_t y = state[2*i+1];
91 if (y >= UMAC_P64)
92 y -= UMAC_P64;
93 state[2*i] = 0;
94 state[2*i+1] = 1;
95
96 _nettle_umac_poly128 (key, state + 2*i, 0, y);
97 }
98 memcpy (prev, m, n * sizeof(*m));
99 }
100 else
101 for (i = 0, key += 2; i < n; i++, key += 6)
102 _nettle_umac_poly128 (key, state + 2*i, prev[i], m[i]);
103 }
104
105 void
_nettle_umac_l2_final(const uint32_t * key,uint64_t * state,unsigned n,uint64_t count)106 _nettle_umac_l2_final(const uint32_t *key, uint64_t *state, unsigned n,
107 uint64_t count)
108 {
109 uint64_t *prev = state + 2*n;
110 unsigned i;
111
112 assert (count > 0);
113 if (count == 1)
114 for (i = 0; i < n; i++)
115 {
116 *state++ = 0;
117 *state++ = *prev++;
118 }
119 else if (count <= UMAC_POLY64_BLOCKS)
120 for (i = 0; i < n; i++)
121 {
122 uint64_t y;
123 *state++ = 0;
124
125 y = *state;
126 if (y >= UMAC_P64)
127 y -= UMAC_P64;
128 *state++ = y;
129 }
130 else
131 {
132 uint64_t pad = (uint64_t) 1 << 63;
133 if (count % 2 == 1)
134 for (i = 0, key += 2; i < n; i++, key += 6)
135 _nettle_umac_poly128 (key, state + 2*i, prev[i], pad);
136 else
137 for (i = 0, key += 2; i < n; i++, key += 6)
138 _nettle_umac_poly128 (key, state + 2*i, pad, 0);
139
140 for (i = 0; i < n; i++, state += 2)
141 {
142 uint64_t yh, yl;
143
144 yh = state[0];
145 yl = state[1];
146 if (yh == UMAC_P128_HI && yl >= UMAC_P128_LO)
147 {
148 state[0] = 0;
149 state[1] = yl -= UMAC_P128_LO;
150 }
151 }
152 }
153 }
154