1/*
2 *  ccmode.h
3 *  corecrypto
4 *
5 *  Created by Michael Brouwer on 12/6/10.
6 *  Copyright 2010,2011 Apple Inc. All rights reserved.
7 *
8 */
9
10#ifndef _CORECRYPTO_CCMODE_H_
11#define _CORECRYPTO_CCMODE_H_
12
13#include <corecrypto/cc.h>
14#include <corecrypto/ccmode_impl.h>
15
16/* ECB mode. */
17
18/* Declare a ecb key named _name_.  Pass the size field of a struct ccmode_ecb
19   for _size_. */
20#define ccecb_ctx_decl(_size_, _name_) cc_ctx_decl(ccecb_ctx, _size_, _name_)
21#define ccecb_ctx_clear(_size_, _name_) cc_ctx_clear(ccecb_ctx, _size_, _name_)
22
23CC_INLINE size_t ccecb_context_size(const struct ccmode_ecb *mode)
24{
25    return mode->size;
26}
27
28CC_INLINE unsigned long ccecb_block_size(const struct ccmode_ecb *mode)
29{
30	return mode->block_size;
31}
32
33CC_INLINE void ccecb_init(const struct ccmode_ecb *mode, ccecb_ctx *ctx,
34                           unsigned long key_len, const void *key)
35{
36    mode->init(mode, ctx, key_len, key);
37}
38
39CC_INLINE void ccecb_update(const struct ccmode_ecb *mode, const ccecb_ctx *ctx,
40	unsigned long in_len, const void *in, void *out)
41{
42	unsigned long numBlocks = (in_len / mode->block_size);
43	mode->ecb(ctx, numBlocks, in, out);
44}
45
46CC_INLINE void ccecb_one_shot(const struct ccmode_ecb *mode,
47	unsigned long key_len, const void *key, unsigned long in_len,
48	const void *in, void *out)
49{
50	unsigned long numBlocks = (in_len / mode->block_size);
51	ccecb_ctx_decl(mode->size, ctx);
52	mode->init(mode, ctx, key_len, key);
53	mode->ecb(ctx, numBlocks, in, out);
54	ccecb_ctx_clear(mode->size, ctx);
55}
56
57/* CBC mode. */
58
59/* The CBC interface changed due to rdar://11468135. This macros is to indicate
60   to client which CBC API is implemented. Clients can support old versions of
61   corecrypto at build time using this.
62 */
63#define __CC_HAS_FIX_FOR_11468135__ 1
64
65/* Declare a cbc key named _name_.  Pass the size field of a struct ccmode_cbc
66   for _size_. */
67#define cccbc_ctx_decl(_size_, _name_) cc_ctx_decl(cccbc_ctx, _size_, _name_)
68#define cccbc_ctx_clear(_size_, _name_) cc_ctx_clear(cccbc_ctx, _size_, _name_)
69
70/* Declare a cbc iv tweak named _name_.  Pass the blocksize field of a struct ccmode_cbc
71   for _size_. */
72#define cccbc_iv_decl(_size_, _name_) cc_ctx_decl(cccbc_iv, _size_, _name_)
73#define cccbc_iv_clear(_size_, _name_) cc_ctx_clear(cccbc_iv, _size_, _name_)
74
75/* Actual symmetric algorithm implementation can provide you one of these.
76
77   Alternatively you can create a ccmode_cbc instance from any ccmode_ecb
78   cipher.  To do so, statically initialize a struct ccmode_cbc using the
79   CCMODE_FACTORY_CBC_DECRYPT or CCMODE_FACTORY_CBC_ENCRYPT macros. Alternatively
80   you can dynamically initialize a struct ccmode_cbc ccmode_factory_cbc_decrypt()
81   or ccmode_factory_cbc_encrypt(). */
82
83CC_INLINE size_t cccbc_context_size(const struct ccmode_cbc *mode)
84{
85    return mode->size;
86}
87
88CC_INLINE unsigned long cccbc_block_size(const struct ccmode_cbc *mode)
89{
90	return mode->block_size;
91}
92
93CC_INLINE void cccbc_init(const struct ccmode_cbc *mode, cccbc_ctx *ctx,
94                           unsigned long key_len, const void *key)
95{
96    mode->init(mode, ctx, key_len, key);
97}
98
99CC_INLINE void cccbc_set_iv(const struct ccmode_cbc *mode, cccbc_iv *iv_ctx, const void *iv)
100{
101    if(iv)
102        cc_copy(mode->block_size, iv_ctx, iv);
103    else
104        cc_zero(mode->block_size, iv_ctx);
105}
106
107CC_INLINE void cccbc_update(const struct ccmode_cbc *mode,  cccbc_ctx *ctx, cccbc_iv *iv,
108	unsigned long nblocks, const void *in, void *out)
109{
110	mode->cbc(ctx, iv, nblocks, in, out);
111}
112
113CC_INLINE void cccbc_one_shot(const struct ccmode_cbc *mode,
114	unsigned long key_len, const void *key, const void *iv, unsigned long nblocks,
115	const void *in, void *out)
116{
117	cccbc_ctx_decl(mode->size, ctx);
118	cccbc_iv_decl(mode->block_size, iv_ctx);
119	mode->init(mode, ctx, key_len, key);
120    if(iv)
121        cccbc_set_iv      (mode, iv_ctx, iv);
122    else
123        cc_zero(mode->block_size, iv_ctx);
124    mode->cbc(ctx, iv_ctx, nblocks, in, out);
125	cccbc_ctx_clear(mode->size, ctx);
126}
127
128/* CFB mode. */
129
130/* Declare a cfb key named _name_.  Pass the size field of a struct ccmode_cfb
131 for _size_. */
132#define cccfb_ctx_decl(_size_, _name_) cc_ctx_decl(cccfb_ctx, _size_, _name_)
133#define cccfb_ctx_clear(_size_, _name_) cc_ctx_clear(cccfb_ctx, _size_, _name_)
134
135CC_INLINE size_t cccfb_context_size(const struct ccmode_cfb *mode)
136{
137    return mode->size;
138}
139
140CC_INLINE unsigned long cccfb_block_size(const struct ccmode_cfb *mode)
141{
142	return mode->block_size;
143}
144
145CC_INLINE void cccfb_init(const struct ccmode_cfb *mode, cccfb_ctx *ctx,
146                           unsigned long key_len, const void *key, const void *iv)
147{
148    mode->init(mode, ctx, key_len, key, iv);
149}
150
151CC_INLINE void cccfb_update(const struct ccmode_cfb *mode, cccfb_ctx *ctx,
152	unsigned long in_len, const void *in, void *out)
153{
154	mode->cfb(ctx, in_len, in, out);
155}
156
157CC_INLINE void cccfb_one_shot(const struct ccmode_cfb *mode,
158	unsigned long key_len, const void *key, const void *iv,
159    unsigned long in_len, const void *in, void *out)
160{
161	cccfb_ctx_decl(mode->size, ctx);
162	mode->init(mode, ctx, key_len, key, iv);
163	mode->cfb(ctx, in_len, in, out);
164	cccfb_ctx_clear(mode->size, ctx);
165}
166
167/* CFB8 mode. */
168
169/* Declare a cfb8 key named _name_.  Pass the size field of a struct ccmode_cfb8
170 for _size_. */
171#define cccfb8_ctx_decl(_size_, _name_) cc_ctx_decl(cccfb8_ctx, _size_, _name_)
172#define cccfb8_ctx_clear(_size_, _name_) cc_ctx_clear(cccfb8_ctx, _size_, _name_)
173
174CC_INLINE size_t cccfb8_context_size(const struct ccmode_cfb8 *mode)
175{
176    return mode->size;
177}
178
179CC_INLINE unsigned long cccfb8_block_size(const struct ccmode_cfb8 *mode)
180{
181	return mode->block_size;
182}
183
184CC_INLINE void cccfb8_init(const struct ccmode_cfb8 *mode, cccfb8_ctx *ctx,
185                           unsigned long key_len, const void *key, const void *iv)
186{
187    mode->init(mode, ctx, key_len, key, iv);
188}
189
190CC_INLINE void cccfb8_update(const struct ccmode_cfb8 *mode,  cccfb8_ctx *ctx,
191	unsigned long in_len, const void *in, void *out)
192{
193	mode->cfb8(ctx, in_len, in, out);
194}
195
196CC_INLINE void cccfb8_one_shot(const struct ccmode_cfb8 *mode,
197	unsigned long key_len, const void *key, const void *iv,
198    unsigned long in_len, const void *in, void *out)
199{
200	cccfb8_ctx_decl(mode->size, ctx);
201	mode->init(mode, ctx, key_len, key, iv);
202	mode->cfb8(ctx, in_len, in, out);
203	cccfb8_ctx_clear(mode->size, ctx);
204}
205
206/* CTR mode. */
207
208/* Declare a ctr key named _name_.  Pass the size field of a struct ccmode_ctr
209 for _size_. */
210#define ccctr_ctx_decl(_size_, _name_) cc_ctx_decl(ccctr_ctx, _size_, _name_)
211#define ccctr_ctx_clear(_size_, _name_) cc_ctx_clear(ccctr_ctx, _size_, _name_)
212
213/* This is Integer Counter Mode: The IV is the initial value of the counter
214 that is incremented by 1 for each new block. Use the mode flags to select
215 if the IV/Counter is stored in big or little endian. */
216
217CC_INLINE size_t ccctr_context_size(const struct ccmode_ctr *mode)
218{
219    return mode->size;
220}
221
222CC_INLINE unsigned long ccctr_block_size(const struct ccmode_ctr *mode)
223{
224	return mode->block_size;
225}
226
227CC_INLINE void ccctr_init(const struct ccmode_ctr *mode, ccctr_ctx *ctx,
228                           unsigned long key_len, const void *key, const void *iv)
229{
230    mode->init(mode, ctx, key_len, key, iv);
231}
232
233CC_INLINE void ccctr_update(const struct ccmode_ctr *mode, ccctr_ctx *ctx,
234	unsigned long in_len, const void *in, void *out)
235{
236	unsigned long numBlocks = (in_len / mode->block_size);
237	mode->ctr(ctx, numBlocks, in, out);
238}
239
240CC_INLINE void ccctr_one_shot(const struct ccmode_ctr *mode,
241	unsigned long key_len, const void *key, const void *iv,
242    unsigned long in_len, const void *in, void *out)
243{
244	unsigned long numBlocks = (in_len / mode->block_size);
245	ccctr_ctx_decl(mode->size, ctx);
246	mode->init(mode, ctx, key_len, key, iv);
247	mode->ctr(ctx, numBlocks, in, out);
248	ccctr_ctx_clear(mode->size, ctx);
249}
250
251
252/* OFB mode. */
253
254/* Declare a ofb key named _name_.  Pass the size field of a struct ccmode_ofb
255 for _size_. */
256#define ccofb_ctx_decl(_size_, _name_) cc_ctx_decl(ccofb_ctx, _size_, _name_)
257#define ccofb_ctx_clear(_size_, _name_) cc_ctx_clear(ccofb_ctx, _size_, _name_)
258
259CC_INLINE size_t ccofb_context_size(const struct ccmode_ofb *mode)
260{
261    return mode->size;
262}
263
264CC_INLINE unsigned long ccofb_block_size(const struct ccmode_ofb *mode)
265{
266	return mode->block_size;
267}
268
269CC_INLINE void ccofb_init(const struct ccmode_ofb *mode, ccofb_ctx *ctx,
270                           unsigned long key_len, const void *key, const void *iv)
271{
272    mode->init(mode, ctx, key_len, key, iv);
273}
274
275CC_INLINE void ccofb_update(const struct ccmode_ofb *mode, ccofb_ctx *ctx,
276	unsigned long in_len, const void *in, void *out)
277{
278	mode->ofb(ctx, in_len, in, out);
279}
280
281CC_INLINE void ccofb_one_shot(const struct ccmode_ofb *mode,
282	unsigned long key_len, const void *key, const void *iv,
283    unsigned long in_len, const void *in, void *out)
284{
285	ccofb_ctx_decl(mode->size, ctx);
286	mode->init(mode, ctx, key_len, key, iv);
287	mode->ofb(ctx, in_len, in, out);
288	ccofb_ctx_clear(mode->size, ctx);
289}
290
291/* Authenticated cipher modes. */
292
293/* XTS mode. */
294
295/* Declare a xts key named _name_.  Pass the size field of a struct ccmode_xts
296 for _size_. */
297#define ccxts_ctx_decl(_size_, _name_) cc_ctx_decl(ccxts_ctx, _size_, _name_)
298#define ccxts_ctx_clear(_size_, _name_) cc_ctx_clear(ccxts_ctx, _size_, _name_)
299
300/* Declare a xts tweak named _name_.  Pass the tweak_size field of a struct ccmode_xts
301 for _size_. */
302#define ccxts_tweak_decl(_size_, _name_) cc_ctx_decl(ccxts_tweak, _size_, _name_)
303#define ccxts_tweak_clear(_size_, _name_) cc_ctx_clear(ccxts_tweak, _size_, _name_)
304
305/* Actual symmetric algorithm implementation can provide you one of these.
306
307 Alternatively you can create a ccmode_xts instance from any ccmode_ecb
308 cipher.  To do so, statically initialize a struct ccmode_xts using the
309 CCMODE_FACTORY_XTS_DECRYPT or CCMODE_FACTORY_XTS_ENCRYPT macros. Alternatively
310 you can dynamically initialize a struct ccmode_xts ccmode_factory_xts_decrypt()
311 or ccmode_factory_xts_encrypt(). */
312
313/* NOTE that xts mode does not do cts padding.  It's really an xex mode.
314   If you need cts padding use the ccpad_xts_encrypt and ccpad_xts_decrypt
315   functions.   Also note that xts only works for ecb modes with a block_size
316   of 16.  */
317
318CC_INLINE size_t ccxts_context_size(const struct ccmode_xts *mode)
319{
320    return mode->size;
321}
322
323CC_INLINE unsigned long ccxts_block_size(const struct ccmode_xts *mode)
324{
325	return mode->block_size;
326}
327
328CC_INLINE void ccxts_init(const struct ccmode_xts *mode, ccxts_ctx *ctx,
329                           unsigned long key_len, const void *key, const void *tweak_key)
330{
331    mode->init(mode, ctx, key_len, key, tweak_key);
332}
333
334CC_INLINE void ccxts_set_tweak(const struct ccmode_xts *mode, ccxts_ctx *ctx, ccxts_tweak *tweak, const void *iv)
335{
336	mode->set_tweak(ctx, tweak, iv);
337}
338
339CC_INLINE void *ccxts_update(const struct ccmode_xts *mode, ccxts_ctx *ctx,
340	ccxts_tweak *tweak, unsigned long in_len, const void *in, void *out)
341{
342	return mode->xts(ctx, tweak, in_len, in, out);
343}
344
345CC_INLINE void ccxts_one_shot(const struct ccmode_xts *mode,
346	unsigned long key_len, const void *key, const void *tweak_key,
347    const void* iv,
348	unsigned long in_len, const void *in, void *out)
349{
350	ccxts_ctx_decl(mode->size, ctx);
351    ccxts_tweak_decl(mode->tweak_size, tweak);
352	mode->init(mode, ctx, key_len, key, tweak_key);
353    mode->set_tweak(ctx, tweak, iv);
354	mode->xts(ctx, tweak, in_len, in, out);
355	ccxts_ctx_clear(mode->size, ctx);
356    ccxts_tweak_clear(mode->tweak_size, tweak);
357}
358
359/* GCM mode. */
360
361/* Declare a gcm key named _name_.  Pass the size field of a struct ccmode_gcm
362 for _size_. */
363#define ccgcm_ctx_decl(_size_, _name_) cc_ctx_decl(ccgcm_ctx, _size_, _name_)
364#define ccgcm_ctx_clear(_size_, _name_) cc_ctx_clear(ccgcm_ctx, _size_, _name_)
365
366CC_INLINE size_t ccgcm_context_size(const struct ccmode_gcm *mode)
367{
368    return mode->size;
369}
370
371CC_INLINE unsigned long ccgcm_block_size(const struct ccmode_gcm *mode)
372{
373	return mode->block_size;
374}
375
376CC_INLINE void ccgcm_init(const struct ccmode_gcm *mode, ccgcm_ctx *ctx,
377                           unsigned long key_len, const void *key)
378{
379    mode->init(mode, ctx, key_len, key);
380}
381
382CC_INLINE void ccgcm_set_iv(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t iv_size, const void *iv)
383{
384	mode->set_iv(ctx, iv_size, iv);
385}
386
387CC_INLINE void ccgcm_gmac(const struct ccmode_gcm *mode, ccgcm_ctx *ctx,
388	unsigned long nbytes, const void *in)
389{
390	mode->gmac(ctx, nbytes, in);
391}
392
393CC_INLINE void ccgcm_update(const struct ccmode_gcm *mode, ccgcm_ctx *ctx,
394	unsigned long nbytes, const void *in, void *out)
395{
396	mode->gcm(ctx, nbytes, in, out);
397}
398
399CC_INLINE void ccgcm_finalize(const struct ccmode_gcm *mode, ccgcm_ctx *ctx,
400	size_t tag_size, void *tag)
401{
402	mode->finalize(ctx, tag_size, tag);
403}
404
405CC_INLINE void ccgcm_reset(const struct ccmode_gcm *mode, ccgcm_ctx *ctx)
406{
407    mode->reset(ctx);
408}
409
410
411CC_INLINE void ccgcm_one_shot(const struct ccmode_gcm *mode,
412	unsigned long key_len, const void *key,
413	unsigned long iv_len, const void *iv,
414	unsigned long nbytes, const void *in, void *out,
415	unsigned long adata_len, const void* adata,
416	size_t tag_len, void *tag)
417{
418	ccgcm_ctx_decl(mode->size, ctx);
419	mode->init(mode, ctx, key_len, key);
420	mode->set_iv(ctx, iv_len, iv);
421	mode->gmac(ctx, adata_len, adata);
422	mode->gcm(ctx, nbytes, in, out);
423	mode->finalize(ctx, tag_len, tag);
424	ccgcm_ctx_clear(mode->size, ctx);
425}
426
427/* OMAC mode. */
428
429
430/* Declare a omac key named _name_.  Pass the size field of a struct ccmode_omac
431 for _size_. */
432#define ccomac_ctx_decl(_size_, _name_) cc_ctx_decl(ccomac_ctx, _size_, _name_)
433#define ccomac_ctx_clear(_size_, _name_) cc_ctx_clear(ccomac_ctx, _size_, _name_)
434
435CC_INLINE size_t ccomac_context_size(const struct ccmode_omac *mode)
436{
437    return mode->size;
438}
439
440CC_INLINE unsigned long ccomac_block_size(const struct ccmode_omac *mode)
441{
442	return mode->block_size;
443}
444
445CC_INLINE void ccomac_init(const struct ccmode_omac *mode, ccomac_ctx *ctx,
446                           unsigned long tweak_len, unsigned long key_len, const void *key)
447{
448    return mode->init(mode, ctx, tweak_len, key_len, key);
449}
450
451CC_INLINE int ccomac_update(const struct ccmode_omac *mode, ccomac_ctx *ctx,
452	unsigned long in_len, const void *tweak, const void *in, void *out)
453{
454	return mode->omac(ctx, in_len, tweak, in, out);
455}
456
457CC_INLINE int ccomac_one_shot(const struct ccmode_omac *mode,
458	unsigned long tweak_len, unsigned long key_len, const void *key,
459	const void *tweak, unsigned long in_len, const void *in, void *out)
460{
461	ccomac_ctx_decl(mode->size, ctx);
462	mode->init(mode, ctx, tweak_len, key_len, key);
463	int result = mode->omac(ctx, in_len, tweak, in, out);
464	ccomac_ctx_clear(mode->size, ctx);
465    return result;
466}
467
468
469#endif /* _CORECRYPTO_CCMODE_H_ */
470