1/*
2 * Copyright (c) 1999-2001,2005-2008,2010-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/*
25 * symCipher.c - CommonCrypto-based symmetric cipher module
26 */
27
28/* THIS FILE CONTAINS KERNEL CODE */
29
30#include "sslBuildFlags.h"
31#include "sslDebug.h"
32#include "sslMemory.h"
33#include "symCipher.h"
34#include "cipherSpecs.h"
35#include "SSLRecordInternal.h"
36
37#ifdef KERNEL
38
39#include <corecrypto/ccaes.h>
40#include <corecrypto/ccdes.h>
41#include <corecrypto/ccmode.h>
42
43#include <AssertMacros.h>
44
45struct SymCipherContext {
46    const struct ccmode_cbc *cbc;
47    cccbc_ctx u[]; /* this will have the key and iv */
48};
49
50/* Macros for accessing the content of a SymCipherContext */
51
52/*
53 SymCipherContext looks like this in memory:
54
55 {
56    const struct ccmode_cbc *cbc;
57    cccbc_ctx key[n];
58    cccbc_iv  iv[m];
59 }
60
61 cccbc_ctx and cccbc_iv are typedef-ined as aligned opaque struct, the actual contexts are arrays
62 of those types normally declared with a cc_ctx_decl macro.
63 The cc_ctx_n macros gives the number of elements in those arrays that are needed to store the
64 contexts.
65 The size of the context depends on the actual cbc implementation used.
66*/
67
68
69/* CTX_SIZE: Total size of the SymCipherContext struct for a cbc implementation */
70static inline
71size_t CTX_SIZE(const struct ccmode_cbc *cbc)
72{
73#ifdef __CC_HAS_FIX_FOR_11468135__
74    return (sizeof(SymCipherContext) + (sizeof(cccbc_ctx) * (cc_ctx_n(cccbc_ctx, cbc->size) + cc_ctx_n(cccbc_iv, cbc->block_size))));
75#else
76    /* This is approximate, but will work in that case, this code will go away after we transition */
77    return (sizeof(SymCipherContext) + sizeof(cccbc_ctx) + cbc->size);
78#endif
79}
80
81/* CTX_KEY: Address of the key context in the SymCipherContext struct */
82static inline
83cccbc_ctx *CTX_KEY(struct SymCipherContext *ctx)
84{
85    return &ctx->u[0];
86}
87
88
89/* CTX_IV: Address of the iv context in the SymCipherContext struct */
90#ifdef __CC_HAS_FIX_FOR_11468135__
91static inline
92cccbc_iv *CTX_IV(struct SymCipherContext *ctx)
93{
94    return (cccbc_iv *)&ctx->u[cc_ctx_n(cccbc_ctx, ctx->cbc->size)];
95}
96#endif
97
98static
99const void *ccmode(SSL_CipherAlgorithm alg, int enc)
100{
101    switch(alg) {
102        case SSL_CipherAlgorithmAES_128_CBC:
103        case SSL_CipherAlgorithmAES_256_CBC:
104            return enc?ccaes_cbc_encrypt_mode():ccaes_cbc_decrypt_mode();
105        case SSL_CipherAlgorithm3DES_CBC:
106            return enc?ccdes3_cbc_encrypt_mode():ccdes3_cbc_decrypt_mode();
107        case SSL_CipherAlgorithmAES_128_GCM:
108        case SSL_CipherAlgorithmAES_256_GCM:
109        case SSL_CipherAlgorithmRC4_128:
110            /* TODO: we should do RC4 for TLS, but we dont need it for DTLS */
111        default:
112            check(0);
113            return NULL; /* This will cause CCCryptorCreate to return an error */
114    }
115}
116
117static
118int CCSymmInit(
119    const SSLSymmetricCipherParams *params,
120    int encrypting,
121    uint8_t *key,
122    uint8_t* iv,
123    SymCipherContext *cipherCtx)
124{
125    check(cipherCtx!=NULL);
126    check(params);
127    SymCipherContext ctx = *cipherCtx;
128
129	/*
130	 * Cook up a cccbx_ctx object. Assumes:
131	 * 		cipherCtx->symCipher.keyAlg
132	 *		cipherCtx->encrypting
133	 * 		key (raw key bytes)
134	 *		iv (raw bytes)
135	 * On successful exit:
136	 * 		Resulting ccmode --> cipherCtx
137	 */
138
139    /* FIXME: this should not be needed as long as CCSymFinish is called */
140	if(ctx) {
141        sslFree(ctx);
142        ctx = NULL;
143	}
144
145    const struct ccmode_cbc *cbc = ccmode(params->keyAlg, encrypting);
146
147    ctx = sslMalloc(CTX_SIZE(cbc));
148
149    if(ctx==NULL) {
150        sslErrorLog("CCSymmInit: Can't allocate context\n");
151        return errSSLRecordInternal;
152    }
153
154    ctx->cbc = cbc;
155
156#ifdef __CC_HAS_FIX_FOR_11468135__
157    cccbc_init(cbc, CTX_KEY(ctx), params->keySize, key);
158    cccbc_set_iv(cbc, CTX_IV(ctx), iv);
159#else
160    cccbc_init(cbc, CTX_KEY(ctx), params->keySize, key, iv);
161#endif
162
163    *cipherCtx = ctx;
164	return 0;
165}
166
167/* same for en/decrypt */
168static
169int CCSymmEncryptDecrypt(
170                         const uint8_t *src,
171                         uint8_t *dest,
172                         size_t len,
173                         SymCipherContext cipherCtx)
174{
175
176	ASSERT(cipherCtx != NULL);
177    ASSERT(cipherCtx->cbc != NULL);
178
179	if(cipherCtx == NULL || cipherCtx->cbc == NULL) {
180		sslErrorLog("CCSymmEncryptDecrypt: NULL cipherCtx\n");
181		return errSSLRecordInternal;
182	}
183
184    ASSERT((len%cipherCtx->cbc->block_size)==0);
185
186    if(len%cipherCtx->cbc->block_size) {
187        sslErrorLog("CCSymmEncryptDecrypt: Invalid size\n");
188        return errSSLRecordInternal;
189    }
190
191    unsigned long nblocks = len/cipherCtx->cbc->block_size;
192
193#ifdef __CC_HAS_FIX_FOR_11468135__
194    cccbc_update(cipherCtx->cbc, CTX_KEY(cipherCtx), CTX_IV(cipherCtx), nblocks, src, dest);
195#else
196    cipherCtx->cbc->cbc(CTX_KEY(cipherCtx), nblocks, src, dest);
197#endif
198	return 0;
199}
200
201static
202int CCSymmFinish(
203                 SymCipherContext cipherCtx)
204{
205	if(cipherCtx) {
206        sslFree(cipherCtx);
207	}
208	return 0;
209}
210
211
212#else
213
214#define ENABLE_RC4      1
215#define ENABLE_3DES     1
216#define ENABLE_AES      1
217#define ENABLE_AES256   1
218
219/*
220 * CommonCrypto-based symmetric cipher callouts
221 */
222#include <CommonCrypto/CommonCryptor.h>
223#include <CommonCrypto/CommonCryptorSPI.h>
224#include <assert.h>
225
226static
227CCAlgorithm CCAlg(SSL_CipherAlgorithm alg)
228{
229    switch(alg) {
230        case SSL_CipherAlgorithmAES_128_CBC:
231        case SSL_CipherAlgorithmAES_256_CBC:
232        case SSL_CipherAlgorithmAES_128_GCM:
233        case SSL_CipherAlgorithmAES_256_GCM:
234            return kCCAlgorithmAES128;          /* AES128 here means 128bit block size, not key size */
235        case SSL_CipherAlgorithm3DES_CBC:
236            return kCCAlgorithm3DES;
237        case SSL_CipherAlgorithmDES_CBC:
238            return kCCAlgorithmDES;
239        case SSL_CipherAlgorithmRC4_128:
240            return kCCAlgorithmRC4;
241        case SSL_CipherAlgorithmRC2_128:
242            return kCCAlgorithmRC2;
243        default:
244            assert(0);
245            return (CCAlgorithm)(-1); /* This will cause CCCryptorCreate to return an error */
246    }
247}
248
249static CCOptions CCOpt(CipherType cipherType)
250{
251#if 0
252    if(cipherType==aeadCipherType) return kCCModeGCM;
253#endif
254    return 0;
255}
256
257static
258int CCSymmInit(
259    const SSLSymmetricCipherParams *params,
260    int encrypting,
261	uint8_t *key,
262	uint8_t* iv,
263	SymCipherContext *cipherCtx)
264{
265    assert(cipherCtx!=NULL);
266
267	/*
268	 * Cook up a CCCryptorRef. Assumes:
269	 * 		cipherCtx->symCipher.keyAlg
270	 *		cipherCtx->encrypting
271	 * 		key (raw key bytes)
272	 *		iv (raw bytes)
273	 * On successful exit:
274	 * 		Resulting CCCryptorRef --> cipherCtx->cryptorRef
275	 */
276	CCCryptorStatus ccrtn;
277	CCOperation op = encrypting ? kCCEncrypt : kCCDecrypt;
278    CCCryptorRef cryptorRef = (CCCryptorRef)*cipherCtx;
279
280    /* FIXME: this should not be needed as long as CCSymFinish is called */
281	if(cryptorRef) {
282		CCCryptorRelease(cryptorRef);
283		cryptorRef = NULL;
284	}
285
286	ccrtn = CCCryptorCreate(op, CCAlg(params->keyAlg),
287        /* options - gcm or no padding, default CBC */
288        CCOpt(params->cipherType),
289		key, params->keySize,
290		iv,
291		&cryptorRef);
292	if(ccrtn) {
293		sslErrorLog("CCCryptorCreate returned %d\n", (int)ccrtn);
294		return errSSLRecordInternal;
295	}
296    *cipherCtx = (SymCipherContext)cryptorRef;
297	return 0;
298}
299
300/* same for en/decrypt */
301static
302int CCSymmEncryptDecrypt(
303                              const uint8_t *src,
304                              uint8_t *dest,
305                              size_t len,
306                              SymCipherContext cipherCtx)
307{
308	CCCryptorStatus ccrtn;
309	CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
310	ASSERT(cryptorRef != NULL);
311	if(cryptorRef == NULL) {
312		sslErrorLog("CCSymmEncryptDecrypt: NULL cryptorRef\n");
313		return errSSLRecordInternal;
314	}
315    size_t data_moved;
316	ccrtn = CCCryptorUpdate(cryptorRef, src, len,
317                            dest, len, &data_moved);
318    assert(data_moved == len);
319#if SSL_DEBUG
320	if(ccrtn) {
321		sslErrorLog("CCSymmEncryptDecrypt: returned %d\n", (int)ccrtn);
322		return errSSLRecordInternal;
323	}
324#endif
325	return 0;
326}
327
328#if ENABLE_AES_GCM
329
330/* same for en/decrypt */
331static
332int CCSymmAEADSetIV(
333    const uint8_t *iv,
334    size_t len,
335    SymCipherContext cipherCtx)
336{
337	CCCryptorStatus ccrtn;
338	CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
339
340	ASSERT(cryptorRef != NULL);
341	if(cryptorRef == NULL) {
342		sslErrorLog("CCSymmAEADAddIV: NULL cryptorRef\n");
343		return errSecInternalComponent;
344	}
345	ccrtn = CCCryptorGCMAddIV(cryptorRef, iv, len);
346#if SSL_DEBUG
347	if(ccrtn) {
348		sslErrorLog("CCSymmAEADAddIV: returned %d\n", (int)ccrtn);
349		return errSSLRecordInternal;
350	}
351#endif
352	return 0;
353}
354
355/* same for en/decrypt */
356static
357int CCSymmAddADD(
358    const uint8_t *src,
359    size_t len,
360    SymCipherContext cipherCtx)
361{
362	CCCryptorStatus ccrtn;
363	CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
364
365	ASSERT(cryptorRef != NULL);
366	if(cryptorRef == NULL) {
367		sslErrorLog("CCSymmAddADD: NULL cryptorRef\n");
368		return errSSLRecordInternal;
369	}
370	ccrtn = CCCryptorGCMAddADD(cryptorRef, src, len);
371#if SSL_DEBUG
372	if(ccrtn) {
373		sslErrorLog("CCSymmAddADD: returned %d\n", (int)ccrtn);
374		return errSSLRecordInternal;
375	}
376#endif
377	return 0;
378}
379
380static
381int CCSymmAEADEncrypt(
382    const uint8_t *src,
383    uint8_t *dest,
384    size_t len,
385    SymCipherContext cipherCtx)
386{
387	CCCryptorStatus ccrtn;
388	CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
389
390	ASSERT(cryptorRef != NULL);
391	if(cryptorRef == NULL) {
392		sslErrorLog("CCSymmAEADEncrypt: NULL cryptorRef\n");
393		return errSSLRecordInternal;
394	}
395	ccrtn = CCCryptorGCMEncrypt(cryptorRef, src, len, dest);
396#if SSL_DEBUG
397	if(ccrtn) {
398		sslErrorLog("CCSymmAEADEncrypt: returned %d\n", (int)ccrtn);
399		return errSSLRecordInternal;
400	}
401#endif
402	return 0;
403}
404
405
406static
407int CCSymmAEADDecrypt(
408    const uint8_t *src,
409    uint8_t *dest,
410    size_t len,
411    SymCipherContext cipherCtx)
412{
413	CCCryptorStatus ccrtn;
414	CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
415
416	ASSERT(cipherCtx != NULL);
417	ASSERT(cipherCtx->cryptorRef != NULL);
418	if(cipherCtx->cryptorRef == NULL) {
419		sslErrorLog("CCSymmAEADDecrypt: NULL cryptorRef\n");
420		return errSSLRecordInternal;
421	}
422	ccrtn = CCCryptorGCMDecrypt(cryptorRef, src, len, dest);
423#if SSL_DEBUG
424	if(ccrtn) {
425		sslErrorLog("CCSymmAEADDecrypt: returned %d\n", (int)ccrtn);
426		return errSSLRecordInternal;
427	}
428#endif
429	return 0;
430}
431
432
433static
434int CCSymmAEADDone(
435    uint8_t *mac,
436    size_t *macLen,
437    SymCipherContext cipherCtx)
438{
439	CCCryptorStatus ccrtn;
440	CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
441
442	ASSERT(cipherCtx != NULL);
443	ASSERT(cipherCtx->cryptorRef != NULL);
444	if(cipherCtx->cryptorRef == NULL) {
445		sslErrorLog("CCSymmAEADDone: NULL cryptorRef\n");
446		return errSSLRecordInternal;
447	}
448	ccrtn = CCCryptorGCMFinal(cipherCtx->cryptorRef, mac, macLen);
449    CCCryptorStatus ccrtn2 = CCCryptorGCMReset(cipherCtx->cryptorRef);
450    if (ccrtn == kCCSuccess)
451        ccrtn = ccrtn2;
452#if SSL_DEBUG
453	if(ccrtn) {
454		sslErrorLog("CCSymmAEADDone: returned %d\n", (int)ccrtn);
455		return errSSLRecordInternal;
456	}
457#endif
458	return 0;
459}
460#endif
461
462static
463int CCSymmFinish(
464	SymCipherContext cipherCtx)
465{
466	CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
467
468	if(cryptorRef) {
469		CCCryptorRelease(cryptorRef);
470	}
471	return 0;
472}
473
474#endif /* KERNEL */
475
476#if	ENABLE_DES
477const SSLSymmetricCipher SSLCipherDES_CBC = {
478    .params = &SSLCipherDES_CBCParams,
479    .c.cipher = {
480        .initialize = CCSymmInit,
481        .encrypt = CCSymmEncryptDecrypt,
482        .decrypt = CCSymmEncryptDecrypt
483    },
484    .finish = CCSymmFinish
485};
486#endif	/* ENABLE_DES */
487
488#if	ENABLE_3DES
489const SSLSymmetricCipher SSLCipher3DES_CBC = {
490    .params = &SSLCipher3DES_CBCParams,
491    .c.cipher = {
492        .initialize = CCSymmInit,
493        .encrypt = CCSymmEncryptDecrypt,
494        .decrypt = CCSymmEncryptDecrypt
495    },
496    .finish = CCSymmFinish
497};
498#endif	/* ENABLE_3DES */
499
500#if		ENABLE_RC4
501const SSLSymmetricCipher SSLCipherRC4_128 = {
502    .params = &SSLCipherRC4_128Params,
503    .c.cipher = {
504        .initialize = CCSymmInit,
505        .encrypt = CCSymmEncryptDecrypt,
506        .decrypt = CCSymmEncryptDecrypt
507    },
508    .finish = CCSymmFinish
509};
510#endif	/* ENABLE_RC4 */
511
512#if		ENABLE_RC2
513const SSLSymmetricCipher SSLCipherRC2_128 = {
514    .params = &SSLCipherRC2_128Params,
515    .c.cipher = {
516        .initialize = CCSymmInit,
517        .encrypt = CCSymmEncryptDecrypt,
518        .decrypt = CCSymmEncryptDecrypt
519    },
520    .finish = CCSymmFinish
521};
522#endif	/* ENABLE_RC2*/
523
524#if		ENABLE_AES
525const SSLSymmetricCipher SSLCipherAES_128_CBC = {
526    .params = &SSLCipherAES_128_CBCParams,
527    .c.cipher = {
528        .initialize = CCSymmInit,
529        .encrypt = CCSymmEncryptDecrypt,
530        .decrypt = CCSymmEncryptDecrypt
531    },
532    .finish = CCSymmFinish
533};
534#endif	/* ENABLE_AES */
535
536#if ENABLE_AES256
537const SSLSymmetricCipher SSLCipherAES_256_CBC = {
538    .params = &SSLCipherAES_256_CBCParams,
539    .c.cipher = {
540        .initialize = CCSymmInit,
541        .encrypt = CCSymmEncryptDecrypt,
542        .decrypt = CCSymmEncryptDecrypt
543    },
544    .finish = CCSymmFinish
545};
546#endif /* ENABLE_AES256 */
547
548#if ENABLE_AES_GCM
549const SSLSymmetricCipher SSLCipherAES_128_GCM = {
550    .params = &SSLCipherAES_128_GCMParams,
551    .c.aead = {
552        .initialize = CCSymmInit,
553        .setIV = CCSymmAEADSetIV,
554        .update = CCSymmAddADD,
555        .encrypt = CCSymmAEADEncrypt,
556        .decrypt = CCSymmAEADDecrypt,
557        .done =  CCSymmAEADDone
558    },
559    .finish = CCSymmFinish
560};
561
562const SSLSymmetricCipher SSLCipherAES_256_GCM = {
563    .params = &SSLCipherAES_256_GCMParams,
564    .c.aead = {
565        .initialize = CCSymmInit,
566        .setIV = CCSymmAEADSetIV,
567        .update = CCSymmAddADD,
568        .encrypt = CCSymmAEADEncrypt,
569        .decrypt = CCSymmAEADDecrypt,
570        .done =  CCSymmAEADDone
571    },
572    .finish = CCSymmFinish
573};
574#endif /* ENABLE_AES_GCM */
575