3 * Generic authenticated encryption interface
5 * (c) 2018 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
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.
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.
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,
28 #ifndef CATACOMB_GAEAD_H
29 #define CATACOMB_GAEAD_H
35 /*----- Header files ------------------------------------------------------*/
39 #include <mLib/bits.h>
41 #ifndef CATACOMB_BUF_H
45 #ifndef CATACOMB_KEYSZ_H
49 /*----- Generic AEAD interface --------------------------------------------*/
51 typedef struct gaead_key
{
52 const struct gaead_keyops
*ops
;
55 typedef struct gaead_enc
{
56 const struct gaead_encops
*ops
;
59 typedef struct gaead_dec
{
60 const struct gaead_decops
*ops
;
63 typedef struct gaead_aad
{
64 const struct gaead_aadops
*ops
;
67 typedef struct gaead_keyops
{
68 const struct gcaead
*c
; /* Pointer to AEAD class */
70 gaead_aad
*(*aad
)(const gaead_key */
*k*/
);
71 /* Return an AAD-hashing object for this key. Only available if
72 * the @AEADF_AADNDEP@ class flag is clear.
75 gaead_enc
*(*enc
)(const gaead_key */
*k*/
,
76 const void */
*n*/
, size_t /*nsz*/,
77 size_t /*hsz*/, size_t /*msz*/, size_t /*tsz*/);
78 /* Return a message encryption object for this key, with the given
79 * nonce. If the @AEADF_PCHSZ@, @AEADF_PCMSZ@ and/or @AEADF_PCTSZ@
80 * class flags are set then the caller must provide the AAD length
81 * @hsz@, message length @msz@ and/or tag length @tsz@ respectively;
82 * otherwise these arguments will be ignored.
84 * The caller is expected to have ensured that the nonce and tag
85 * lengths are acceptable, e.g., by checking against the tables
86 * provided in the class object. Some unfortunate AEAD schemes have
87 * more complicated requirements: if the sizes are unacceptable in
88 * combination, this function returns null.
91 gaead_dec
*(*dec
)(const gaead_key */
*k*/
,
92 const void */
*n*/
, size_t /*nsz*/,
93 size_t /*hsz*/, size_t /*csz*/, size_t /*tsz*/);
94 /* Return a message encryption object for this key, with the given
95 * nonce. If the @AEADF_PCHSZ@, @AEADF_PCMSZ@ and/or @AEADF_PCTSZ@
96 * class flags are set then the caller must provide the AAD length
97 * @hsz@, ciphertext length @csz@ and/or tag length @tsz@
98 * respectively; otherwise these arguments will be ignored.
100 * The caller is expected to have ensured that the nonce and tag
101 * lengths are acceptable, e.g., by checking against the tables
102 * provided in the class object. Some unfortunate AEAD schemes have
103 * more complicated requirements: if the sizes are unacceptable in
104 * combination, this function returns null.
107 void (*destroy
)(gaead_key */
*k*/
);
108 /* Destroy the key object. This will not invalidate AAD-hashing,
109 * encryption or decryption objects.
114 typedef struct gaead_aadops
{
115 const struct gcaead
*c
; /* Pointer to AEAD class */
117 gaead_aad
*(*dup
)(const gaead_aad */
*a*/
);
118 /* Return a new AAD-hashing object with a copy of this object's
119 * state. This is useful if the AAD for multiple messages shares a
120 * common prefix: the prefix can be processed once, and a copy
121 * created for each different suffix. Only available if the
122 * @AEADF_AADNDEP@ class flag is clear.
125 void (*hash
)(gaead_aad */
*a*/
, const void */
*h*/
, size_t /*hsz*/);
126 /* Feed header (additional authenticated) data into the AAD-hashing
127 * object. If the @AEADF_NOAAD@ class flag is set then @hsz@ must be
131 void (*destroy
)(gaead_aad */
*a*/
);
132 /* Destroy the AAD-hashing object. */
136 typedef struct gaead_encops
{
137 const struct gcaead
*c
; /* Pointer to AEAD class */
139 gaead_aad
*(*aad
)(gaead_enc */
*e*/
);
140 /* Return a new AAD-hashing object for the current key and nonce. If
141 * the @AEADF_AADNDEP@ class flag is clear then this works just as if
142 * the @aad@ method on the key had been called instead: the new
143 * object is in fact independent of the nonce and can be used with
144 * any encryption or decryption operation. If @AEADF_AADNDEP@ is
145 * set, then the returned AAD-hashing object is specific to this
146 * encryption operation. If @AEADF_AADFIRST@ is also set, then all
147 * additional data must be hashed before any message data is
148 * presented for encryption.
151 int (*reinit
)(gaead_enc */
*e*/
, const void */
*n*/
, size_t /*nsz*/,
152 size_t /*hsz*/, size_t /*msz*/, size_t /*tsz*/);
153 /* Reinitialize this object for a new encryption operation with a
154 * different nonce. The data lengths @hsz@, @msz@, and @tsz@ are as
155 * for the key @enc@ method. Returns zero on success.
157 * The caller is expected to have ensured that the nonce and tag
158 * lengths are acceptable, e.g., by checking against the tables
159 * provided in the class object. Some unfortunate AEAD schemes have
160 * more complicated requirements: if the sizes are unacceptable in
161 * combination, this function returns @-1@.
164 int (*encrypt
)(gaead_enc */
*e*/
, const void */
*m*/
, size_t /*msz*/,
166 /* Encrypt a chunk of data, writing the result to the output buffer
167 * @b@. This will succeed if @BLEFT(b) >= msz + e->c->bufsz@;
168 * otherwise it might fail. Failure doesn't affect the encryption
169 * operation's state. Returns zero on success, or @-1@ on failure.
172 int (*done
)(gaead_enc */
*e*/
, const gaead_aad */
*a*/
, buf */
*b*/
,
173 void */
*t*/
, size_t /*tsz*/);
174 /* Completes encryption, returning the authentication tag for the
175 * message and any additional authenticated data accumulated in @a@.
176 * The pointer @a@ may be null if there is no AAD. If the
177 * @AEADF_AADNDEP@ class flag is set, and any header data has been
178 * provided to the operation's AAD-hashing object, then a pointer to
179 * this object must be provided as @a@. If @AEADF_AADNDEP@ is clear,
180 * then any AAD-hashing object for this key may be provided.
181 * Internally buffered ciphertext may be written to @b@. This will
182 * succeed if @BLEFT(b) >= e->c->bufsz@; otherwise it might fail.
183 * Failure doesn't affect the encryption operation's state. Returns
184 * zero on success, or @-1@ on failure.
187 void (*destroy
)(gaead_enc */
*e*/
);
188 /* Destroy the encryption object. */
192 typedef struct gaead_decops
{
193 const struct gcaead
*c
; /* Pointer to AEAD class */
195 gaead_aad
*(*aad
)(gaead_dec */
*d*/
);
196 /* Return a new AAD-hashing object for the current key and nonce. If
197 * the @AEADF_AADNDEP@ class flag is clear then this works just as if
198 * the @aad@ method on the key had been called instead: the new
199 * object is in fact independent of the nonce and can be used with
200 * any encryption or decryption operation. If @AEADF_AADNDEP@ is
201 * set, then the returned AAD-hashing object is specific to this
202 * decryption operation. If @AEADF_AADFIRST@ is also set, then all
203 * additional data must be hashed before any ciphertext is presented
207 int (*reinit
)(gaead_dec */
*d*/
, const void */
*n*/
, size_t /*nsz*/,
208 size_t /*hsz*/, size_t /*csz*/, size_t /*tsz*/);
209 /* Reinitialize this object for a new decryption operation with a
210 * different nonce. The data lengths @hsz@, @csz@, and @tsz@ are as
211 * for the key @dec@ method.
213 * The caller is expected to have ensured that the nonce and tag
214 * lengths are acceptable, e.g., by checking against the tables
215 * provided in the class object. Some unfortunate AEAD schemes have
216 * more complicated requirements: if the sizes are unacceptable in
217 * combination, this function returns @-1@.
220 int (*decrypt
)(gaead_dec */
*d*/
, const void */
*c*/
, size_t /*csz*/,
222 /* Decrypt a chunk of data, writing the result to the output buffer
223 * @b@. This will succeed if @BLEFT(b) >= msz + e->c->bufsz@;
224 * otherwise it might fail. Failure doesn't affect the decryption
225 * operation's state. Returns zero on success, or @-1@ on failure.
227 * CAUTION: the decrypted data may be inauthentic. Don't do anything
228 * risky with it until its tag has been verified.
231 int (*done
)(gaead_dec */
*d*/
, const gaead_aad */
*a*/
, buf */
*b*/
,
232 const void */
*t*/
, size_t /*tsz*/);
233 /* Completes decryption, verifying the authentication tag for the
234 * message and any additional authenticated data accumulated in @a@.
235 * The pointer @a@ may be null if there is no AAD. If the
236 * @AEADF_AADNDEP@ class flag is set, and any header data has been
237 * provided to the operation's AAD-hashing object, then a pointer to
238 * this object must be provided as @a@. If @AEADF_AADNDEP@ is clear,
239 * then any AAD-hashing object for this key may be provided.
240 * Internally buffered plaintext may be written to @b@. This will
241 * succeed if @BLEFT(b) >= e->c->bufsz@; otherwise it might fail.
242 * Failure doesn't affect the decryption operation's state. Returns
243 * @+1@ on success, @0@ on verification failure, or @-1@ on other
247 void (*destroy
)(gaead_dec */
*d*/
);
248 /* Destroy the decryption object. */
252 typedef struct gcaead
{
253 const char *name
; /* AEAD scheme name */
254 const octet
*keysz
; /* Acceptable keys-size table */
255 const octet
*noncesz
; /* Acceptable nonce-size table */
256 const octet
*tagsz
; /* Acceptable tag-size table */
257 size_t blksz
; /* Block size, or zero if none */
258 unsigned bufsz
; /* Maximum extra msg/ct output */
259 unsigned ohd
; /* Maximum encryption overhead */
260 unsigned f
; /* Various other flags */
261 #define AEADF_PCHSZ 1u /* Precommit to AAD size */
262 #define AEADF_PCMSZ 2u /* Precommit to message size */
263 #define AEADF_PCTSZ 4u /* Precommit to tag size */
264 #define AEADF_AADNDEP 8u /* AAD hash is nonce-dependent */
265 #define AEADF_AADFIRST 16u /* AAD must precede msg/ct */
266 #define AEADF_NOAAD 32u /* AAD is not permitted */
268 gaead_key
*(*key
)(const void */
*k*/
, size_t /*ksz*/);
269 /* Return a key object (above) with the given key material. */
271 int (*szok
)(size_t /*nsz*/, size_t /*hsz*/,
272 size_t /*msz*/, size_t /*tsz*/);
273 /* Return true (nonzero) if the given collection of sizes for nonce,
274 * header, message, and tag are acceptable in combination. Mostly
275 * this will be true if the nonce length and tag size are are
276 * acceptable independently (and the header and message lengths are
277 * irrelevant), but some schemes are more awkward.
281 #define GAEAD_KEY(cc, k, ksz) (cc)->key((k), (ksz))
282 #define GAEAD_CLASS(obj) (obj)->ops->c
283 #define GAEAD_AAD(ked) (ked)->ops->aad((ked))
284 #define GAEAD_REINIT(ed, n, nsz, hsz, msz, tsz) \
285 (ed)->ops->reinit((ed), (n), (nsz), (hsz), (msz), (tsz))
286 #define GAEAD_ENC(k, n, nsz, hsz, msz, tsz) \
287 (k)->ops->enc((k), (n), (nsz), (hsz), (msz), (tsz))
288 #define GAEAD_DEC(k, n, nsz, hsz, msz, tsz) \
289 (k)->ops->dec((k), (n), (nsz), (hsz), (msz), (tsz))
290 #define GAEAD_DUP(a) (a)->ops->dup((a))
291 #define GAEAD_HASH(a, h, hsz) (a)->ops->hash((a), (h), (hsz))
292 #define GAEAD_ENCRYPT(e, m, msz, b) \
293 (e)->ops->encrypt((e), (m), (msz), (b))
294 #define GAEAD_DECRYPT(d, c, csz, b) \
295 (d)->ops->decrypt((d), (c), (csz), (b))
296 #define GAEAD_DONE(ed, aad, b, t, tsz) \
297 (ed)->ops->done((ed), (aad), (b), (t), (tsz))
298 #define GAEAD_DESTROY(obj) (obj)->ops->destroy((obj))
300 /*----- Functions provided ------------------------------------------------*/
302 /* --- @gaead_szokcommon@ --- *
304 * Arguments: @const gcaead *aec@ = pointer to AEAD class
305 * @size_t nsz@, @size_t hsz@, @size_t msz@, @size_t tsz@ =
306 * nonce, header, message, and tag sizes
308 * Returns: Nonzero if the sizes are acceptable to the AEAD scheme in
311 * Use: Generic implementation for sensible AEAD schemes.
314 extern int gaead_szokcommon(const gcaead */
*aec*/
,
315 size_t /*nsz*/, size_t /*hsz*/,
316 size_t /*msz*/, size_t /*tsz*/);
318 /* --- @gaead_encrypt@ --- *
320 * Arguments: @const gaead_key *k@ = the AEAD key, already prepared
321 * @const void *n@, @size_t nsz@ = nonce
322 * @const void *h@, @size_t hsz@ = additional `header' data
323 * @const void *m@, @size_t msz@ = message input
324 * @void *c@, @size_t *csz_input@ = ciphertext output
325 * @void *t@, @size_t tsz@ = tag output
327 * Returns: Zero on success, @-1@ if the output buffer is too small.
329 * Use: Encrypts and authenticates a message in a single operation.
330 * This just saves a bunch of messing about with the various
331 * @gaead_...@ objects.
333 * On entry, @*csz_inout@ should be the capacity of the
334 * ciphertext buffer; on exit, it will be updated with the
335 * actual size of ciphertext produced. The function will not
336 * fail if @*csz_inout >= msz + k->c->ohd@.
339 extern int gaead_encrypt(const gaead_key */
*k*/
,
340 const void */
*n*/
, size_t /*nsz*/,
341 const void */
*h*/
, size_t /*hsz*/,
342 const void */
*m*/
, size_t /*msz*/,
343 void */
*c*/
, size_t */
*csz_inout*/
,
344 void */
*t*/
, size_t /*tsz*/);
346 /* --- @gaead_decrypt@ --- *
348 * Arguments: @const gaead_key *k@ = the AEAD key, already prepared
349 * @const void *n@, @size_t nsz@ = nonce
350 * @const void *h@, @size_t hsz@ = additional `header' data
351 * @const void *c@, @size_t csz@ = ciphertext input
352 * @void *m@, @size_t *msz_inout@ = message output
353 * @const void *t@, @size_t tsz@ = tag input
355 * Returns: @+1@ if everything is good; zero for authentication failure,
356 * @-1@ for other problems.
358 * Use: Decrypts and verifies a message in a single operation.
359 * This just saves a bunch of messing about with the various
360 * @gaead_...@ objects.
362 * On entry, @*msz_inout@ should be the capacity of the
363 * message buffer; on exit, it will be updated with the
364 * actual size of message produced. The function will not
365 * fail if @*msz_inout >= csz@.
368 extern int gaead_decrypt(const gaead_key */
*k*/
,
369 const void */
*n*/
, size_t /*nsz*/,
370 const void */
*h*/
, size_t /*hsz*/,
371 const void */
*c*/
, size_t /*csz*/,
372 void */
*m*/
, size_t */
*msz_inout*/
,
373 const void */
*t*/
, size_t /*tsz*/);
375 /*----- Tables ------------------------------------------------------------*/
377 extern const gcaead
*const gaeadtab
[];
379 /* --- @gaead_byname@ --- *
381 * Arguments: @const char *p@ = pointer to name string
383 * Returns: The named AEAD class, or null.
386 extern const gcaead
*gaead_byname(const char */
*p*/
);
388 /*----- That's all, folks -------------------------------------------------*/