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