xref: /xnu-8020.121.3/EXTERNAL_HEADERS/corecrypto/ccmode.h (revision fdd8201d7b966f0c3ea610489d29bd841d358941) !
1 /* Copyright (c) (2010,2011,2012,2014,2015,2016,2017,2018,2019) Apple Inc. All rights reserved.
2  *
3  * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which
4  * is contained in the License.txt file distributed with corecrypto) and only to
5  * people who accept that license. IMPORTANT:  Any license rights granted to you by
6  * Apple Inc. (if any) are limited to internal use within your organization only on
7  * devices and computers you own or control, for the sole purpose of verifying the
8  * security characteristics and correct functioning of the Apple Software.  You may
9  * not, directly or indirectly, redistribute the Apple Software or any portions thereof.
10  */
11 
12 #ifndef _CORECRYPTO_CCMODE_H_
13 #define _CORECRYPTO_CCMODE_H_
14 
15 #include <corecrypto/cc.h>
16 #include <corecrypto/ccmode_impl.h>
17 #include <corecrypto/ccmode_siv.h>
18 #include <corecrypto/ccmode_siv_hmac.h>
19 
20 /* ECB mode. */
21 
22 /* Declare a ecb key named _name_.  Pass the size field of a struct ccmode_ecb
23    for _size_. */
24 #define ccecb_ctx_decl(_size_, _name_) cc_ctx_decl(ccecb_ctx, _size_, _name_)
25 #define ccecb_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
26 
ccecb_context_size(const struct ccmode_ecb * mode)27 CC_INLINE size_t ccecb_context_size(const struct ccmode_ecb *mode)
28 {
29     return mode->size;
30 }
31 
ccecb_block_size(const struct ccmode_ecb * mode)32 CC_INLINE size_t ccecb_block_size(const struct ccmode_ecb *mode)
33 {
34     return mode->block_size;
35 }
36 
ccecb_init(const struct ccmode_ecb * mode,ccecb_ctx * ctx,size_t key_len,const void * key)37 CC_INLINE int ccecb_init(const struct ccmode_ecb *mode, ccecb_ctx *ctx, size_t key_len, const void *key)
38 {
39     return mode->init(mode, ctx, key_len, key);
40 }
41 
ccecb_update(const struct ccmode_ecb * mode,const ccecb_ctx * ctx,size_t nblocks,const void * in,void * out)42 CC_INLINE int ccecb_update(const struct ccmode_ecb *mode, const ccecb_ctx *ctx, size_t nblocks, const void *in, void *out)
43 {
44     return mode->ecb(ctx, nblocks, in, out);
45 }
46 
47 CC_INLINE int
ccecb_one_shot(const struct ccmode_ecb * mode,size_t key_len,const void * key,size_t nblocks,const void * in,void * out)48 ccecb_one_shot(const struct ccmode_ecb *mode, size_t key_len, const void *key, size_t nblocks, const void *in, void *out)
49 {
50     int rc;
51     ccecb_ctx_decl(mode->size, ctx);
52     rc = mode->init(mode, ctx, key_len, key);
53     if (rc == 0) {
54         rc = mode->ecb(ctx, nblocks, in, out);
55     }
56     ccecb_ctx_clear(mode->size, ctx);
57     return rc;
58 }
59 
60 /* CBC mode. */
61 
62 #define __CC_HAS_FIX_FOR_11468135__ 1
63 
64 /* Declare a cbc key named _name_.  Pass the size field of a struct ccmode_cbc
65    for _size_. */
66 #define cccbc_ctx_decl(_size_, _name_) cc_ctx_decl(cccbc_ctx, _size_, _name_)
67 #define cccbc_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
68 
69 /* Declare a cbc iv tweak named _name_.  Pass the blocksize field of a
70    struct ccmode_cbc for _size_. */
71 #define cccbc_iv_decl(_size_, _name_) cc_ctx_decl(cccbc_iv, _size_, _name_)
72 #define cccbc_iv_clear(_size_, _name_) cc_clear(_size_, _name_)
73 
74 /* Actual symmetric algorithm implementation can provide you one of these.
75 
76    Alternatively you can create a ccmode_cbc instance from any ccmode_ecb
77    cipher.  To do so, statically initialize a struct ccmode_cbc using the
78    CCMODE_FACTORY_CBC_DECRYPT or CCMODE_FACTORY_CBC_ENCRYPT macros.
79    Alternatively you can dynamically initialize a struct ccmode_cbc
80    ccmode_factory_cbc_decrypt() or ccmode_factory_cbc_encrypt(). */
81 
cccbc_context_size(const struct ccmode_cbc * mode)82 CC_INLINE size_t cccbc_context_size(const struct ccmode_cbc *mode)
83 {
84     return mode->size;
85 }
86 
cccbc_block_size(const struct ccmode_cbc * mode)87 CC_INLINE size_t cccbc_block_size(const struct ccmode_cbc *mode)
88 {
89     return mode->block_size;
90 }
91 
cccbc_init(const struct ccmode_cbc * mode,cccbc_ctx * ctx,size_t key_len,const void * key)92 CC_INLINE int cccbc_init(const struct ccmode_cbc *mode, cccbc_ctx *ctx, size_t key_len, const void *key)
93 {
94     return mode->init(mode, ctx, key_len, key);
95 }
96 
cccbc_set_iv(const struct ccmode_cbc * mode,cccbc_iv * iv_ctx,const void * iv)97 CC_INLINE int cccbc_set_iv(const struct ccmode_cbc *mode, cccbc_iv *iv_ctx, const void *iv)
98 {
99     if (iv) {
100         cc_copy(mode->block_size, iv_ctx, iv);
101     } else {
102         cc_clear(mode->block_size, iv_ctx);
103     }
104     return 0;
105 }
106 
cccbc_update(const struct ccmode_cbc * mode,cccbc_ctx * ctx,cccbc_iv * iv,size_t nblocks,const void * in,void * out)107 CC_INLINE int cccbc_update(const struct ccmode_cbc *mode, cccbc_ctx *ctx, cccbc_iv *iv, size_t nblocks, const void *in, void *out)
108 {
109     return mode->cbc(ctx, iv, nblocks, in, out);
110 }
111 
112 int cccbc_one_shot(const struct ccmode_cbc *mode,
113                    size_t key_len,
114                    const void *key,
115                    const void *iv,
116                    size_t nblocks,
117                    const void *in,
118                    void *out);
119 
120 /* CFB mode. */
121 
122 /* Declare a cfb key named _name_.  Pass the size field of a struct ccmode_cfb
123    for _size_. */
124 #define cccfb_ctx_decl(_size_, _name_) cc_ctx_decl(cccfb_ctx, _size_, _name_)
125 #define cccfb_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
126 
cccfb_context_size(const struct ccmode_cfb * mode)127 CC_INLINE size_t cccfb_context_size(const struct ccmode_cfb *mode)
128 {
129     return mode->size;
130 }
131 
cccfb_block_size(const struct ccmode_cfb * mode)132 CC_INLINE size_t cccfb_block_size(const struct ccmode_cfb *mode)
133 {
134     return mode->block_size;
135 }
136 
cccfb_init(const struct ccmode_cfb * mode,cccfb_ctx * ctx,size_t key_len,const void * key,const void * iv)137 CC_INLINE int cccfb_init(const struct ccmode_cfb *mode, cccfb_ctx *ctx, size_t key_len, const void *key, const void *iv)
138 {
139     return mode->init(mode, ctx, key_len, key, iv);
140 }
141 
cccfb_update(const struct ccmode_cfb * mode,cccfb_ctx * ctx,size_t nbytes,const void * in,void * out)142 CC_INLINE int cccfb_update(const struct ccmode_cfb *mode, cccfb_ctx *ctx, size_t nbytes, const void *in, void *out)
143 {
144     return mode->cfb(ctx, nbytes, in, out);
145 }
146 
cccfb_one_shot(const struct ccmode_cfb * mode,size_t key_len,const void * key,const void * iv,size_t nbytes,const void * in,void * out)147 CC_INLINE int cccfb_one_shot(const struct ccmode_cfb *mode,
148                              size_t key_len,
149                              const void *key,
150                              const void *iv,
151                              size_t nbytes,
152                              const void *in,
153                              void *out)
154 {
155     int rc;
156     cccfb_ctx_decl(mode->size, ctx);
157     rc = mode->init(mode, ctx, key_len, key, iv);
158     if (rc == 0) {
159         rc = mode->cfb(ctx, nbytes, in, out);
160     }
161     cccfb_ctx_clear(mode->size, ctx);
162     return rc;
163 }
164 
165 /* CFB8 mode. */
166 
167 /* Declare a cfb8 key named _name_.  Pass the size field of a struct ccmode_cfb8
168  for _size_. */
169 #define cccfb8_ctx_decl(_size_, _name_) cc_ctx_decl(cccfb8_ctx, _size_, _name_)
170 #define cccfb8_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
171 
cccfb8_context_size(const struct ccmode_cfb8 * mode)172 CC_INLINE size_t cccfb8_context_size(const struct ccmode_cfb8 *mode)
173 {
174     return mode->size;
175 }
176 
cccfb8_block_size(const struct ccmode_cfb8 * mode)177 CC_INLINE size_t cccfb8_block_size(const struct ccmode_cfb8 *mode)
178 {
179     return mode->block_size;
180 }
181 
cccfb8_init(const struct ccmode_cfb8 * mode,cccfb8_ctx * ctx,size_t key_len,const void * key,const void * iv)182 CC_INLINE int cccfb8_init(const struct ccmode_cfb8 *mode, cccfb8_ctx *ctx, size_t key_len, const void *key, const void *iv)
183 {
184     return mode->init(mode, ctx, key_len, key, iv);
185 }
186 
cccfb8_update(const struct ccmode_cfb8 * mode,cccfb8_ctx * ctx,size_t nbytes,const void * in,void * out)187 CC_INLINE int cccfb8_update(const struct ccmode_cfb8 *mode, cccfb8_ctx *ctx, size_t nbytes, const void *in, void *out)
188 {
189     return mode->cfb8(ctx, nbytes, in, out);
190 }
191 
cccfb8_one_shot(const struct ccmode_cfb8 * mode,size_t key_len,const void * key,const void * iv,size_t nbytes,const void * in,void * out)192 CC_INLINE int cccfb8_one_shot(const struct ccmode_cfb8 *mode,
193                               size_t key_len,
194                               const void *key,
195                               const void *iv,
196                               size_t nbytes,
197                               const void *in,
198                               void *out)
199 {
200     int rc;
201     cccfb8_ctx_decl(mode->size, ctx);
202     rc = mode->init(mode, ctx, key_len, key, iv);
203     if (rc == 0) {
204         rc = mode->cfb8(ctx, nbytes, in, out);
205     }
206     cccfb8_ctx_clear(mode->size, ctx);
207     return rc;
208 }
209 
210 /* CTR mode. */
211 
212 /* Declare a ctr key named _name_.  Pass the size field of a struct ccmode_ctr
213  for _size_. */
214 #define ccctr_ctx_decl(_size_, _name_) cc_ctx_decl(ccctr_ctx, _size_, _name_)
215 #define ccctr_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
216 
217 /* This is Integer Counter Mode: The IV is the initial value of the counter
218  that is incremented by 1 for each new block. Use the mode flags to select
219  if the IV/Counter is stored in big or little endian. */
220 
ccctr_context_size(const struct ccmode_ctr * mode)221 CC_INLINE size_t ccctr_context_size(const struct ccmode_ctr *mode)
222 {
223     return mode->size;
224 }
225 
ccctr_block_size(const struct ccmode_ctr * mode)226 CC_INLINE size_t ccctr_block_size(const struct ccmode_ctr *mode)
227 {
228     return mode->block_size;
229 }
230 
ccctr_init(const struct ccmode_ctr * mode,ccctr_ctx * ctx,size_t key_len,const void * key,const void * iv)231 CC_INLINE int ccctr_init(const struct ccmode_ctr *mode, ccctr_ctx *ctx, size_t key_len, const void *key, const void *iv)
232 {
233     return mode->init(mode, ctx, key_len, key, iv);
234 }
235 
ccctr_update(const struct ccmode_ctr * mode,ccctr_ctx * ctx,size_t nbytes,const void * in,void * out)236 CC_INLINE int ccctr_update(const struct ccmode_ctr *mode, ccctr_ctx *ctx, size_t nbytes, const void *in, void *out)
237 {
238     return mode->ctr(ctx, nbytes, in, out);
239 }
240 
ccctr_one_shot(const struct ccmode_ctr * mode,size_t key_len,const void * key,const void * iv,size_t nbytes,const void * in,void * out)241 CC_INLINE int ccctr_one_shot(const struct ccmode_ctr *mode,
242                              size_t key_len,
243                              const void *key,
244                              const void *iv,
245                              size_t nbytes,
246                              const void *in,
247                              void *out)
248 {
249     int rc;
250     ccctr_ctx_decl(mode->size, ctx);
251     rc = mode->init(mode, ctx, key_len, key, iv);
252     if (rc == 0) {
253         rc = mode->ctr(ctx, nbytes, in, out);
254     }
255     ccctr_ctx_clear(mode->size, ctx);
256     return rc;
257 }
258 
259 /* OFB mode. */
260 
261 /* Declare a ofb key named _name_.  Pass the size field of a struct ccmode_ofb
262  for _size_. */
263 #define ccofb_ctx_decl(_size_, _name_) cc_ctx_decl(ccofb_ctx, _size_, _name_)
264 #define ccofb_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
265 
ccofb_context_size(const struct ccmode_ofb * mode)266 CC_INLINE size_t ccofb_context_size(const struct ccmode_ofb *mode)
267 {
268     return mode->size;
269 }
270 
ccofb_block_size(const struct ccmode_ofb * mode)271 CC_INLINE size_t ccofb_block_size(const struct ccmode_ofb *mode)
272 {
273     return mode->block_size;
274 }
275 
ccofb_init(const struct ccmode_ofb * mode,ccofb_ctx * ctx,size_t key_len,const void * key,const void * iv)276 CC_INLINE int ccofb_init(const struct ccmode_ofb *mode, ccofb_ctx *ctx, size_t key_len, const void *key, const void *iv)
277 {
278     return mode->init(mode, ctx, key_len, key, iv);
279 }
280 
ccofb_update(const struct ccmode_ofb * mode,ccofb_ctx * ctx,size_t nbytes,const void * in,void * out)281 CC_INLINE int ccofb_update(const struct ccmode_ofb *mode, ccofb_ctx *ctx, size_t nbytes, const void *in, void *out)
282 {
283     return mode->ofb(ctx, nbytes, in, out);
284 }
285 
ccofb_one_shot(const struct ccmode_ofb * mode,size_t key_len,const void * key,const void * iv,size_t nbytes,const void * in,void * out)286 CC_INLINE int ccofb_one_shot(const struct ccmode_ofb *mode,
287                              size_t key_len,
288                              const void *key,
289                              const void *iv,
290                              size_t nbytes,
291                              const void *in,
292                              void *out)
293 {
294     int rc;
295     ccofb_ctx_decl(mode->size, ctx);
296     rc = mode->init(mode, ctx, key_len, key, iv);
297     if (rc == 0) {
298         rc = mode->ofb(ctx, nbytes, in, out);
299     }
300     ccofb_ctx_clear(mode->size, ctx);
301     return rc;
302 }
303 
304 /* XTS mode. */
305 
306 /* Declare a xts key named _name_.  Pass the size field of a struct ccmode_xts
307  for _size_. */
308 #define ccxts_ctx_decl(_size_, _name_) cc_ctx_decl(ccxts_ctx, _size_, _name_)
309 #define ccxts_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
310 
311 /* Declare a xts tweak named _name_.  Pass the tweak_size field of a
312    struct ccmode_xts for _size_. */
313 #define ccxts_tweak_decl(_size_, _name_) cc_ctx_decl(ccxts_tweak, _size_, _name_)
314 #define ccxts_tweak_clear(_size_, _name_) cc_clear(_size_, _name_)
315 
316 /* Actual symmetric algorithm implementation can provide you one of these.
317 
318  Alternatively you can create a ccmode_xts instance from any ccmode_ecb
319  cipher.  To do so, statically initialize a struct ccmode_xts using the
320  CCMODE_FACTORY_XTS_DECRYPT or CCMODE_FACTORY_XTS_ENCRYPT macros. Alternatively
321  you can dynamically initialize a struct ccmode_xts
322  ccmode_factory_xts_decrypt() or ccmode_factory_xts_encrypt(). */
323 
324 /* NOTE that xts mode does not do cts padding.  It's really an xex mode.
325    If you need cts padding use the ccpad_xts_encrypt and ccpad_xts_decrypt
326    functions.   Also note that xts only works for ecb modes with a block_size
327    of 16.  */
328 
ccxts_context_size(const struct ccmode_xts * mode)329 CC_INLINE size_t ccxts_context_size(const struct ccmode_xts *mode)
330 {
331     return mode->size;
332 }
333 
ccxts_block_size(const struct ccmode_xts * mode)334 CC_INLINE size_t ccxts_block_size(const struct ccmode_xts *mode)
335 {
336     return mode->block_size;
337 }
338 
339 /*!
340  @function   ccxts_init
341  @abstract   Initialize an XTS context.
342 
343  @param      mode       Descriptor for the mode
344  @param      ctx        Context for this instance
345  @param      key_nbytes Length of the key arguments in bytes
346  @param      data_key   Key for data encryption
347  @param      tweak_key  Key for tweak generation
348 
349  @result     0 iff successful.
350 
351  @discussion For security reasons, the two keys must be different.
352  */
353 CC_INLINE int
ccxts_init(const struct ccmode_xts * mode,ccxts_ctx * ctx,size_t key_nbytes,const void * data_key,const void * tweak_key)354 ccxts_init(const struct ccmode_xts *mode, ccxts_ctx *ctx, size_t key_nbytes, const void *data_key, const void *tweak_key)
355 {
356     return mode->init(mode, ctx, key_nbytes, data_key, tweak_key);
357 }
358 
359 /*!
360  @function   ccxts_set_tweak
361  @abstract   Initialize the tweak for a sector.
362 
363  @param      mode       Descriptor for the mode
364  @param      ctx        Context for this instance
365  @param      tweak      Context for the tweak for this sector
366  @param      iv         Data used to generate the tweak
367 
368  @discussion The IV must be exactly one block in length.
369  */
ccxts_set_tweak(const struct ccmode_xts * mode,ccxts_ctx * ctx,ccxts_tweak * tweak,const void * iv)370 CC_INLINE int ccxts_set_tweak(const struct ccmode_xts *mode, ccxts_ctx *ctx, ccxts_tweak *tweak, const void *iv)
371 {
372     return mode->set_tweak(ctx, tweak, iv);
373 }
374 
375 /*!
376  @function   ccxts_update
377  @abstract   Encrypt or decrypt data.
378 
379  @param      mode       Descriptor for the mode
380  @param      ctx        Context for an instance
381  @param      tweak      Context for the tweak for this sector
382  @param      nblocks    Length of the data in blocks
383  @param      in         Input data
384  @param      out        Output buffer
385 
386  @result     The updated internal buffer of the tweak context. May be ignored.
387   */
388 CC_INLINE void *
ccxts_update(const struct ccmode_xts * mode,ccxts_ctx * ctx,ccxts_tweak * tweak,size_t nblocks,const void * in,void * out)389 ccxts_update(const struct ccmode_xts *mode, ccxts_ctx *ctx, ccxts_tweak *tweak, size_t nblocks, const void *in, void *out)
390 {
391     return mode->xts(ctx, tweak, nblocks, in, out);
392 }
393 
394 /*!
395  @function   ccxts_one_shot
396  @abstract   Encrypt or decrypt data in XTS mode.
397 
398  @param      mode       Descriptor for the mode
399  @param      key_nbytes Length of the key arguments in bytes
400  @param      data_key   Key for data encryption
401  @param      tweak_key  Key for tweak generation
402  @param      iv         Data used to generate the tweak
403  @param      nblocks    Length of the data in blocks
404  @param      in         Input data
405  @param      out        Output buffer
406 
407  @result     0 iff successful.
408 
409  @discussion For security reasons, the two keys must be different.
410  */
411 int ccxts_one_shot(const struct ccmode_xts *mode,
412                    size_t key_nbytes,
413                    const void *data_key,
414                    const void *tweak_key,
415                    const void *iv,
416                    size_t nblocks,
417                    const void *in,
418                    void *out);
419 
420 /* Authenticated cipher modes. */
421 
422 /* GCM mode. */
423 
424 /* Declare a gcm key named _name_.  Pass the size field of a struct ccmode_gcm
425  for _size_. */
426 #define ccgcm_ctx_decl(_size_, _name_) cc_ctx_decl(ccgcm_ctx, _size_, _name_)
427 #define ccgcm_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
428 
429 #define CCGCM_IV_NBYTES 12
430 #define CCGCM_BLOCK_NBYTES 16
431 
432 /* (2^32 - 2) blocks */
433 /* (2^36 - 32) bytes */
434 /* (2^39 - 256) bits */
435 /* Exceeding this figure breaks confidentiality and authenticity. */
436 #define CCGCM_TEXT_MAX_NBYTES ((1ULL << 36) - 32ULL)
437 
ccgcm_context_size(const struct ccmode_gcm * mode)438 CC_INLINE size_t ccgcm_context_size(const struct ccmode_gcm *mode)
439 {
440     return mode->size;
441 }
442 
ccgcm_block_size(const struct ccmode_gcm * mode)443 CC_INLINE size_t ccgcm_block_size(const struct ccmode_gcm *mode)
444 {
445     return mode->block_size;
446 }
447 
448 /*!
449  @function   ccgcm_init
450  @abstract   Initialize a GCM context.
451 
452  @param      mode       Descriptor for the mode
453  @param      ctx        Context for this instance
454  @param      key_nbytes Length of the key in bytes
455  @param      key        Key for the underlying blockcipher (AES)
456 
457  @result     0 iff successful.
458 
459  @discussion The correct sequence of calls is:
460 
461  @code ccgcm_init(...)
462  ccgcm_set_iv(...)
463  ccgcm_aad(...)       (may be called zero or more times)
464  ccgcm_update(...)    (may be called zero or more times)
465  ccgcm_finalize(...)
466 
467  To reuse the context for additional encryptions, follow this sequence:
468 
469  @code ccgcm_reset(...)
470  ccgcm_set_iv(...)
471  ccgcm_aad(...)       (may be called zero or more times)
472  ccgcm_update(...)    (may be called zero or more times)
473  ccgcm_finalize(...)
474 
475  @warning The key-IV pair must be unique per encryption. The IV must be nonzero in length.
476 
477  @warning It is not permitted to call @p ccgcm_inc_iv after initializing the cipher via the @p ccgcm_init interface. Nonzero is
478  returned in the event of an improper call sequence.
479 
480  @warning This function is not FIPS-compliant. Use @p ccgcm_init_with_iv instead.
481  */
ccgcm_init(const struct ccmode_gcm * mode,ccgcm_ctx * ctx,size_t key_nbytes,const void * key)482 CC_INLINE int ccgcm_init(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t key_nbytes, const void *key)
483 {
484     return mode->init(mode, ctx, key_nbytes, key);
485 }
486 
487 /*!
488  @function   ccgcm_init_with_iv
489  @abstract   Initialize a GCM context to manage IVs internally.
490 
491  @param      mode       Descriptor for the mode
492  @param      ctx        Context for this instance
493  @param      key_nbytes Length of the key in bytes
494  @param      key        Key for the underlying blockcipher (AES)
495  @param      iv         IV for the first encryption
496 
497  @result     0 iff successful.
498 
499  @discussion The correct sequence of calls is:
500 
501  @code ccgcm_init_with_iv(...)
502  ccgcm_aad(...)       (may be called zero or more times)
503  ccgcm_update(...)    (may be called zero or more times)
504  ccgcm_finalize(...)
505 
506  To reuse the context for additional encryptions, follow this sequence:
507 
508  @code ccgcm_reset(...)
509  ccgcm_inc_iv(...)
510  ccgcm_aad(...)       (may be called zero or more times)
511  ccgcm_update(...)    (may be called zero or more times)
512  ccgcm_finalize(...)
513 
514  The IV must be exactly 12 bytes in length.
515 
516  Internally, the IV is treated as a four-byte salt followed by an eight-byte counter. This is to match the behavior of certain
517  protocols (e.g. TLS). In the call to @p ccgcm_inc_iv, the counter component will be interpreted as a big-endian, unsigned value
518  and incremented in place.
519 
520  @warning It is not permitted to call @p ccgcm_set_iv after initializing the cipher via the @p ccgcm_init_with_iv interface.
521  Nonzero is returned in the event of an improper call sequence.
522 
523  @warning The security of GCM depends on the uniqueness of key-IV pairs. To avoid key-IV repetition, callers should not initialize
524  multiple contexts with the same key material via the @p ccgcm_init_with_iv interface.
525  */
526 int ccgcm_init_with_iv(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t key_nbytes, const void *key, const void *iv);
527 
528 /*!
529  @function   ccgcm_set_iv
530  @abstract   Set the IV for encryption.
531 
532  @param      mode       Descriptor for the mode
533  @param      ctx        Context for this instance
534  @param      iv_nbytes  Length of the IV in bytes
535  @param      iv         Initialization vector
536 
537  @result     0 iff successful.
538 
539  @discussion Set the initialization vector for encryption.
540 
541  @warning The key-IV pair must be unique per encryption. The IV must be nonzero in length.
542 
543  In stateful protocols, if each packet exposes a guaranteed-unique value, it is recommended to format this as a 12-byte value for
544  use as the IV.
545 
546  In stateless protocols, it is recommended to choose a 16-byte value using a cryptographically-secure pseudorandom number
547  generator (e.g. @p ccrng).
548 
549  @warning This function may not be used after initializing the cipher via @p ccgcm_init_with_iv. Nonzero is returned in the event
550  of an improper call sequence.
551 
552  @warning This function is not FIPS-compliant. Use @p ccgcm_init_with_iv instead.
553  */
ccgcm_set_iv(const struct ccmode_gcm * mode,ccgcm_ctx * ctx,size_t iv_nbytes,const void * iv)554 CC_INLINE int ccgcm_set_iv(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t iv_nbytes, const void *iv)
555 {
556     return mode->set_iv(ctx, iv_nbytes, iv);
557 }
558 
559 /*!
560  @function   ccgcm_set_iv_legacy
561  @abstract   Set the IV for encryption.
562 
563  @param      mode       Descriptor for the mode
564  @param      ctx        Context for this instance
565  @param      iv_nbytes  Length of the IV in bytes
566  @param      iv         Initialization vector
567 
568  @result     0 iff successful.
569 
570  @discussion Identical to @p ccgcm_set_iv except that it allows zero-length IVs.
571 
572  @warning Zero-length IVs nullify the authenticity guarantees of GCM.
573 
574  @warning Do not use this function in new applications.
575  */
576 int ccgcm_set_iv_legacy(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t iv_nbytes, const void *iv);
577 
578 /*!
579  @function   ccgcm_inc_iv
580  @abstract   Increment the IV for another encryption.
581 
582  @param      mode       Descriptor for the mode
583  @param      ctx        Context for this instance
584  @param      iv         Updated initialization vector
585 
586  @result     0 iff successful.
587 
588  @discussion Updates the IV internally for another encryption.
589 
590  Internally, the IV is treated as a four-byte salt followed by an eight-byte counter. This is to match the behavior of certain
591  protocols (e.g. TLS). The counter component is interpreted as a big-endian, unsigned value and incremented in place.
592 
593  The updated IV is copied to @p iv. This is to support protocols that require part of the IV to be specified explicitly in each
594  packet (e.g. TLS).
595 
596  @warning This function may be used only after initializing the cipher via @p ccgcm_init_with_iv.
597  */
598 int ccgcm_inc_iv(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, void *iv);
599 
600 /*!
601  @function   ccgcm_aad
602  @abstract   Authenticate additional data.
603 
604  @param      mode               Descriptor for the mode
605  @param      ctx                Context for this instance
606  @param      nbytes             Length of the additional data in bytes
607  @param      additional_data    Additional data to authenticate
608 
609  @result     0 iff successful.
610 
611  @discussion This is typically used to authenticate data that cannot be encrypted (e.g. packet headers).
612 
613  This function may be called zero or more times.
614  */
ccgcm_aad(const struct ccmode_gcm * mode,ccgcm_ctx * ctx,size_t nbytes,const void * additional_data)615 CC_INLINE int ccgcm_aad(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t nbytes, const void *additional_data)
616 {
617     return mode->gmac(ctx, nbytes, additional_data);
618 }
619 
620 /*!
621  @function   ccgcm_gmac
622 
623  @discussion ccgcm_gmac is deprecated. Use the drop-in replacement 'ccgcm_aad' instead.
624  */
ccgcm_gmac(const struct ccmode_gcm * mode,ccgcm_ctx * ctx,size_t nbytes,const void * in)625 CC_INLINE int ccgcm_gmac (const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t nbytes, const void *in)
626 cc_deprecate_with_replacement("ccgcm_aad", 13.0, 10.15, 13.0, 6.0, 4.0)
627 {
628     return mode->gmac(ctx, nbytes, in);
629 }
630 
631 /*!
632  @function   ccgcm_update
633  @abstract   Encrypt or decrypt data.
634 
635  @param      mode       Descriptor for the mode
636  @param      ctx        Context for this instance
637  @param      nbytes     Length of the data in bytes
638  @param      in         Input plaintext or ciphertext
639  @param      out        Output ciphertext or plaintext
640 
641  @result     0 iff successful.
642 
643  @discussion In-place processing is supported.
644 
645  This function may be called zero or more times.
646  */
ccgcm_update(const struct ccmode_gcm * mode,ccgcm_ctx * ctx,size_t nbytes,const void * in,void * out)647 CC_INLINE int ccgcm_update(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t nbytes, const void *in, void *out)
648 {
649     return mode->gcm(ctx, nbytes, in, out);
650 }
651 
652 /*!
653  @function   ccgcm_finalize
654  @abstract   Finish processing and authenticate.
655 
656  @param      mode       Descriptor for the mode
657  @param      ctx        Context for this instance
658  @param      tag_nbytes Length of the tag in bytes
659  @param      tag        Authentication tag
660 
661  @result     0 iff successful.
662 
663  @discussion Finish processing a packet and generate the authentication tag.
664 
665  On encryption, @p tag is purely an output parameter. The generated tag is written to @p tag.
666 
667  On decryption, @p tag is both an input and an output parameter. Well-behaved callers should provide the authentication tag
668  generated during encryption. The function will return nonzero if the input tag does not match the generated tag. The generated
669  tag will be written into the @p tag buffer whether authentication succeeds or fails.
670 
671  @warning The generated tag is written to @p tag to support legacy applications that perform authentication manually. Do not
672  follow this usage pattern in new applications. Rely on the function's error code to verify authenticity.
673  */
ccgcm_finalize(const struct ccmode_gcm * mode,ccgcm_ctx * ctx,size_t tag_nbytes,void * tag)674 CC_INLINE int ccgcm_finalize(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t tag_nbytes, void *tag)
675 {
676     return mode->finalize(ctx, tag_nbytes, tag);
677 }
678 
679 /*!
680  @function   ccgcm_reset
681  @abstract   Reset the context for another encryption.
682 
683  @param      mode       Descriptor for the mode
684  @param      ctx        Context for this instance
685 
686  @result     0 iff successful.
687 
688  @discussion Refer to @p ccgcm_init for correct usage.
689  */
ccgcm_reset(const struct ccmode_gcm * mode,ccgcm_ctx * ctx)690 CC_INLINE int ccgcm_reset(const struct ccmode_gcm *mode, ccgcm_ctx *ctx)
691 {
692     return mode->reset(ctx);
693 }
694 
695 /*!
696  @function   ccgcm_one_shot
697  @abstract   Encrypt or decrypt with GCM.
698 
699  @param      mode           Descriptor for the mode
700  @param      key_nbytes     Length of the key in bytes
701  @param      key            Key for the underlying blockcipher (AES)
702  @param      iv_nbytes      Length of the IV in bytes
703  @param      iv             Initialization vector
704  @param      adata_nbytes   Length of the additional data in bytes
705  @param      adata          Additional data to authenticate
706  @param      nbytes         Length of the data in bytes
707  @param      in             Input plaintext or ciphertext
708  @param      out            Output ciphertext or plaintext
709  @param      tag_nbytes     Length of the tag in bytes
710  @param      tag            Authentication tag
711 
712  @result     0 iff successful.
713 
714  @discussion Perform GCM encryption or decryption.
715 
716  @warning The key-IV pair must be unique per encryption. The IV must be nonzero in length.
717 
718  In stateful protocols, if each packet exposes a guaranteed-unique value, it is recommended to format this as a 12-byte value for
719  use as the IV.
720 
721  In stateless protocols, it is recommended to choose a 16-byte value using a cryptographically-secure pseudorandom number
722  generator (e.g. @p ccrng).
723 
724  In-place processing is supported.
725 
726  On encryption, @p tag is purely an output parameter. The generated tag is written to @p tag.
727 
728  On decryption, @p tag is primarily an input parameter. The caller should provide the authentication tag generated during
729  encryption. The function will return nonzero if the input tag does not match the generated tag.
730 
731  @warning To support legacy applications, @p tag is also an output parameter during decryption. The generated tag is written to @p
732  tag. Legacy callers may choose to compare this to the tag generated during encryption. Do not follow this usage pattern in new
733  applications.
734  */
735 int ccgcm_one_shot(const struct ccmode_gcm *mode,
736                    size_t key_nbytes,
737                    const void *key,
738                    size_t iv_nbytes,
739                    const void *iv,
740                    size_t adata_nbytes,
741                    const void *adata,
742                    size_t nbytes,
743                    const void *in,
744                    void *out,
745                    size_t tag_nbytes,
746                    void *tag);
747 
748 /*!
749  @function   ccgcm_one_shot_legacy
750  @abstract   Encrypt or decrypt with GCM.
751 
752  @param      mode           Descriptor for the mode
753  @param      key_nbytes     Length of the key in bytes
754  @param      key            Key for the underlying blockcipher (AES)
755  @param      iv_nbytes      Length of the IV in bytes
756  @param      iv             Initialization vector
757  @param      adata_nbytes   Length of the additional data in bytes
758  @param      adata          Additional data to authenticate
759  @param      nbytes         Length of the data in bytes
760  @param      in             Input plaintext or ciphertext
761  @param      out            Output ciphertext or plaintext
762  @param      tag_nbytes     Length of the tag in bytes
763  @param      tag            Authentication tag
764 
765  @result     0 iff successful.
766 
767  @discussion Identical to @p ccgcm_one_shot except that it allows zero-length IVs.
768 
769  @warning Zero-length IVs nullify the authenticity guarantees of GCM.
770 
771  @warning Do not use this function in new applications.
772  */
773 int ccgcm_one_shot_legacy(const struct ccmode_gcm *mode,
774                           size_t key_nbytes,
775                           const void *key,
776                           size_t iv_nbytes,
777                           const void *iv,
778                           size_t adata_nbytes,
779                           const void *adata,
780                           size_t nbytes,
781                           const void *in,
782                           void *out,
783                           size_t tag_nbytes,
784                           void *tag);
785 
786 /* CCM */
787 
788 #define ccccm_ctx_decl(_size_, _name_) cc_ctx_decl(ccccm_ctx, _size_, _name_)
789 #define ccccm_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
790 
791 /* Declare a ccm nonce named _name_.  Pass the mode->nonce_ctx_size for _size_. */
792 #define ccccm_nonce_decl(_size_, _name_) cc_ctx_decl(ccccm_nonce, _size_, _name_)
793 #define ccccm_nonce_clear(_size_, _name_) cc_clear(_size_, _name_)
794 
ccccm_context_size(const struct ccmode_ccm * mode)795 CC_INLINE size_t ccccm_context_size(const struct ccmode_ccm *mode)
796 {
797     return mode->size;
798 }
799 
ccccm_block_size(const struct ccmode_ccm * mode)800 CC_INLINE size_t ccccm_block_size(const struct ccmode_ccm *mode)
801 {
802     return mode->block_size;
803 }
804 
ccccm_init(const struct ccmode_ccm * mode,ccccm_ctx * ctx,size_t key_len,const void * key)805 CC_INLINE int ccccm_init(const struct ccmode_ccm *mode, ccccm_ctx *ctx, size_t key_len, const void *key)
806 {
807     return mode->init(mode, ctx, key_len, key);
808 }
809 
ccccm_set_iv(const struct ccmode_ccm * mode,ccccm_ctx * ctx,ccccm_nonce * nonce_ctx,size_t nonce_len,const void * nonce,size_t mac_size,size_t auth_len,size_t data_len)810 CC_INLINE int ccccm_set_iv(const struct ccmode_ccm *mode,
811                            ccccm_ctx *ctx,
812                            ccccm_nonce *nonce_ctx,
813                            size_t nonce_len,
814                            const void *nonce,
815                            size_t mac_size,
816                            size_t auth_len,
817                            size_t data_len)
818 {
819     return mode->set_iv(ctx, nonce_ctx, nonce_len, nonce, mac_size, auth_len, data_len);
820 }
821 
ccccm_cbcmac(const struct ccmode_ccm * mode,ccccm_ctx * ctx,ccccm_nonce * nonce_ctx,size_t nbytes,const void * in)822 CC_INLINE int ccccm_cbcmac(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, size_t nbytes, const void *in)
823 {
824     return mode->cbcmac(ctx, nonce_ctx, nbytes, in);
825 }
826 
827 CC_INLINE int
ccccm_update(const struct ccmode_ccm * mode,ccccm_ctx * ctx,ccccm_nonce * nonce_ctx,size_t nbytes,const void * in,void * out)828 ccccm_update(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, size_t nbytes, const void *in, void *out)
829 {
830     return mode->ccm(ctx, nonce_ctx, nbytes, in, out);
831 }
832 
ccccm_finalize(const struct ccmode_ccm * mode,ccccm_ctx * ctx,ccccm_nonce * nonce_ctx,void * mac)833 CC_INLINE int ccccm_finalize(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, void *mac)
834 {
835     return mode->finalize(ctx, nonce_ctx, mac);
836 }
837 
ccccm_reset(const struct ccmode_ccm * mode,ccccm_ctx * ctx,ccccm_nonce * nonce_ctx)838 CC_INLINE int ccccm_reset(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx)
839 {
840     return mode->reset(ctx, nonce_ctx);
841 }
842 
ccccm_one_shot(const struct ccmode_ccm * mode,size_t key_len,const void * key,size_t nonce_len,const void * nonce,size_t nbytes,const void * in,void * out,size_t adata_len,const void * adata,size_t mac_size,void * mac)843 CC_INLINE int ccccm_one_shot(const struct ccmode_ccm *mode,
844                              size_t key_len,
845                              const void *key,
846                              size_t nonce_len,
847                              const void *nonce,
848                              size_t nbytes,
849                              const void *in,
850                              void *out,
851                              size_t adata_len,
852                              const void *adata,
853                              size_t mac_size,
854                              void *mac)
855 {
856     int rc;
857     ccccm_ctx_decl(mode->size, ctx);
858     ccccm_nonce_decl(mode->nonce_size, nonce_ctx);
859     rc = mode->init(mode, ctx, key_len, key);
860     if (rc == 0) {
861         rc = mode->set_iv(ctx, nonce_ctx, nonce_len, nonce, mac_size, adata_len, nbytes);
862     }
863     if (rc == 0) {
864         rc = mode->cbcmac(ctx, nonce_ctx, adata_len, adata);
865     }
866     if (rc == 0) {
867         rc = mode->ccm(ctx, nonce_ctx, nbytes, in, out);
868     }
869     if (rc == 0) {
870         rc = mode->finalize(ctx, nonce_ctx, mac);
871     }
872     ccccm_ctx_clear(mode->size, ctx);
873     ccccm_nonce_clear(mode->nonce_size, nonce_ctx);
874 
875     return rc;
876 }
877 
878 /* OMAC mode. */
879 
880 /* Declare a omac key named _name_.  Pass the size field of a struct ccmode_omac
881  for _size_. */
882 #define ccomac_ctx_decl(_size_, _name_) cc_ctx_decl(ccomac_ctx, _size_, _name_)
883 #define ccomac_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
884 
ccomac_context_size(const struct ccmode_omac * mode)885 CC_INLINE size_t ccomac_context_size(const struct ccmode_omac *mode)
886 {
887     return mode->size;
888 }
889 
ccomac_block_size(const struct ccmode_omac * mode)890 CC_INLINE size_t ccomac_block_size(const struct ccmode_omac *mode)
891 {
892     return mode->block_size;
893 }
894 
ccomac_init(const struct ccmode_omac * mode,ccomac_ctx * ctx,size_t tweak_len,size_t key_len,const void * key)895 CC_INLINE int ccomac_init(const struct ccmode_omac *mode, ccomac_ctx *ctx, size_t tweak_len, size_t key_len, const void *key)
896 {
897     return mode->init(mode, ctx, tweak_len, key_len, key);
898 }
899 
900 CC_INLINE int
ccomac_update(const struct ccmode_omac * mode,ccomac_ctx * ctx,size_t nblocks,const void * tweak,const void * in,void * out)901 ccomac_update(const struct ccmode_omac *mode, ccomac_ctx *ctx, size_t nblocks, const void *tweak, const void *in, void *out)
902 {
903     return mode->omac(ctx, nblocks, tweak, in, out);
904 }
905 
ccomac_one_shot(const struct ccmode_omac * mode,size_t tweak_len,size_t key_len,const void * key,const void * tweak,size_t nblocks,const void * in,void * out)906 CC_INLINE int ccomac_one_shot(const struct ccmode_omac *mode,
907                               size_t tweak_len,
908                               size_t key_len,
909                               const void *key,
910                               const void *tweak,
911                               size_t nblocks,
912                               const void *in,
913                               void *out)
914 {
915     int rc;
916     ccomac_ctx_decl(mode->size, ctx);
917     rc = mode->init(mode, ctx, tweak_len, key_len, key);
918     if (rc == 0) {
919         rc = mode->omac(ctx, nblocks, tweak, in, out);
920     }
921     ccomac_ctx_clear(mode->size, ctx);
922     return rc;
923 }
924 
925 #endif /* _CORECRYPTO_CCMODE_H_ */
926