chiark / gitweb /
math/gfx-sqr.c: Use bithacking rather than a table for squaring.
[catacomb] / symm / ocb.h
1 /* -*-c-*-
2  *
3  * Common definitions for OCB and related modes
4  *
5  * (c) 2018 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Catacomb.
11  *
12  * Catacomb is free software: you can redistribute it and/or modify it
13  * under the terms of the GNU Library General Public License as published
14  * by the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Catacomb is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with Catacomb.  If not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25  * USA.
26  */
27
28 #ifndef CATACOMB_OCB_H
29 #define CATACOMB_OCB_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <stddef.h>
38
39 #include <mLib/bits.h>
40 #include <mLib/compiler.h>
41
42 /*----- Constants ---------------------------------------------------------*/
43
44 /* The number of offsets to maintain.  Rather than calculate and store all
45  * possible offset values in advance, or calculate new ones on demand (and
46  * have to allocate space for them), we calculate a number in advance, and
47  * determine any others every time they're needed.  If we calculate the first
48  * %$n$% offsets only, then we spend %$i - n + 1$% time calculating offset
49  * %$L_i$% when %$i \ge n$%.  But the offset %$L_i$% is used only for a
50  * %$2^{-i-1}$% fraction of the blocks.  Summing up this geometric series
51  * shows us that we add only a small constant overhead, and save storage
52  * space for many offsets.
53  */
54 #define OCB_NCALC 16
55 #define OCB_CALCMASK ((1ul << OCB_NCALC) - 1)
56
57 /*----- Functions provided ------------------------------------------------*/
58
59 /* --- @ocb_ctz@, @ocb_ctzl@ --- *
60  *
61  * Arguments:   @unsigned i@ or @unsigned long i@ = operand, assumed nonzero
62  *
63  * Returns:     The number of trailing zero bits in @i@, or nonsense if
64  *              %$i = 0$%.
65  */
66
67 extern unsigned ocb_ctz(unsigned /*i*/);
68 extern unsigned ocb_ctzl(unsigned long /*i*/);
69
70 #if GCC_VERSION_P(3, 4)
71 #  define OCB_CTZ(i) __builtin_ctz(i)
72 #  define OCB_CTZL(i) __builtin_ctzl(i)
73 #else
74 #  define OCB_CTZ(i) ocb_ctz(i)
75 #  define OCB_CTZL(i) ocb_ctzl(i)
76 #endif
77
78 /* --- @OCB_OFFSET@ --- *
79  *
80  * Arguments:   @PRE@ = block cipher prefix
81  *              @uint32 *o@ = pointer to offset accumulator
82  *              @uint32 (*l)[PRE_BLKSZ]@ = pointer to offset mask table
83  *              @unsigned long i@ = block index
84  *
85  * Returns:     ---
86  *
87  * Use:         Update the per-block offset for Grey-code-based OCB
88  *              variants.  On entry, @o@ is assumed to hold the offset for
89  *              block @i - 1@; on exit @o@ is updated to hold the offset for
90  *              block @i@.
91  */
92
93 #define OCB_OFFSET(PRE, o, l, i) do {                                   \
94   uint32 (*_l)[PRE##_BLKSZ/4] = (l);                                    \
95   uint32 *_o = (o);                                                     \
96   unsigned long _i = (i);                                               \
97   unsigned _j;                                                          \
98                                                                         \
99   if (_i&OCB_CALCMASK) {                                                \
100     _j = OCB_CTZ(_i);                                                   \
101     BLKC_XMOVE(PRE, _o, _l[_j]);                                        \
102   } else {                                                              \
103     uint32 _t[PRE##_BLKSZ];                                             \
104     _j = OCB_CTZL(_i) - OCB_NCALC;                                      \
105     BLKC_BLSHIFT(PRE, IRRED, _t, _l[OCB_NCALC - 1]);                    \
106     while (_j--) BLKC_BLSHIFT(PRE, IRRED, _t, _t);                      \
107     BLKC_XMOVE(PRE, _t, _l[_j]);                                        \
108   }                                                                     \
109 } while (0)
110
111 /*----- That's all, folks -------------------------------------------------*/
112
113 #ifdef __cplusplus
114   }
115 #endif
116
117 #endif