]>
Commit | Line | Data |
---|---|---|
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 | ||
27 | CC_INLINE size_t ccecb_context_size(const struct ccmode_ecb *mode) | |
28 | { | |
29 | return mode->size; | |
30 | } | |
31 | ||
32 | CC_INLINE size_t ccecb_block_size(const struct ccmode_ecb *mode) | |
33 | { | |
34 | return mode->block_size; | |
35 | } | |
36 | ||
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 | ||
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 | |
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 | ||
82 | CC_INLINE size_t cccbc_context_size(const struct ccmode_cbc *mode) | |
83 | { | |
84 | return mode->size; | |
85 | } | |
86 | ||
87 | CC_INLINE size_t cccbc_block_size(const struct ccmode_cbc *mode) | |
88 | { | |
89 | return mode->block_size; | |
90 | } | |
91 | ||
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 | ||
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 | ||
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 | ||
127 | CC_INLINE size_t cccfb_context_size(const struct ccmode_cfb *mode) | |
128 | { | |
129 | return mode->size; | |
130 | } | |
131 | ||
132 | CC_INLINE size_t cccfb_block_size(const struct ccmode_cfb *mode) | |
133 | { | |
134 | return mode->block_size; | |
135 | } | |
136 | ||
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 | ||
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 | ||
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 | ||
172 | CC_INLINE size_t cccfb8_context_size(const struct ccmode_cfb8 *mode) | |
173 | { | |
174 | return mode->size; | |
175 | } | |
176 | ||
177 | CC_INLINE size_t cccfb8_block_size(const struct ccmode_cfb8 *mode) | |
178 | { | |
179 | return mode->block_size; | |
180 | } | |
181 | ||
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 | ||
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 | ||
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 | ||
221 | CC_INLINE size_t ccctr_context_size(const struct ccmode_ctr *mode) | |
222 | { | |
223 | return mode->size; | |
224 | } | |
225 | ||
226 | CC_INLINE size_t ccctr_block_size(const struct ccmode_ctr *mode) | |
227 | { | |
228 | return mode->block_size; | |
229 | } | |
230 | ||
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 | ||
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 | ||
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 | ||
266 | CC_INLINE size_t ccofb_context_size(const struct ccmode_ofb *mode) | |
267 | { | |
268 | return mode->size; | |
269 | } | |
270 | ||
271 | CC_INLINE size_t ccofb_block_size(const struct ccmode_ofb *mode) | |
272 | { | |
273 | return mode->block_size; | |
274 | } | |
275 | ||
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 | ||
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 | ||
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 | ||
329 | CC_INLINE size_t ccxts_context_size(const struct ccmode_xts *mode) | |
330 | { | |
331 | return mode->size; | |
332 | } | |
333 | ||
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 | |
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 | */ | |
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 * | |
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 | ||
438 | CC_INLINE size_t ccgcm_context_size(const struct ccmode_gcm *mode) | |
439 | { | |
440 | return mode->size; | |
441 | } | |
442 | ||
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 | */ | |
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 | */ | |
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 | */ | |
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 | */ | |
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 | */ | |
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 | */ | |
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 | */ | |
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 | ||
795 | CC_INLINE size_t ccccm_context_size(const struct ccmode_ccm *mode) | |
796 | { | |
797 | return mode->size; | |
798 | } | |
799 | ||
800 | CC_INLINE size_t ccccm_block_size(const struct ccmode_ccm *mode) | |
801 | { | |
802 | return mode->block_size; | |
803 | } | |
804 | ||
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 | ||
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 | ||
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 | |
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 | ||
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 | ||
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 | ||
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 | ||
885 | CC_INLINE size_t ccomac_context_size(const struct ccmode_omac *mode) | |
886 | { | |
887 | return mode->size; | |
888 | } | |
889 | ||
890 | CC_INLINE size_t ccomac_block_size(const struct ccmode_omac *mode) | |
891 | { | |
892 | return mode->block_size; | |
893 | } | |
894 | ||
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 | |
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 | ||
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_ */ |