1/*
2 * Copyright (c) 2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include "corecryptoSymmetricBridge.h"
25#include "ccMemory.h"
26#include <corecrypto/ccrc4.h>
27
28static void *noMode(void) { return NULL; }
29
30// RC4 as a mode trick ...
31
32static void rc4ModeInit(const struct ccmode_ofb *ofb, ccofb_ctx *ctx,
33             unsigned long key_len, const void *key,
34             const void *iv)
35{
36    ccrc4_eay.init((ccrc4_ctx *)ctx, key_len, key);
37}
38
39static void rc4crypt(ccofb_ctx *ctx, unsigned long nbytes, const void *in, void *out)
40{
41    ccrc4_eay.crypt((ccrc4_ctx *) ctx, nbytes, in, out);
42}
43
44typedef struct eay_rc4_key_st
45{
46	uint32_t x,y;
47	uint32_t data[256];
48} eay_RC4_KEY;
49
50static const struct ccmode_ofb rc4mode = {
51    .size = sizeof(eay_RC4_KEY),
52    .block_size = 1,
53    .init = rc4ModeInit,
54    .ofb = rc4crypt,
55};
56
57
58
59static const struct ccmode_ofb *cc_rc4_crypt_mode(void)
60{
61    return &rc4mode;
62}
63
64
65// 2 dimensional array of various mode/cipher contexts
66// encrypt/decrypt x algorithm matching the list in CommonCryptor.h
67
68const modeList ccmodeList[CC_SUPPORTED_CIPHERS][CC_DIRECTIONS] = {
69    { // AES
70        { ccaes_ecb_encrypt_mode, ccaes_cbc_encrypt_mode, ccaes_cfb_encrypt_mode, ccaes_cfb8_encrypt_mode, ccaes_ctr_crypt_mode, ccaes_ofb_crypt_mode, ccaes_xts_encrypt_mode, ccaes_gcm_encrypt_mode, ccaes_ccm_encrypt_mode },
71        { ccaes_ecb_decrypt_mode, ccaes_cbc_decrypt_mode, ccaes_cfb_decrypt_mode, ccaes_cfb8_decrypt_mode, ccaes_ctr_crypt_mode, ccaes_ofb_crypt_mode, ccaes_xts_decrypt_mode, ccaes_gcm_decrypt_mode,  ccaes_ccm_decrypt_mode }
72    },
73
74    { // DES
75        { ccdes_ecb_encrypt_mode, ccdes_cbc_encrypt_mode, ccdes_cfb_encrypt_mode, ccdes_cfb8_encrypt_mode, ccdes_ctr_crypt_mode, ccdes_ofb_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode },
76        { ccdes_ecb_decrypt_mode, ccdes_cbc_decrypt_mode, ccdes_cfb_decrypt_mode, ccdes_cfb8_decrypt_mode, ccdes_ctr_crypt_mode, ccdes_ofb_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode }
77    },
78
79    { // DES3
80        { ccdes3_ecb_encrypt_mode, ccdes3_cbc_encrypt_mode, ccdes3_cfb_encrypt_mode, ccdes3_cfb8_encrypt_mode, ccdes3_ctr_crypt_mode, ccdes3_ofb_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode },
81        { ccdes3_ecb_decrypt_mode, ccdes3_cbc_decrypt_mode, ccdes3_cfb_decrypt_mode, ccdes3_cfb8_decrypt_mode, ccdes3_ctr_crypt_mode, ccdes3_ofb_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode }
82    },
83
84    { // CAST
85        { cccast_ecb_encrypt_mode, cccast_cbc_encrypt_mode, cccast_cfb_encrypt_mode, cccast_cfb8_encrypt_mode, cccast_ctr_crypt_mode, cccast_ofb_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode },
86        { cccast_ecb_decrypt_mode, cccast_cbc_decrypt_mode, cccast_cfb_decrypt_mode, cccast_cfb8_decrypt_mode, cccast_ctr_crypt_mode, cccast_ofb_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode }
87    },
88
89    { // RC4 - hijack OFB to put in streaming cipher descriptor
90        { (ecb_p) noMode, (cbc_p) noMode, (cfb_p) noMode, (cfb8_p) noMode, (ctr_p) noMode, cc_rc4_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode },
91        { (ecb_p) noMode, (cbc_p) noMode, (cfb_p) noMode, (cfb8_p) noMode, (ctr_p) noMode, cc_rc4_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode },
92    },
93
94
95    { // RC2
96        { ccrc2_ecb_encrypt_mode, ccrc2_cbc_encrypt_mode, ccrc2_cfb_encrypt_mode, ccrc2_cfb8_encrypt_mode, ccrc2_ctr_crypt_mode, ccrc2_ofb_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode },
97        { ccrc2_ecb_decrypt_mode, ccrc2_cbc_decrypt_mode, ccrc2_cfb_decrypt_mode, ccrc2_cfb8_decrypt_mode, ccrc2_ctr_crypt_mode, ccrc2_ofb_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode }
98    },
99
100    { // Blowfish
101        { ccblowfish_ecb_encrypt_mode, ccblowfish_cbc_encrypt_mode, ccblowfish_cfb_encrypt_mode, ccblowfish_cfb8_encrypt_mode, ccblowfish_ctr_crypt_mode, ccblowfish_ofb_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode },
102        { ccblowfish_ecb_decrypt_mode, ccblowfish_cbc_decrypt_mode, ccblowfish_cfb_decrypt_mode, ccblowfish_cfb8_decrypt_mode, ccblowfish_ctr_crypt_mode, ccblowfish_ofb_crypt_mode, (xts_p) noMode, (gcm_p) noMode, (ccm_p) noMode }
103    },
104};
105
106
107// Thunks
108//ECB
109
110static size_t ccecb_mode_get_ctx_size(corecryptoMode modeObject) { return modeObject.ecb->size; }
111static size_t ccecb_mode_get_block_size(corecryptoMode modeObject) { return modeObject.ecb->block_size; }
112static void ccecb_mode_setup(corecryptoMode modeObj, const void *IV,
113                             const void *key, size_t keylen, const void *tweak,
114                             size_t tweaklen, int options, modeCtx ctx)
115{
116    modeObj.ecb->init(modeObj.ecb, ctx.ecb, keylen, key);
117}
118
119static void ccecb_mode_crypt(corecryptoMode modeObj, const void *in, void *out, size_t len, modeCtx ctx)
120{
121    modeObj.ecb->ecb(ctx.ecb, len / ccecb_mode_get_block_size(modeObj), in, out);
122}
123
124const cc2CCModeDescriptor ccecb_mode = {
125    .mode_get_ctx_size = ccecb_mode_get_ctx_size,
126    .mode_get_block_size = ccecb_mode_get_block_size,
127    .mode_setup = ccecb_mode_setup,
128    .mode_encrypt = ccecb_mode_crypt,
129    .mode_decrypt = ccecb_mode_crypt,
130    .mode_encrypt_tweaked = NULL,
131    .mode_decrypt_tweaked = NULL,
132    .mode_done = NULL,
133    .mode_setiv = NULL,
134    .mode_getiv = NULL
135};
136
137// CBC
138
139static size_t cccbc_mode_get_ctx_size(const corecryptoMode modeObject) { return modeObject.cbc->size + 16; }
140static size_t cccbc_mode_get_block_size(const corecryptoMode modeObject) { return modeObject.cbc->block_size; }
141static void cccbc_mode_setup(const corecryptoMode modeObj, const void *iv,
142                             const void *key, size_t keylen, const void *tweak,
143                             size_t tweaklen, int options, modeCtx ctx)
144{
145    CC_XMEMCPY(ctx.cbc->iv, iv, modeObj.cbc->block_size);
146    modeObj.cbc->init(modeObj.cbc, &ctx.cbc->cbc, keylen, key);
147}
148
149static void cccbc_mode_crypt(const corecryptoMode modeObj, const void *in, void *out, size_t len, modeCtx ctx)
150{
151    modeObj.cbc->cbc(&ctx.cbc->cbc, (cccbc_iv *) ctx.cbc->iv, len / cccbc_mode_get_block_size(modeObj), in, out);
152}
153
154static int cccbc_getiv(const corecryptoMode modeObj, void *iv, uint32_t *len, modeCtx ctx)
155{
156    if(*len < cccbc_mode_get_block_size(modeObj)) {
157        *len = (uint32_t) cccbc_mode_get_block_size(modeObj);
158        return -1;
159    }
160    CC_XMEMCPY(iv, ctx.cbc->iv, *len = (uint32_t) cccbc_mode_get_block_size(modeObj));
161    return 0;
162}
163
164static int cccbc_setiv(const corecryptoMode modeObj, const void *iv, uint32_t len, modeCtx ctx)
165{
166    if(len != cccbc_mode_get_block_size(modeObj)) return -1;
167    CC_XMEMCPY(ctx.cbc->iv, iv, cccbc_mode_get_block_size(modeObj));
168    return 0;
169}
170
171const cc2CCModeDescriptor cccbc_mode = {
172    .mode_get_ctx_size = cccbc_mode_get_ctx_size,
173    .mode_get_block_size = cccbc_mode_get_block_size,
174    .mode_setup = cccbc_mode_setup,
175    .mode_encrypt = cccbc_mode_crypt,
176    .mode_decrypt = cccbc_mode_crypt,
177    .mode_encrypt_tweaked = NULL,
178    .mode_decrypt_tweaked = NULL,
179    .mode_done = NULL,
180    .mode_setiv = cccbc_setiv,
181    .mode_getiv = cccbc_getiv
182};
183
184// CFB
185
186static size_t cccfb_mode_get_ctx_size(const corecryptoMode modeObject) { return modeObject.cfb->size; }
187static size_t cccfb_mode_get_block_size(const corecryptoMode modeObject) { return modeObject.cfb->block_size; }
188static void cccfb_mode_setup(const corecryptoMode modeObj, const void *iv,
189                             const void *key, size_t keylen, const void *tweak,
190                             size_t tweaklen, int options, modeCtx ctx)
191{
192    modeObj.cfb->init(modeObj.cfb, ctx.cfb, keylen, key, iv);
193}
194
195static void cccfb_mode_crypt(const corecryptoMode modeObj, const void *in, void *out, size_t len, modeCtx ctx)
196{
197    modeObj.cfb->cfb(ctx.cfb, len / cccfb_mode_get_block_size(modeObj), in, out);
198}
199
200const cc2CCModeDescriptor cccfb_mode = {
201    .mode_get_ctx_size = cccfb_mode_get_ctx_size,
202    .mode_get_block_size = cccfb_mode_get_block_size,
203    .mode_setup = cccfb_mode_setup,
204    .mode_encrypt = cccfb_mode_crypt,
205    .mode_decrypt = cccfb_mode_crypt,
206    .mode_encrypt_tweaked = NULL,
207    .mode_decrypt_tweaked = NULL,
208    .mode_done = NULL,
209    .mode_setiv = NULL,
210    .mode_getiv = NULL
211};
212
213
214// CFB8
215
216static size_t cccfb8_mode_get_ctx_size(const corecryptoMode modeObject) { return modeObject.cfb8->size; }
217static size_t cccfb8_mode_get_block_size(const corecryptoMode modeObject) { return modeObject.cfb8->block_size; }
218static void cccfb8_mode_setup(const corecryptoMode modeObj, const void *iv,
219                              const void *key, size_t keylen, const void *tweak,
220                              size_t tweaklen, int options, modeCtx ctx)
221{
222    modeObj.cfb8->init(modeObj.cfb8, ctx.cfb8, keylen, key, iv);
223}
224
225static void cccfb8_mode_crypt(const corecryptoMode modeObj, const void *in, void *out, size_t len, modeCtx ctx)
226{
227    modeObj.cfb8->cfb8(ctx.cfb8, len / cccfb8_mode_get_block_size(modeObj), in, out);
228}
229
230const cc2CCModeDescriptor cccfb8_mode = {
231    .mode_get_ctx_size = cccfb8_mode_get_ctx_size,
232    .mode_get_block_size = cccfb8_mode_get_block_size,
233    .mode_setup = cccfb8_mode_setup,
234    .mode_encrypt = cccfb8_mode_crypt,
235    .mode_decrypt = cccfb8_mode_crypt,
236    .mode_encrypt_tweaked = NULL,
237    .mode_decrypt_tweaked = NULL,
238    .mode_done = NULL,
239    .mode_setiv = NULL,
240    .mode_getiv = NULL
241};
242
243// CTR
244
245static size_t ccctr_mode_get_ctx_size(const corecryptoMode modeObject) { return modeObject.ctr->size; }
246static size_t ccctr_mode_get_block_size(const corecryptoMode modeObject) { return modeObject.ctr->block_size; }
247static void ccctr_mode_setup(const corecryptoMode modeObj, const void *iv,
248                             const void *key, size_t keylen, const void *tweak,
249                             size_t tweaklen, int options, modeCtx ctx)
250{
251    modeObj.ctr->init(modeObj.ctr, ctx.ctr, keylen, key, iv);
252}
253
254static void ccctr_mode_crypt(const corecryptoMode modeObj, const void *in, void *out, size_t len, modeCtx ctx)
255{
256    modeObj.ctr->ctr(ctx.ctr, len / ccctr_mode_get_block_size(modeObj), in, out);
257}
258
259const cc2CCModeDescriptor ccctr_mode = {
260    .mode_get_ctx_size = ccctr_mode_get_ctx_size,
261    .mode_get_block_size = ccctr_mode_get_block_size,
262    .mode_setup = ccctr_mode_setup,
263    .mode_encrypt = ccctr_mode_crypt,
264    .mode_decrypt = ccctr_mode_crypt,
265    .mode_encrypt_tweaked = NULL,
266    .mode_decrypt_tweaked = NULL,
267    .mode_done = NULL,
268    .mode_setiv = NULL,
269    .mode_getiv = NULL
270};
271
272// OFB
273
274static size_t ccofb_mode_get_ctx_size(const corecryptoMode modeObject) { return modeObject.ofb->size; }
275static size_t ccofb_mode_get_block_size(const corecryptoMode modeObject) { return modeObject.ofb->block_size; }
276static void ccofb_mode_setup(const corecryptoMode modeObj, const void *iv,
277                             const void *key, size_t keylen, const void *tweak,
278                             size_t tweaklen, int options, modeCtx ctx)
279{
280    modeObj.ofb->init(modeObj.ofb, ctx.ofb, keylen, key, iv);
281}
282
283static void ccofb_mode_crypt(const corecryptoMode modeObj, const void *in, void *out, size_t len, modeCtx ctx)
284{
285    modeObj.ofb->ofb(ctx.ofb, len / ccofb_mode_get_block_size(modeObj), in, out);
286}
287
288const cc2CCModeDescriptor ccofb_mode = {
289    .mode_get_ctx_size = ccofb_mode_get_ctx_size,
290    .mode_get_block_size = ccofb_mode_get_block_size,
291    .mode_setup = ccofb_mode_setup,
292    .mode_encrypt = ccofb_mode_crypt,
293    .mode_decrypt = ccofb_mode_crypt,
294    .mode_encrypt_tweaked = NULL,
295    .mode_decrypt_tweaked = NULL,
296    .mode_done = NULL,
297    .mode_setiv = NULL,
298    .mode_getiv = NULL
299};
300
301// XTS
302/* For now we always schedule both encrypt and decrypt contexts for AES-XTS.  Original CommonCrypto support
303 * allowed a "both" (kCCEncrypt and kCCDecrypt) capability used for AES-XTS block I/O.  The initialization
304 * and correct mode objext and context passing are done at the CommonCryptor layer.
305 */
306
307
308static size_t ccxts_mode_get_ctx_size(const corecryptoMode modeObject) { return modeObject.xts->size; }
309static size_t ccxts_mode_get_block_size(const corecryptoMode modeObject) { return modeObject.xts->block_size; }
310static void ccxts_mode_setup(const corecryptoMode modeObj, const void *iv,
311                             const void *key, size_t keylen, const void *tweak,
312                             size_t tweaklen, int options, modeCtx ctx)
313{
314    modeObj.xts->init(modeObj.xts, ctx.xts, keylen, key, tweak);
315}
316
317#ifdef UNUSED_INTERFACE
318static void ccxts_mode_crypt(const corecryptoMode modeObj, const void *in, void *out, size_t len, modeCtx ctx)
319{
320    modeObj.xts->xts(ctx.xts, len / ccxts_mode_get_block_size(modeObj), in, out);
321}
322
323static int ccxts_setiv(const corecryptoMode modeObj, const void *iv, uint32_t len, modeCtx ctx)
324{
325    if(len != modeObj.xts->block_size) return -1;
326    modeObj.xts->set_tweak(ctx.xts, iv);
327    return 0;
328}
329
330static int ccxts_getiv(const corecryptoMode modeObj, void *iv, uint32_t *len, modeCtx ctx)
331{
332    if(*len < modeObj.xts->block_size) {
333        *len = modeObj.xts->block_size;
334        return -1;
335    }
336    CC_XMEMCPY(iv, modeObj.xts->xts(ctx.xts, 0, NULL, NULL), *len = modeObj.xts->block_size);
337    return 0;
338}
339#endif
340
341/*
342 * These match what we had in libtomcrypt - they really are "this is a logical block" routines, so need
343 * to handle partial blocks - so we use corecrypto's xts pad routines in every case.
344 */
345
346static void ccxts_mode_encrypt_tweak(const corecryptoMode modeObj, const void *in, size_t len, void *out, const void *iv, modeCtx ctx)
347{
348    ccxts_tweak_decl(ccxts_context_size(modeObj.xts), tweak);
349    modeObj.xts->set_tweak(ctx.xts, tweak, iv);
350    ccpad_xts_encrypt(modeObj.xts, ctx.xts, tweak, len, in, out);
351}
352
353static void ccxts_mode_decrypt_tweak(const corecryptoMode modeObj, const void *in, size_t len, void *out, const void *iv, modeCtx ctx)
354{
355    ccxts_tweak_decl(ccxts_context_size(modeObj.xts), tweak);
356    modeObj.xts->set_tweak(ctx.xts, tweak, iv);
357    ccpad_xts_decrypt(modeObj.xts, ctx.xts, tweak, len, in, out);
358}
359
360
361const cc2CCModeDescriptor ccxts_mode = {
362    .mode_get_ctx_size = ccxts_mode_get_ctx_size,
363    .mode_get_block_size = ccxts_mode_get_block_size,
364    .mode_setup = ccxts_mode_setup,
365    .mode_encrypt = NULL,
366    .mode_decrypt = NULL,
367    .mode_encrypt_tweaked = ccxts_mode_encrypt_tweak,
368    .mode_decrypt_tweaked = ccxts_mode_decrypt_tweak,
369    .mode_done = NULL,
370    .mode_setiv = NULL,
371    .mode_getiv = NULL
372};
373
374// GCM
375
376static size_t ccgcm_mode_get_ctx_size(const corecryptoMode modeObject) { return modeObject.gcm->size; }
377static size_t ccgcm_mode_get_block_size(const corecryptoMode modeObject) { return modeObject.gcm->block_size; }
378static void ccgcm_mode_setup(const corecryptoMode modeObj, const void *iv,
379                             const void *key, size_t keylen, const void *tweak,
380                             size_t tweaklen, int options, modeCtx ctx)
381{
382    modeObj.gcm->init(modeObj.gcm, ctx.gcm, keylen, key);
383}
384
385static void ccgcm_mode_crypt(const corecryptoMode modeObj, const void *in, void *out, size_t len, modeCtx ctx)
386{
387    modeObj.gcm->gcm(ctx.gcm, len, in, out);
388}
389
390static int ccgcm_setiv(const corecryptoMode modeObj, const void *iv, uint32_t len, modeCtx ctx)
391{
392    modeObj.gcm->set_iv(ctx.gcm, len, iv);
393    return 0;
394}
395
396
397const cc2CCModeDescriptor ccgcm_mode = {
398    .mode_get_ctx_size = ccgcm_mode_get_ctx_size,
399    .mode_get_block_size = ccgcm_mode_get_block_size,
400    .mode_setup = ccgcm_mode_setup,
401    .mode_encrypt = ccgcm_mode_crypt,
402    .mode_decrypt = ccgcm_mode_crypt,
403    .mode_encrypt_tweaked = NULL,
404    .mode_decrypt_tweaked = NULL,
405    .mode_done = NULL,
406    .mode_setiv = ccgcm_setiv,
407    .mode_getiv = NULL
408};
409
410// CCM
411
412static size_t ccccm_mode_get_ctx_size(const corecryptoMode modeObject) { return modeObject.ccm->size + sizeof(ccm_nonce_ctx); }
413static size_t ccccm_mode_get_block_size(const corecryptoMode modeObject) { return modeObject.ccm->block_size; }
414static void ccccm_mode_setup(const corecryptoMode modeObj, const void *iv,
415                             const void *key, size_t keylen, const void *tweak,
416                             size_t tweaklen, int options, modeCtx ctx)
417{
418    modeObj.ccm->init(modeObj.ccm, &ctx.ccm->ccm, keylen, key);
419    ctx.ccm->nonce_size = (size_t) 0xffffffffffffffff;
420    ctx.ccm->mac_size = (size_t) 0xffffffffffffffff;
421    ctx.ccm->ad_len = (size_t) 0xffffffffffffffff;
422    ctx.ccm->total_len = (size_t) 0xffffffffffffffff;
423}
424
425static void ccccm_mode_crypt(const corecryptoMode modeObj, const void *in, void *out, size_t len, modeCtx ctx)
426{
427    modeObj.ccm->ccm(&ctx.ccm->ccm, (ccccm_nonce *) &ctx.ccm->nonce, len, in, out);
428}
429
430static int ccccm_mode_done(const corecryptoMode modeObj, modeCtx ctx)
431{
432    modeObj.ccm->finalize(&ctx.ccm->ccm, (ccccm_nonce *) &ctx.ccm->nonce, ctx.ccm->mac);
433    ctx.ccm->mac_size = ctx.ccm->nonce.mac_size;
434    return 0;
435}
436
437const cc2CCModeDescriptor ccccm_mode = {
438    .mode_get_ctx_size = ccccm_mode_get_ctx_size,
439    .mode_get_block_size = ccccm_mode_get_block_size,
440    .mode_setup = ccccm_mode_setup,
441    .mode_encrypt = ccccm_mode_crypt,
442    .mode_decrypt = ccccm_mode_crypt,
443    .mode_encrypt_tweaked = NULL,
444    .mode_decrypt_tweaked = NULL,
445    .mode_done = ccccm_mode_done,
446    .mode_setiv = NULL,
447    .mode_getiv = NULL
448};
449
450
451// Padding
452
453static int ccpkcs7_encrypt_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *cipherText, size_t *moved)
454{
455    ccpad_pkcs7_encrypt(modeObj.cbc, &ctx.cbc->cbc, (cccbc_iv*) ctx.cbc->iv, len, buff, cipherText);
456    *moved = modeptr->mode_get_block_size(modeObj);
457    return 0;
458}
459static int ccpkcs7_decrypt_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *plainText, size_t *moved)
460{
461    *moved = ccpad_pkcs7_decrypt(modeObj.cbc, &ctx.cbc->cbc, (cccbc_iv*) ctx.cbc->iv, len, buff, plainText);
462    return 0;
463}
464
465
466static int ccpkcs7_encrypt_ecb_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *cipherText, size_t *moved)
467{
468    ccpad_pkcs7_ecb_encrypt(modeObj.ecb, ctx.ecb, len, buff, cipherText);
469    *moved = modeptr->mode_get_block_size(modeObj);
470    return 0;
471}
472static int ccpkcs7_decrypt_ecb_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *plainText, size_t *moved)
473{
474    *moved = ccpad_pkcs7_ecb_decrypt(modeObj.ecb, ctx.ecb, len, buff, plainText);
475    return 0;
476}
477
478
479/*
480 * Maximum space needed for padding.
481 */
482
483// Utility functions
484static inline size_t cc_round_down_by_blocksize(const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, size_t length) {
485    size_t blocksize = modeptr->mode_get_block_size(modeObj);
486    return length / blocksize * blocksize;
487}
488
489static inline size_t cc_round_up_by_blocksize(const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, size_t length) {
490    return cc_round_down_by_blocksize(modeptr, modeObj, length + modeptr->mode_get_block_size(modeObj) - 1);
491}
492
493#define MAXBLOCKSIZE_PKCS7 128
494
495static size_t ccpkcs7_padlen(int encrypting, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, size_t inputLength, bool final)
496{
497    size_t retval;
498
499    if(final) {
500        if(encrypting) retval = cc_round_down_by_blocksize(modeptr, modeObj, inputLength+modeptr->mode_get_block_size(modeObj)); // round up to blocksize
501        else retval = inputLength; // largest would be inputLength - 1 actually.
502    } else {
503        if(encrypting) retval = cc_round_down_by_blocksize(modeptr, modeObj, inputLength); // round down to blocksize
504        else {
505            if(inputLength && (inputLength % modeptr->mode_get_block_size(modeObj) == 0)) inputLength--;
506            retval = cc_round_down_by_blocksize(modeptr, modeObj, inputLength);
507        }
508    }
509
510    return retval;
511}
512
513/*
514 * How many bytes to reserve to enable padding - this is pre-encrypt/decrypt bytes.
515 */
516
517static size_t ccpkcs7_reserve(int encrypt, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj)
518{
519    if(encrypt) {
520		return 0;
521    } else {
522    	return modeptr->mode_get_block_size(modeObj);
523    }
524}
525
526const cc2CCPaddingDescriptor ccpkcs7_pad = {
527    .encrypt_pad = ccpkcs7_encrypt_pad,
528    .decrypt_pad = ccpkcs7_decrypt_pad,
529    .padlen = ccpkcs7_padlen,
530    .padreserve = ccpkcs7_reserve,
531};
532
533const cc2CCPaddingDescriptor ccpkcs7_ecb_pad = {
534    .encrypt_pad = ccpkcs7_encrypt_ecb_pad,
535    .decrypt_pad = ccpkcs7_decrypt_ecb_pad,
536    .padlen = ccpkcs7_padlen,
537    .padreserve = ccpkcs7_reserve,
538};
539
540
541static int cccts1_encrypt_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *cipherText, size_t *moved)
542{
543    ccpad_cts1_encrypt(modeObj.cbc, &ctx.cbc->cbc, (cccbc_iv*) ctx.cbc->iv, len, buff, cipherText);
544    *moved = len;
545    return 0;
546}
547static int cccts1_decrypt_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *plainText, size_t *moved)
548{
549    ccpad_cts1_decrypt(modeObj.cbc, &ctx.cbc->cbc, (cccbc_iv*) ctx.cbc->iv, len, buff, plainText);
550    *moved = len;
551    return 0;
552}
553
554static int cccts2_encrypt_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *cipherText, size_t *moved)
555{
556    ccpad_cts2_encrypt(modeObj.cbc, &ctx.cbc->cbc, (cccbc_iv*) ctx.cbc->iv, len, buff, cipherText);
557    *moved = len;
558    return 0;
559}
560static int cccts2_decrypt_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *plainText, size_t *moved)
561{
562    ccpad_cts2_decrypt(modeObj.cbc, &ctx.cbc->cbc, (cccbc_iv*) ctx.cbc->iv, len, buff, plainText);
563    *moved = len;
564    return 0;
565}
566
567
568static int cccts3_encrypt_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *cipherText, size_t *moved)
569{
570    ccpad_cts3_encrypt(modeObj.cbc, &ctx.cbc->cbc, (cccbc_iv*) ctx.cbc->iv, len, buff, cipherText);
571    *moved = len;
572    return 0;
573}
574static int cccts3_decrypt_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *plainText, size_t *moved)
575{
576    ccpad_cts3_decrypt(modeObj.cbc, &ctx.cbc->cbc, (cccbc_iv*) ctx.cbc->iv, len, buff, plainText);
577    *moved = len;
578    return 0;
579}
580
581
582
583/*
584 * Maximum space needed for padding.
585 */
586
587#define MAXBLOCKSIZE_PKCS7 128
588
589static size_t ccctsX_padlen(int encrypting, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, size_t inputLength, bool final)
590{
591    size_t retval;
592    size_t blocksize = modeptr->mode_get_block_size(modeObj);
593    if(final) {
594        if(encrypting) retval = cc_round_up_by_blocksize(modeptr, modeObj, inputLength); // round up to blocksize
595        else retval = inputLength; // largest would be inputLength - 1 actually.
596    } else {
597        if(encrypting) {
598            if(inputLength <= blocksize) retval = 0;
599            else retval = cc_round_down_by_blocksize(modeptr, modeObj, inputLength - blocksize);
600        }
601        else retval = inputLength; // largest would be inputLength - 1 actually.
602    }
603
604    return retval;
605}
606
607/*
608 * How many bytes to reserve to enable padding - this is pre-encrypt/decrypt bytes.
609 */
610
611static size_t ccctsX_reserve(int encrypt, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj)
612{
613    return modeptr->mode_get_block_size(modeObj) * 2;
614}
615
616const cc2CCPaddingDescriptor cccts1_pad = {
617    .encrypt_pad = cccts1_encrypt_pad,
618    .decrypt_pad = cccts1_decrypt_pad,
619    .padlen = ccctsX_padlen,
620    .padreserve = ccctsX_reserve,
621};
622
623const cc2CCPaddingDescriptor cccts2_pad = {
624    .encrypt_pad = cccts2_encrypt_pad,
625    .decrypt_pad = cccts2_decrypt_pad,
626    .padlen = ccctsX_padlen,
627    .padreserve = ccctsX_reserve,
628};
629
630
631const cc2CCPaddingDescriptor cccts3_pad = {
632    .encrypt_pad = cccts3_encrypt_pad,
633    .decrypt_pad = cccts3_decrypt_pad,
634    .padlen = ccctsX_padlen,
635    .padreserve = ccctsX_reserve,
636};
637
638
639static int ccnopad_encrypt_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *cipherText, size_t *moved)
640{
641    *moved = 0;
642    if(len != 0) return -1;
643    return 0;
644}
645static int ccnopad_decrypt_pad(modeCtx ctx, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, void *buff, size_t len, void *plainText, size_t *moved)
646{
647    *moved = 0;
648    if(len != 0) return -1;
649    return 0;
650}
651
652/*
653 * Maximum space needed for padding.
654 */
655
656static size_t ccnopad_padlen(int encrypting, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj, size_t inputLength, bool final)
657{
658    return cc_round_down_by_blocksize(modeptr, modeObj, inputLength);
659}
660
661/*
662 * How many bytes to reserve to enable padding - this is pre-encrypt/decrypt bytes.
663 */
664
665static size_t ccnopad_reserve(int encrypt, const cc2CCModeDescriptor *modeptr, const corecryptoMode modeObj)
666{
667    return 0;
668}
669
670const cc2CCPaddingDescriptor ccnopad_pad = {
671    .encrypt_pad = ccnopad_encrypt_pad,
672    .decrypt_pad = ccnopad_decrypt_pad,
673    .padlen = ccnopad_padlen,
674    .padreserve = ccnopad_reserve,
675};
676
677
678