| 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. If the @AEADF_NOAAD@ class flag is set then @hsz@ must be |
| 128 | * zero. |
| 129 | */ |
| 130 | |
| 131 | void (*destroy)(gaead_aad */*a*/); |
| 132 | /* Destroy the AAD-hashing object. */ |
| 133 | |
| 134 | } gaead_aadops; |
| 135 | |
| 136 | typedef struct gaead_encops { |
| 137 | const struct gcaead *c; /* Pointer to AEAD class */ |
| 138 | |
| 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. |
| 149 | */ |
| 150 | |
| 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. |
| 156 | * |
| 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@. |
| 162 | */ |
| 163 | |
| 164 | int (*encrypt)(gaead_enc */*e*/, const void */*m*/, size_t /*msz*/, |
| 165 | buf */*b*/); |
| 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. |
| 170 | */ |
| 171 | |
| 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. |
| 185 | */ |
| 186 | |
| 187 | void (*destroy)(gaead_enc */*e*/); |
| 188 | /* Destroy the encryption object. */ |
| 189 | |
| 190 | } gaead_encops; |
| 191 | |
| 192 | typedef struct gaead_decops { |
| 193 | const struct gcaead *c; /* Pointer to AEAD class */ |
| 194 | |
| 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 |
| 204 | * for decryption. |
| 205 | */ |
| 206 | |
| 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. |
| 212 | * |
| 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@. |
| 218 | */ |
| 219 | |
| 220 | int (*decrypt)(gaead_dec */*d*/, const void */*c*/, size_t /*csz*/, |
| 221 | buf */*b*/); |
| 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. |
| 226 | * |
| 227 | * CAUTION: the decrypted data may be inauthentic. Don't do anything |
| 228 | * risky with it until its tag has been verified. |
| 229 | */ |
| 230 | |
| 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 |
| 244 | * kinds of failures. |
| 245 | */ |
| 246 | |
| 247 | void (*destroy)(gaead_dec */*d*/); |
| 248 | /* Destroy the decryption object. */ |
| 249 | |
| 250 | } gaead_decops; |
| 251 | |
| 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 */ |
| 267 | |
| 268 | gaead_key *(*key)(const void */*k*/, size_t /*ksz*/); |
| 269 | /* Return a key object (above) with the given key material. */ |
| 270 | |
| 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. |
| 278 | */ |
| 279 | } gcaead; |
| 280 | |
| 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)) |
| 299 | |
| 300 | /*----- Functions provided ------------------------------------------------*/ |
| 301 | |
| 302 | /* --- @gaead_szokcommon@ --- * |
| 303 | * |
| 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 |
| 307 | * |
| 308 | * Returns: Nonzero if the sizes are acceptable to the AEAD scheme in |
| 309 | * combination. |
| 310 | * |
| 311 | * Use: Generic implementation for sensible AEAD schemes. |
| 312 | */ |
| 313 | |
| 314 | extern int gaead_szokcommon(const gcaead */*aec*/, |
| 315 | size_t /*nsz*/, size_t /*hsz*/, |
| 316 | size_t /*msz*/, size_t /*tsz*/); |
| 317 | |
| 318 | /* --- @gaead_encrypt@ --- * |
| 319 | * |
| 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 |
| 326 | * |
| 327 | * Returns: Zero on success, @-1@ if the output buffer is too small. |
| 328 | * |
| 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. |
| 332 | * |
| 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@. |
| 337 | */ |
| 338 | |
| 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*/); |
| 345 | |
| 346 | /* --- @gaead_decrypt@ --- * |
| 347 | * |
| 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 |
| 354 | * |
| 355 | * Returns: @+1@ if everything is good; zero for authentication failure, |
| 356 | * @-1@ for other problems. |
| 357 | * |
| 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. |
| 361 | * |
| 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@. |
| 366 | */ |
| 367 | |
| 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*/); |
| 374 | |
| 375 | /*----- Tables ------------------------------------------------------------*/ |
| 376 | |
| 377 | extern const gcaead *const gaeadtab[]; |
| 378 | |
| 379 | /* --- @gaead_byname@ --- * |
| 380 | * |
| 381 | * Arguments: @const char *p@ = pointer to name string |
| 382 | * |
| 383 | * Returns: The named AEAD class, or null. |
| 384 | */ |
| 385 | |
| 386 | extern const gcaead *gaead_byname(const char */*p*/); |
| 387 | |
| 388 | /*----- That's all, folks -------------------------------------------------*/ |
| 389 | |
| 390 | #ifdef __cplusplus |
| 391 | } |
| 392 | #endif |
| 393 | |
| 394 | #endif |