]> git.saurik.com Git - apple/xnu.git/blame_incremental - EXTERNAL_HEADERS/corecrypto/ccmode.h
xnu-7195.101.1.tar.gz
[apple/xnu.git] / EXTERNAL_HEADERS / corecrypto / ccmode.h
... / ...
CommitLineData
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
27CC_INLINE size_t ccecb_context_size(const struct ccmode_ecb *mode)
28{
29 return mode->size;
30}
31
32CC_INLINE size_t ccecb_block_size(const struct ccmode_ecb *mode)
33{
34 return mode->block_size;
35}
36
37CC_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
42CC_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
47CC_INLINE int
48ccecb_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
82CC_INLINE size_t cccbc_context_size(const struct ccmode_cbc *mode)
83{
84 return mode->size;
85}
86
87CC_INLINE size_t cccbc_block_size(const struct ccmode_cbc *mode)
88{
89 return mode->block_size;
90}
91
92CC_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
97CC_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
107CC_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
112int 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
127CC_INLINE size_t cccfb_context_size(const struct ccmode_cfb *mode)
128{
129 return mode->size;
130}
131
132CC_INLINE size_t cccfb_block_size(const struct ccmode_cfb *mode)
133{
134 return mode->block_size;
135}
136
137CC_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
142CC_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
147CC_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
172CC_INLINE size_t cccfb8_context_size(const struct ccmode_cfb8 *mode)
173{
174 return mode->size;
175}
176
177CC_INLINE size_t cccfb8_block_size(const struct ccmode_cfb8 *mode)
178{
179 return mode->block_size;
180}
181
182CC_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
187CC_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
192CC_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
221CC_INLINE size_t ccctr_context_size(const struct ccmode_ctr *mode)
222{
223 return mode->size;
224}
225
226CC_INLINE size_t ccctr_block_size(const struct ccmode_ctr *mode)
227{
228 return mode->block_size;
229}
230
231CC_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
236CC_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
241CC_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
266CC_INLINE size_t ccofb_context_size(const struct ccmode_ofb *mode)
267{
268 return mode->size;
269}
270
271CC_INLINE size_t ccofb_block_size(const struct ccmode_ofb *mode)
272{
273 return mode->block_size;
274}
275
276CC_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
281CC_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
286CC_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
329CC_INLINE size_t ccxts_context_size(const struct ccmode_xts *mode)
330{
331 return mode->size;
332}
333
334CC_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 */
353CC_INLINE int
354ccxts_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 */
370CC_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 */
388CC_INLINE void *
389ccxts_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 */
411int 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
438CC_INLINE size_t ccgcm_context_size(const struct ccmode_gcm *mode)
439{
440 return mode->size;
441}
442
443CC_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 */
482CC_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 */
526int 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 */
554CC_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 */
576int 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 */
598int 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 */
615CC_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 */
625CC_INLINE int ccgcm_gmac (const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t nbytes, const void *in)
626cc_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 */
647CC_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 */
674CC_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 */
690CC_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 */
735int 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 */
773int 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
795CC_INLINE size_t ccccm_context_size(const struct ccmode_ccm *mode)
796{
797 return mode->size;
798}
799
800CC_INLINE size_t ccccm_block_size(const struct ccmode_ccm *mode)
801{
802 return mode->block_size;
803}
804
805CC_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
810CC_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
822CC_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
827CC_INLINE int
828ccccm_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
833CC_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
838CC_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
843CC_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
885CC_INLINE size_t ccomac_context_size(const struct ccmode_omac *mode)
886{
887 return mode->size;
888}
889
890CC_INLINE size_t ccomac_block_size(const struct ccmode_omac *mode)
891{
892 return mode->block_size;
893}
894
895CC_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
900CC_INLINE int
901ccomac_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
906CC_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_ */