Commit | Line | Data |
---|---|---|
96a5a09c MW |
1 | /* -*-c-*- |
2 | * | |
3 | * Generic authenticated encryption interface | |
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_GAEAD_H | |
29 | #define CATACOMB_GAEAD_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 | ||
41 | #ifndef CATACOMB_BUF_H | |
42 | # include "buf.h" | |
43 | #endif | |
44 | ||
45 | #ifndef CATACOMB_KEYSZ_H | |
46 | # include "keysz.h" | |
47 | #endif | |
48 | ||
49 | /*----- Generic AEAD interface --------------------------------------------*/ | |
50 | ||
51 | typedef struct gaead_key { | |
52 | const struct gaead_keyops *ops; | |
53 | } gaead_key; | |
54 | ||
55 | typedef struct gaead_enc { | |
56 | const struct gaead_encops *ops; | |
57 | } gaead_enc; | |
58 | ||
59 | typedef struct gaead_dec { | |
60 | const struct gaead_decops *ops; | |
61 | } gaead_dec; | |
62 | ||
63 | typedef struct gaead_aad { | |
64 | const struct gaead_aadops *ops; | |
65 | } gaead_aad; | |
66 | ||
67 | typedef struct gaead_keyops { | |
68 | const struct gcaead *c; /* Pointer to AEAD class */ | |
69 | ||
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. | |
73 | */ | |
74 | ||
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. | |
83 | * | |
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. | |
89 | */ | |
90 | ||
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. | |
99 | * | |
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. | |
105 | */ | |
106 | ||
107 | void (*destroy)(gaead_key */*k*/); | |
108 | /* Destroy the key object. This will not invalidate AAD-hashing, | |
109 | * encryption or decryption objects. | |
110 | */ | |
111 | ||
112 | } gaead_keyops; | |
113 | ||
114 | typedef struct gaead_aadops { | |
115 | const struct gcaead *c; /* Pointer to AEAD class */ | |
116 | ||
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. | |
123 | */ | |
124 | ||
125 | void (*hash)(gaead_aad */*a*/, const void */*h*/, size_t /*hsz*/); | |
126 | /* Feed header (additional authenticated) data into the AAD-hashing | |
127 | * object. | |
128 | */ | |
129 | ||
130 | void (*destroy)(gaead_aad */*a*/); | |
131 | /* Destroy the AAD-hashing object. */ | |
132 | ||
133 | } gaead_aadops; | |
134 | ||
135 | typedef struct gaead_encops { | |
136 | const struct gcaead *c; /* Pointer to AEAD class */ | |
137 | ||
138 | gaead_aad *(*aad)(gaead_enc */*e*/); | |
139 | /* Return a new AAD-hashing object for the current key and nonce. If | |
140 | * the @AEADF_AADNDEP@ class flag is clear then this works just as if | |
141 | * the @aad@ method on the key had been called instead: the new | |
142 | * object is in fact independent of the nonce and can be used with | |
143 | * any encryption or decryption operation. If @AEADF_AADNDEP@ is | |
144 | * set, then the returned AAD-hashing object is specific to this | |
145 | * encryption operation. If @AEADF_AADFIRST@ is also set, then all | |
146 | * additional data must be hashed before any message data is | |
147 | * presented for encryption. | |
148 | */ | |
149 | ||
150 | int (*reinit)(gaead_enc */*e*/, const void */*n*/, size_t /*nsz*/, | |
151 | size_t /*hsz*/, size_t /*msz*/, size_t /*tsz*/); | |
152 | /* Reinitialize this object for a new encryption operation with a | |
153 | * different nonce. The data lengths @hsz@, @msz@, and @tsz@ are as | |
154 | * for the key @enc@ method. Returns zero on success. | |
155 | * | |
156 | * The caller is expected to have ensured that the nonce and tag | |
157 | * lengths are acceptable, e.g., by checking against the tables | |
158 | * provided in the class object. Some unfortunate AEAD schemes have | |
159 | * more complicated requirements: if the sizes are unacceptable in | |
160 | * combination, this function returns @-1@. | |
161 | */ | |
162 | ||
163 | int (*encrypt)(gaead_enc */*e*/, const void */*m*/, size_t /*msz*/, | |
164 | buf */*b*/); | |
165 | /* Encrypt a chunk of data, writing the result to the output buffer | |
166 | * @b@. This will succeed if @BLEFT(b) >= msz + e->c->bufsz@; | |
167 | * otherwise it might fail. Failure doesn't affect the encryption | |
168 | * operation's state. Returns zero on success, or @-1@ on failure. | |
169 | */ | |
170 | ||
171 | int (*done)(gaead_enc */*e*/, const gaead_aad */*a*/, buf */*b*/, | |
172 | void */*t*/, size_t /*tsz*/); | |
173 | /* Completes encryption, returning the authentication tag for the | |
174 | * message and any additional authenticated data accumulated in @a@. | |
175 | * The pointer @a@ may be null if there is no AAD. If the | |
176 | * @AEADF_AADNDEP@ class flag is set, and any header data has been | |
177 | * provided to the operation's AAD-hashing object, then a pointer to | |
178 | * this object must be provided as @a@. If @AEADF_AADNDEP@ is clear, | |
179 | * then any AAD-hashing object for this key may be provided. | |
180 | * Internally buffered ciphertext may be written to @b@. This will | |
181 | * succeed if @BLEFT(b) >= e->c->bufsz@; otherwise it might fail. | |
182 | * Failure doesn't affect the encryption operation's state. Returns | |
183 | * zero on success, or @-1@ on failure. | |
184 | */ | |
185 | ||
186 | void (*destroy)(gaead_enc */*e*/); | |
187 | /* Destroy the encryption object. */ | |
188 | ||
189 | } gaead_encops; | |
190 | ||
191 | typedef struct gaead_decops { | |
192 | const struct gcaead *c; /* Pointer to AEAD class */ | |
193 | ||
194 | gaead_aad *(*aad)(gaead_dec */*d*/); | |
195 | /* Return a new AAD-hashing object for the current key and nonce. If | |
196 | * the @AEADF_AADNDEP@ class flag is clear then this works just as if | |
197 | * the @aad@ method on the key had been called instead: the new | |
198 | * object is in fact independent of the nonce and can be used with | |
199 | * any encryption or decryption operation. If @AEADF_AADNDEP@ is | |
200 | * set, then the returned AAD-hashing object is specific to this | |
201 | * decryption operation. If @AEADF_AADFIRST@ is also set, then all | |
202 | * additional data must be hashed before any ciphertext is presented | |
203 | * for decryption. | |
204 | */ | |
205 | ||
206 | int (*reinit)(gaead_dec */*d*/, const void */*n*/, size_t /*nsz*/, | |
207 | size_t /*hsz*/, size_t /*csz*/, size_t /*tsz*/); | |
208 | /* Reinitialize this object for a new decryption operation with a | |
209 | * different nonce. The data lengths @hsz@, @csz@, and @tsz@ are as | |
210 | * for the key @dec@ method. | |
211 | * | |
212 | * The caller is expected to have ensured that the nonce and tag | |
213 | * lengths are acceptable, e.g., by checking against the tables | |
214 | * provided in the class object. Some unfortunate AEAD schemes have | |
215 | * more complicated requirements: if the sizes are unacceptable in | |
216 | * combination, this function returns @-1@. | |
217 | */ | |
218 | ||
219 | int (*decrypt)(gaead_dec */*d*/, const void */*c*/, size_t /*csz*/, | |
220 | buf */*b*/); | |
221 | /* Decrypt a chunk of data, writing the result to the output buffer | |
222 | * @b@. This will succeed if @BLEFT(b) >= msz + e->c->bufsz@; | |
223 | * otherwise it might fail. Failure doesn't affect the decryption | |
224 | * operation's state. Returns zero on success, or @-1@ on failure. | |
225 | * | |
226 | * CAUTION: the decrypted data may be inauthentic. Don't do anything | |
227 | * risky with it until its tag has been verified. | |
228 | */ | |
229 | ||
230 | int (*done)(gaead_dec */*d*/, const gaead_aad */*a*/, buf */*b*/, | |
231 | const void */*t*/, size_t /*tsz*/); | |
232 | /* Completes decryption, verifying the authentication tag for the | |
233 | * message and any additional authenticated data accumulated in @a@. | |
234 | * The pointer @a@ may be null if there is no AAD. If the | |
235 | * @AEADF_AADNDEP@ class flag is set, and any header data has been | |
236 | * provided to the operation's AAD-hashing object, then a pointer to | |
237 | * this object must be provided as @a@. If @AEADF_AADNDEP@ is clear, | |
238 | * then any AAD-hashing object for this key may be provided. | |
239 | * Internally buffered plaintext may be written to @b@. This will | |
240 | * succeed if @BLEFT(b) >= e->c->bufsz@; otherwise it might fail. | |
241 | * Failure doesn't affect the decryption operation's state. Returns | |
242 | * @+1@ on success, @0@ on verification failure, or @-1@ on other | |
243 | * kinds of failures. | |
244 | */ | |
245 | ||
246 | void (*destroy)(gaead_dec */*d*/); | |
247 | /* Destroy the decryption object. */ | |
248 | ||
249 | } gaead_decops; | |
250 | ||
251 | typedef struct gcaead { | |
252 | const char *name; /* AEAD scheme name */ | |
253 | const octet *keysz; /* Acceptable keys-size table */ | |
254 | const octet *noncesz; /* Acceptable nonce-size table */ | |
255 | const octet *tagsz; /* Acceptable tag-size table */ | |
256 | size_t blksz; /* Block size, or zero if none */ | |
257 | unsigned bufsz; /* Maximum extra msg/ct output */ | |
258 | unsigned ohd; /* Maximum encryption overhead */ | |
259 | unsigned f; /* Various other flags */ | |
260 | #define AEADF_PCHSZ 1u /* Precommit to AAD size */ | |
261 | #define AEADF_PCMSZ 2u /* Precommit to message size */ | |
262 | #define AEADF_PCTSZ 4u /* Precommit to tag size */ | |
263 | #define AEADF_AADNDEP 8u /* AAD hash is nonce-dependent */ | |
264 | #define AEADF_AADFIRST 16u /* AAD must precede msg/ct */ | |
265 | ||
266 | gaead_key *(*key)(const void */*k*/, size_t /*ksz*/); | |
267 | /* Return a key object (above) with the given key material. */ | |
268 | ||
269 | int (*szok)(size_t /*nsz*/, size_t /*hsz*/, | |
270 | size_t /*msz*/, size_t /*tsz*/); | |
271 | /* Return true (nonzero) if the given collection of sizes for nonce, | |
272 | * header, message, and tag are acceptable in combination. Mostly | |
273 | * this will be true if the nonce length and tag size are are | |
274 | * acceptable independently (and the header and message lengths are | |
275 | * irrelevant), but some schemes are more awkward. | |
276 | */ | |
277 | } gcaead; | |
278 | ||
279 | #define GAEAD_KEY(cc, k, ksz) (cc)->key((k), (ksz)) | |
280 | #define GAEAD_CLASS(obj) (obj)->ops->c | |
281 | #define GAEAD_AAD(ked) (ked)->ops->aad((ked)) | |
282 | #define GAEAD_REINIT(ed, n, nsz, hsz, msz, tsz) \ | |
283 | (ed)->ops->reinit((ed), (n), (nsz), (hsz), (msz), (tsz)) | |
284 | #define GAEAD_ENC(k, n, nsz, hsz, msz, tsz) \ | |
285 | (k)->ops->enc((k), (n), (nsz), (hsz), (msz), (tsz)) | |
286 | #define GAEAD_DEC(k, n, nsz, hsz, msz, tsz) \ | |
287 | (k)->ops->dec((k), (n), (nsz), (hsz), (msz), (tsz)) | |
288 | #define GAEAD_DUP(a) (a)->ops->dup((a)) | |
289 | #define GAEAD_HASH(a, h, hsz) (a)->ops->hash((a), (h), (hsz)) | |
290 | #define GAEAD_ENCRYPT(e, m, msz, b) \ | |
291 | (e)->ops->encrypt((e), (m), (msz), (b)) | |
292 | #define GAEAD_DECRYPT(d, c, csz, b) \ | |
293 | (d)->ops->decrypt((d), (c), (csz), (b)) | |
294 | #define GAEAD_DONE(ed, aad, b, t, tsz) \ | |
295 | (ed)->ops->done((ed), (aad), (b), (t), (tsz)) | |
296 | #define GAEAD_DESTROY(obj) (obj)->ops->destroy((obj)) | |
297 | ||
298 | /*----- Functions provided ------------------------------------------------*/ | |
299 | ||
300 | /* --- @gaead_szokcommon@ --- * | |
301 | * | |
302 | * Arguments: @const gcaead *aec@ = pointer to AEAD class | |
303 | * @size_t nsz@, @size_t hsz@, @size_t msz@, @size_t tsz@ = | |
304 | * nonce, header, message, and tag sizes | |
305 | * | |
306 | * Returns: Nonzero if the sizes are acceptable to the AEAD scheme in | |
307 | * combination. | |
308 | * | |
309 | * Use: Generic implementation for sensible AEAD schemes. | |
310 | */ | |
311 | ||
312 | extern int gaead_szokcommon(const gcaead */*aec*/, | |
313 | size_t /*nsz*/, size_t /*hsz*/, | |
314 | size_t /*msz*/, size_t /*tsz*/); | |
315 | ||
316 | /* --- @gaead_encrypt@ --- * | |
317 | * | |
318 | * Arguments: @const gaead_key *k@ = the AEAD key, already prepared | |
319 | * @const void *n@, @size_t nsz@ = nonce | |
320 | * @const void *h@, @size_t hsz@ = additional `header' data | |
321 | * @const void *m@, @size_t msz@ = message input | |
322 | * @void *c@, @size_t *csz_input@ = ciphertext output | |
323 | * @void *t@, @size_t tsz@ = tag output | |
324 | * | |
325 | * Returns: Zero on success, @-1@ if the output buffer is too small. | |
326 | * | |
327 | * Use: Encrypts and authenticates a message in a single operation. | |
328 | * This just saves a bunch of messing about with the various | |
329 | * @gaead_...@ objects. | |
330 | * | |
331 | * On entry, @*csz_inout@ should be the capacity of the | |
332 | * ciphertext buffer; on exit, it will be updated with the | |
333 | * actual size of ciphertext produced. The function will not | |
334 | * fail if @*csz_inout >= msz + k->c->ohd@. | |
335 | */ | |
336 | ||
337 | extern int gaead_encrypt(const gaead_key */*k*/, | |
338 | const void */*n*/, size_t /*nsz*/, | |
339 | const void */*h*/, size_t /*hsz*/, | |
340 | const void */*m*/, size_t /*msz*/, | |
341 | void */*c*/, size_t */*csz_inout*/, | |
342 | void */*t*/, size_t /*tsz*/); | |
343 | ||
344 | /* --- @gaead_decrypt@ --- * | |
345 | * | |
346 | * Arguments: @const gaead_key *k@ = the AEAD key, already prepared | |
347 | * @const void *n@, @size_t nsz@ = nonce | |
348 | * @const void *h@, @size_t hsz@ = additional `header' data | |
349 | * @const void *c@, @size_t csz@ = ciphertext input | |
350 | * @void *m@, @size_t *msz_inout@ = message output | |
351 | * @const void *t@, @size_t tsz@ = tag input | |
352 | * | |
353 | * Returns: @+1@ if everything is good; zero for authentication failure, | |
354 | * @-1@ for other problems. | |
355 | * | |
356 | * Use: Decrypts and verifies a message in a single operation. | |
357 | * This just saves a bunch of messing about with the various | |
358 | * @gaead_...@ objects. | |
359 | * | |
360 | * On entry, @*msz_inout@ should be the capacity of the | |
361 | * message buffer; on exit, it will be updated with the | |
362 | * actual size of message produced. The function will not | |
363 | * fail if @*msz_inout >= csz@. | |
364 | */ | |
365 | ||
366 | extern int gaead_decrypt(const gaead_key */*k*/, | |
367 | const void */*n*/, size_t /*nsz*/, | |
368 | const void */*h*/, size_t /*hsz*/, | |
369 | const void */*c*/, size_t /*csz*/, | |
370 | void */*m*/, size_t */*msz_inout*/, | |
371 | const void */*t*/, size_t /*tsz*/); | |
372 | ||
373 | /*----- Tables ------------------------------------------------------------*/ | |
374 | ||
375 | extern const gcaead *const gaeadtab[]; | |
376 | ||
377 | /* --- @gaead_byname@ --- * | |
378 | * | |
379 | * Arguments: @const char *p@ = pointer to name string | |
380 | * | |
381 | * Returns: The named AEAD class, or null. | |
382 | */ | |
383 | ||
384 | extern const gcaead *gaead_byname(const char */*p*/); | |
385 | ||
386 | /*----- That's all, folks -------------------------------------------------*/ | |
387 | ||
388 | #ifdef __cplusplus | |
389 | } | |
390 | #endif | |
391 | ||
392 | #endif |