chiark / gitweb /
debian/.gitignore: Ignore `catacomb-data' directory.
[catacomb] / symm / ccm.h
1 /* -*-c-*-
2  *
3  * The CCM authenticated-encryption mode
4  *
5  * (c) 2017 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
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * Catacomb is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU 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
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 /*----- Notes on CCM ------------------------------------------------------*
29  *
30  * The name is short for `Counter with CBC-MAC'.  CCM was designed in 2002 by
31  * Russ Housley, Doug Whiting, and Niels Ferguson to be a patent-free
32  * alternative to Rogaway's OCB, and is specified by NIST in SP800-38C.  It's
33  * a classic two-pass authenticated encryption scheme, so it needs two
34  * blockcipher applications per message block.
35  *
36  * Unfortunately, CCM is rather annoying in actual use.  The internals
37  * involve quite a lot of fiddly framing, which I've had to generalize for
38  * block sizes other than 128 bits, but that's not exposed beyond the API.
39  * (This does mean that it's rather unlikely that Catacomb's CCM will
40  * interoperate with anyone else's when using a blockcipher with a block size
41  * other than 128 bits.)
42  *
43  * More problematically:
44  *
45  *   * The mode requires that callers precommit to the header, message, and
46  *     tag sizes before commencing processing.  If you don't know these in
47  *     advance then you can't use CCM.
48  *
49  *   * The mode requires that callers present all of the header data before
50  *     encrypting the message.
51  *
52  *   * The header data processing is dependent on the nonce (and the message
53  *     and tag lengths), so it's not possible to preprocess a constant prefix
54  *     of the header.
55  *
56  *   * There's an uncomfortable tradeoff between nonce length and message
57  *     length because the counter input holds both in separate fields, with a
58  *     variably-positioned split between them.
59  *
60  * The implementation is very picky and will abort if you get things wrong.
61  */
62
63 #ifndef CATACOMB_CCM_H
64 #define CATACOMB_CCM_H
65
66 #ifdef __cplusplus
67   extern "C" {
68 #endif
69
70 /*----- Header files ------------------------------------------------------*/
71
72 #include <stddef.h>
73
74 #include <mLib/bits.h>
75 #include <mLib/buf.h>
76
77 #ifndef CATACOMB_GAEAD_H
78 #  include "gaead.h"
79 #endif
80
81 /*----- Common machinery -------------------------------------------------*/
82
83 typedef struct ccm_params {
84   unsigned long hsz, msz;               /* AAD and message lengths */
85   unsigned bsz, nsz, tsz;               /* Block, nonce and tag length */
86 } ccm_params;
87
88 enum { CCMST_AAD, CCMST_MSG };
89
90 /* Minimum and maximum nonce lengths.
91  *
92  * Let the block size be %$N$% bytes, and let %$q$% be the length-of-the-
93  * length of the messaage.  The nonce length is not encoded directly; rather,
94  * it's what's left after the flags bytes and message length fields have been
95  * allocated.
96  *
97  * The maximum is always %$N - 3$%.  If %$N \le 16$%, then there is one byte
98  * used for flags, and at least two bytes for the message length/counter:
99  * (since %$q$% is encoded in a 3-bit field as %$q - 1$%, %$q = 0$% cannot be
100  * encoded and the encoding zero, for %$q = 1$%, is reserved.  If %$N > 16$
101  * then there are two flags bytes, but %$q$% is encoded directly, so only
102  * %$q = 0$% is reserved.
103  *
104  * The minimum is more complicated.  If %$N \le 16$% then we must have %$q
105  * \le 8$%; with one flags byte, this leaves at least %$\max\{ 0, N - 9 \}$%
106  * bytes for the nonce.  When %$N = 8$% this is zero, but when %$N = 16$%
107  * this is 7.  When %$N > 16$%, there are two flags bits, but %$q \le 127$%
108  * (since %$q$%) is encoded directly: thus the nonce may be empty if
109  * %$16 < N \le 129$%, and otherwise must be at least %$N - 129$% bytes.
110  */
111 #define CCM_NSZMIN(PRE) (PRE##_BLKSZ == 16 ? 7 :                        \
112                          PRE##_BLKSZ <= 129 ? 0 :                       \
113                          PRE##_BLKSZ - 129)
114 #define CCM_NSZMAX(PRE) (PRE##_BLKSZ - 3)
115
116 /* Minimum and maximum tag lengths.
117  *
118  * This is even more exasperating.  Again, let the block size be %$N$% bytes;
119  * let %$t$% be the tag length.
120  *
121  * When %$N = 16$%, the tag length is encoded as %$t/2 - 1$% in a three-bit
122  * field, and the encoding zero is reserved.  (The security of the scheme
123  * depends on this reservation to disambiguate MAC header blocks from
124  * counters; I'd have used the remaining flag bit.)  Anyway, this leaves
125  * %$1 \le t/2 - 1 \le 7$%, so we must have %$4 \le t \le 16$% with %$t$%
126  * even.
127  *
128  * When %$N = 8$%, the tag length is encoded in three bits as %$t - 1$%;
129  * again, the zero encoding is reserved.  This leaves %$2 \le t \le 8$%.
130  *
131  * Finally, when %$N \ge 16$%, the tag length is encoded directly in a
132  * seven-bit field.  The zero encoding is still reserved, so we have
133  * %$1 \le t \le \min \{ N, 127 \}$%.
134  */
135 #define CCM_TSZMIN(PRE) (PRE##_BLKSZ == 8 ? 2 :                         \
136                          PRE##_BLKSZ == 16 ? 4 :                        \
137                          1)
138 #define CCM_TSZMAX(PRE) (PRE##_BLKSZ <= 127 ? PRE##_BLKSZ : 127)
139
140 /*----- Macros ------------------------------------------------------------*/
141
142 /* --- @CCM_DECL@ --- *
143  *
144  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
145  *
146  * Use:         Creates declarations for CCM authenticated-encryption mode.
147  */
148
149 #define CCM_DECL(PRE, pre)                                              \
150                                                                         \
151 typedef struct pre##_ccmctx {                                           \
152   /* The buffer is split into two portions during encryption/           \
153    * decryption.  The first N octets hold a chunk of plaintext, which   \
154    * will be fed into the CBC-MAC calculation; the remaining BLKSZ - N  \
155    * octets hold E_K(C), which is the XOR mask to apply to the          \
156    * plaintext or ciphertext.                                           \
157    */                                                                   \
158   pre##_ctx k;                          /* Underlying key */            \
159   ccm_params p;                         /* CCM parameters */            \
160   unsigned long i;                      /* Current position in bytes */ \
161   unsigned st;                          /* Current state */             \
162   uint32 c[PRE##_BLKSZ/4];              /* Current counter value */     \
163   uint32 a[PRE##_BLKSZ/4];              /* CBC-MAC accumulator */       \
164   uint32 s0[PRE##_BLKSZ/4];             /* Mask for MAC tag */          \
165   octet b[PRE##_BLKSZ];                 /* AAD or msg/mask buffer */    \
166   unsigned off;                         /* Crossover point in buffer */ \
167 } pre##_ccmctx;                                                         \
168                                                                         \
169 extern const octet pre##_ccmnoncesz[], pre##_ccmtagsz[];                \
170                                                                         \
171 /* --- @pre_ccminit@ --- *                                              \
172  *                                                                      \
173  * Arguments:   @pre_ccmctx *aad@ = pointer to CCM context              \
174  *              @const pre_ctx *k@ = pointer to key material            \
175  *              @const void *n@ = pointer to nonce                      \
176  *              @size_t nsz@ = size of the nonce                        \
177  *              @size_t hsz@ = size of the AAD                          \
178  *              @size_t msz@ = size of the message/ciphertext           \
179  *              @size_t tsz@ = size of the tag to produce               \
180  *                                                                      \
181  * Returns:     Zero on success; nonzero if the parameters are invalid. \
182  *                                                                      \
183  * Use:         Initialize an CCM operation context with a given key.   \
184  *                                                                      \
185  *              The original key needn't be kept around any more.       \
186  */                                                                     \
187                                                                         \
188 extern int pre##_ccminit(pre##_ccmctx */*ctx*/,                         \
189                          const pre##_ctx */*k*/,                        \
190                          const void */*n*/, size_t /*nsz*/,             \
191                          size_t /*hsz*/, size_t /*msz*/,                \
192                          size_t /*tsz*/);                               \
193                                                                         \
194 /* --- @pre_ccmreinit@ --- *                                            \
195  *                                                                      \
196  * Arguments:   @pre_ccmctx *ctx@ = pointer to CCM context              \
197  *              @const void *n@ = pointer to nonce                      \
198  *              @size_t nsz@ = size of nonce                            \
199  *              @size_t hsz@ = size of the AAD                          \
200  *              @size_t msz@ = size of the message/ciphertext           \
201  *              @size_t tsz@ = size of the tag to produce               \
202  *                                                                      \
203  * Returns:     Zero on success; nonzero if the parameters are invalid. \
204  *                                                                      \
205  * Use:         Reinitialize an CCM operation context, changing the     \
206  *              nonce and/or other parameters.                          \
207  */                                                                     \
208                                                                         \
209 extern int pre##_ccmreinit(pre##_ccmctx */*ctx*/,                       \
210                            const void */*n*/, size_t /*nsz*/,           \
211                            size_t /*hsz*/, size_t /*msz*/,              \
212                            size_t /*tsz*/);                             \
213                                                                         \
214 /* --- @pre_ccmaadhash@ --- *                                           \
215  *                                                                      \
216  * Arguments:   @pre_ccmctx *ctx@ = pointer to AAD context              \
217  *              @const void *p@ = pointer to AAD material               \
218  *              @size_t sz@ = length of AAD material                    \
219  *                                                                      \
220  * Returns:     ---                                                     \
221  *                                                                      \
222  * Use:         Feeds AAD into the context.  This must be done before   \
223  *              any of the message/ciphertext is processed because CCM  \
224  *              is really annoying like that.                           \
225  */                                                                     \
226                                                                         \
227 extern void pre##_ccmaadhash(pre##_ccmctx */*ctx*/,                     \
228                              const void */*p*/, size_t /*sz*/);         \
229                                                                         \
230 /* --- @pre_ccmencrypt@ --- *                                           \
231  *                                                                      \
232  * Arguments:   @pre_ccmctx *ctx@ = pointer to CCM operation context    \
233  *              @const void *src@ = pointer to plaintext message chunk  \
234  *              @size_t sz@ = size of the plaintext                     \
235  *              @buf *dst@ = a buffer to write the ciphertext to        \
236  *                                                                      \
237  * Returns:     Zero on success; @-1@ on failure.                       \
238  *                                                                      \
239  * Use:         Encrypts a chunk of a plaintext message, writing a      \
240  *              chunk of ciphertext to the output buffer and updating   \
241  *              the operation state.                                    \
242  *                                                                      \
243  *              For CCM, we always write a ciphertext chunk the same    \
244  *              size as the plaintext.  The messing about with @buf@    \
245  *              objects makes the interface consistent with other AEAD  \
246  *              schemes which can't do this.                            \
247  */                                                                     \
248                                                                         \
249 extern int pre##_ccmencrypt(pre##_ccmctx */*ctx*/,                      \
250                             const void */*src*/, size_t /*sz*/,         \
251                             buf */*dst*/);                              \
252                                                                         \
253 /* --- @pre_ccmdecrypt@ --- *                                           \
254  *                                                                      \
255  * Arguments:   @pre_ccmctx *ctx@ = pointer to CCM operation context    \
256  *              @const void *src@ = pointer to ciphertext message chunk \
257  *              @size_t sz@ = size of the ciphertext                    \
258  *              @buf *dst@ = a buffer to write the plaintext to         \
259  *                                                                      \
260  * Returns:     Zero on success; @-1@ on failure.                       \
261  *                                                                      \
262  * Use:         Decrypts a chunk of a ciphertext message, writing a     \
263  *              chunk of plaintext to the output buffer and updating    \
264  *              the operation state.                                    \
265  *                                                                      \
266  *              For CCM, we always write a plaintext chunk the same     \
267  *              size as the ciphertext.  The messing about with @buf@   \
268  *              objects makes the interface consistent with other AEAD  \
269  *              schemes which can't do this.                            \
270  */                                                                     \
271                                                                         \
272 extern int pre##_ccmdecrypt(pre##_ccmctx */*ctx*/,                      \
273                             const void */*src*/, size_t /*sz*/,         \
274                             buf */*dst*/);                              \
275                                                                         \
276 /* --- @pre_ccmencryptdone@ --- *                                       \
277  *                                                                      \
278  * Arguments:   @pre_ccmctx *ctx@ = pointer to an CCM context           \
279  *              @buf *dst@ = buffer for remaining ciphertext            \
280  *              @void *tag@ = where to write the tag                    \
281  *              @size_t tsz@ = length of tag to store                   \
282  *                                                                      \
283  * Returns:     Zero on success; @-1@ on failure.                       \
284  *                                                                      \
285  * Use:         Completes an CCM encryption operation.  The @aad@       \
286  *              pointer may be null if there is no additional           \
287  *              authenticated data.  CCM doesn't buffer ciphertext, but \
288  *              the output buffer is provided anyway for consistency    \
289  *              with other AEAD schemes which don't have this property; \
290  *              the function will fail if the output buffer is broken.  \
291  */                                                                     \
292                                                                         \
293 extern int pre##_ccmencryptdone(pre##_ccmctx */*ctx*/, buf */*dst*/,    \
294                                 void */*tag*/, size_t /*tsz*/);         \
295                                                                         \
296 /* --- @pre_ccmdecryptdone@ --- *                                       \
297  *                                                                      \
298  * Arguments:   @pre_ccmctx *ctx@ = pointer to an CCM context           \
299  *              @buf *dst@ = buffer for remaining plaintext             \
300  *              @const void *tag@ = tag to verify                       \
301  *              @size_t tsz@ = length of tag                            \
302  *                                                                      \
303  * Returns:     @+1@ for complete success; @0@ if tag verification      \
304  *              failed; @-1@ for other kinds of errors.                 \
305  *                                                                      \
306  * Use:         Completes an CCM decryption operation.  The @aad@       \
307  *              pointer may be null if there is no additional           \
308  *              authenticated data.  CCM doesn't buffer plaintext, but  \
309  *              the output buffer is provided anyway for consistency    \
310  *              with other AEAD schemes which don't have this property; \
311  *              the function will fail if the output buffer is broken.  \
312  */                                                                     \
313                                                                         \
314 extern int pre##_ccmdecryptdone(pre##_ccmctx */*ctx*/, buf */*dst*/,    \
315                                 const void */*tag*/, size_t /*tsz*/);   \
316                                                                         \
317 /* --- Generic AEAD interface --- */                                    \
318                                                                         \
319 extern const gcaead pre##_ccm;
320
321 /*----- That's all, folks -------------------------------------------------*/
322
323 #ifdef __cplusplus
324   }
325 #endif
326
327 #endif