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