X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/b1ab9ed8d0e0f1c3b66d7daa8fd5564444c56195..e3d3b979fd185d8303f28a937baa53a187fb8c7d:/libsecurity_ssl/lib/symCipher.c?ds=sidebyside diff --git a/libsecurity_ssl/lib/symCipher.c b/libsecurity_ssl/lib/symCipher.c index 45d9ef8e..aab1ec05 100644 --- a/libsecurity_ssl/lib/symCipher.c +++ b/libsecurity_ssl/lib/symCipher.c @@ -22,25 +22,248 @@ */ /* - * symCipher.c - CDSA-based symmetric cipher module + * symCipher.c - CommonCrypto-based symmetric cipher module */ -#include "sslContext.h" -#include "cryptType.h" +/* THIS FILE CONTAINS KERNEL CODE */ + +#include "sslBuildFlags.h" #include "sslDebug.h" #include "sslMemory.h" -#include #include "symCipher.h" +#include "cipherSpecs.h" +#include "SSLRecordInternal.h" + +#ifdef KERNEL + +#include +#include +#include + +#include + +struct SymCipherContext { + const struct ccmode_cbc *cbc; + cccbc_ctx u[]; /* this will have the key and iv */ +}; + +/* Macros for accessing the content of a SymCipherContext */ + +/* + SymCipherContext looks like this in memory: + + { + const struct ccmode_cbc *cbc; + cccbc_ctx key[n]; + cccbc_iv iv[m]; + } + + cccbc_ctx and cccbc_iv are typedef-ined as aligned opaque struct, the actual contexts are arrays + of those types normally declared with a cc_ctx_decl macro. + The cc_ctx_n macros gives the number of elements in those arrays that are needed to store the + contexts. + The size of the context depends on the actual cbc implementation used. +*/ + + +/* CTX_SIZE: Total size of the SymCipherContext struct for a cbc implementation */ +static inline +size_t CTX_SIZE(const struct ccmode_cbc *cbc) +{ +#ifdef __CC_HAS_FIX_FOR_11468135__ + return (sizeof(SymCipherContext) + (sizeof(cccbc_ctx) * (cc_ctx_n(cccbc_ctx, cbc->size) + cc_ctx_n(cccbc_iv, cbc->block_size)))); +#else + /* This is approximate, but will work in that case, this code will go away after we transition */ + return (sizeof(SymCipherContext) + sizeof(cccbc_ctx) + cbc->size); +#endif +} + +/* CTX_KEY: Address of the key context in the SymCipherContext struct */ +static inline +cccbc_ctx *CTX_KEY(struct SymCipherContext *ctx) +{ + return &ctx->u[0]; +} + + +/* CTX_IV: Address of the iv context in the SymCipherContext struct */ +#ifdef __CC_HAS_FIX_FOR_11468135__ +static inline +cccbc_iv *CTX_IV(struct SymCipherContext *ctx) +{ + return (cccbc_iv *)&ctx->u[cc_ctx_n(cccbc_ctx, ctx->cbc->size)]; +} +#endif + +static +const void *ccmode(SSL_CipherAlgorithm alg, int enc) +{ + switch(alg) { + case SSL_CipherAlgorithmAES_128_CBC: + case SSL_CipherAlgorithmAES_256_CBC: + return enc?ccaes_cbc_encrypt_mode():ccaes_cbc_decrypt_mode(); + case SSL_CipherAlgorithm3DES_CBC: + return enc?ccdes3_cbc_encrypt_mode():ccdes3_cbc_decrypt_mode(); + case SSL_CipherAlgorithmAES_128_GCM: + case SSL_CipherAlgorithmAES_256_GCM: + case SSL_CipherAlgorithmRC4_128: + /* TODO: we should do RC4 for TLS, but we dont need it for DTLS */ + default: + check(0); + return NULL; /* This will cause CCCryptorCreate to return an error */ + } +} + +static +int CCSymmInit( + const SSLSymmetricCipherParams *params, + int encrypting, + uint8_t *key, + uint8_t* iv, + SymCipherContext *cipherCtx) +{ + check(cipherCtx!=NULL); + check(params); + SymCipherContext ctx = *cipherCtx; + + /* + * Cook up a cccbx_ctx object. Assumes: + * cipherCtx->symCipher.keyAlg + * cipherCtx->encrypting + * key (raw key bytes) + * iv (raw bytes) + * On successful exit: + * Resulting ccmode --> cipherCtx + */ + + /* FIXME: this should not be needed as long as CCSymFinish is called */ + if(ctx) { + sslFree(ctx); + ctx = NULL; + } + + const struct ccmode_cbc *cbc = ccmode(params->keyAlg, encrypting); + + ctx = sslMalloc(CTX_SIZE(cbc)); + + if(ctx==NULL) { + sslErrorLog("CCSymmInit: Can't allocate context\n"); + return errSSLRecordInternal; + } + + ctx->cbc = cbc; + +#ifdef __CC_HAS_FIX_FOR_11468135__ + cccbc_init(cbc, CTX_KEY(ctx), params->keySize, key); + cccbc_set_iv(cbc, CTX_IV(ctx), iv); +#else + cccbc_init(cbc, CTX_KEY(ctx), params->keySize, key, iv); +#endif + + *cipherCtx = ctx; + return 0; +} + +/* same for en/decrypt */ +static +int CCSymmEncryptDecrypt( + const uint8_t *src, + uint8_t *dest, + size_t len, + SymCipherContext cipherCtx) +{ + + ASSERT(cipherCtx != NULL); + ASSERT(cipherCtx->cbc != NULL); + + if(cipherCtx == NULL || cipherCtx->cbc == NULL) { + sslErrorLog("CCSymmEncryptDecrypt: NULL cipherCtx\n"); + return errSSLRecordInternal; + } + + ASSERT((len%cipherCtx->cbc->block_size)==0); + + if(len%cipherCtx->cbc->block_size) { + sslErrorLog("CCSymmEncryptDecrypt: Invalid size\n"); + return errSSLRecordInternal; + } + + unsigned long nblocks = len/cipherCtx->cbc->block_size; + +#ifdef __CC_HAS_FIX_FOR_11468135__ + cccbc_update(cipherCtx->cbc, CTX_KEY(cipherCtx), CTX_IV(cipherCtx), nblocks, src, dest); +#else + cipherCtx->cbc->cbc(CTX_KEY(cipherCtx), nblocks, src, dest); +#endif + return 0; +} + +static +int CCSymmFinish( + SymCipherContext cipherCtx) +{ + if(cipherCtx) { + sslFree(cipherCtx); + } + return 0; +} + + +#else + +#define ENABLE_RC4 1 +#define ENABLE_3DES 1 +#define ENABLE_AES 1 +#define ENABLE_AES256 1 /* * CommonCrypto-based symmetric cipher callouts */ -OSStatus CCSymmInit( - uint8_t *key, - uint8_t* iv, - CipherContext *cipherCtx, - SSLContext *ctx) +#include +#include +#include + +static +CCAlgorithm CCAlg(SSL_CipherAlgorithm alg) +{ + switch(alg) { + case SSL_CipherAlgorithmAES_128_CBC: + case SSL_CipherAlgorithmAES_256_CBC: + case SSL_CipherAlgorithmAES_128_GCM: + case SSL_CipherAlgorithmAES_256_GCM: + return kCCAlgorithmAES128; /* AES128 here means 128bit block size, not key size */ + case SSL_CipherAlgorithm3DES_CBC: + return kCCAlgorithm3DES; + case SSL_CipherAlgorithmDES_CBC: + return kCCAlgorithmDES; + case SSL_CipherAlgorithmRC4_128: + return kCCAlgorithmRC4; + case SSL_CipherAlgorithmRC2_128: + return kCCAlgorithmRC2; + default: + assert(0); + return (CCAlgorithm)(-1); /* This will cause CCCryptorCreate to return an error */ + } +} + +static CCOptions CCOpt(CipherType cipherType) { +#if 0 + if(cipherType==aeadCipherType) return kCCModeGCM; +#endif + return 0; +} + +static +int CCSymmInit( + const SSLSymmetricCipherParams *params, + int encrypting, + uint8_t *key, + uint8_t* iv, + SymCipherContext *cipherCtx) +{ + assert(cipherCtx!=NULL); + /* * Cook up a CCCryptorRef. Assumes: * cipherCtx->symCipher.keyAlg @@ -51,62 +274,301 @@ OSStatus CCSymmInit( * Resulting CCCryptorRef --> cipherCtx->cryptorRef */ CCCryptorStatus ccrtn; - CCOperation op = cipherCtx->encrypting ? kCCEncrypt : kCCDecrypt; + CCOperation op = encrypting ? kCCEncrypt : kCCDecrypt; + CCCryptorRef cryptorRef = (CCCryptorRef)*cipherCtx; - if(cipherCtx->cryptorRef) { - CCCryptorRelease(cipherCtx->cryptorRef); - cipherCtx->cryptorRef = NULL; + /* FIXME: this should not be needed as long as CCSymFinish is called */ + if(cryptorRef) { + CCCryptorRelease(cryptorRef); + cryptorRef = NULL; } - ccrtn = CCCryptorCreate(op, cipherCtx->symCipher->keyAlg, - 0, /* options - no padding, default CBC */ - key, cipherCtx->symCipher->keySize, + ccrtn = CCCryptorCreate(op, CCAlg(params->keyAlg), + /* options - gcm or no padding, default CBC */ + CCOpt(params->cipherType), + key, params->keySize, iv, - &cipherCtx->cryptorRef); + &cryptorRef); if(ccrtn) { sslErrorLog("CCCryptorCreate returned %d\n", (int)ccrtn); - return internalComponentErr; + return errSSLRecordInternal; } - return noErr; + *cipherCtx = (SymCipherContext)cryptorRef; + return 0; } /* same for en/decrypt */ -OSStatus CCSymmEncryptDecrypt( - const uint8_t *src, - uint8_t *dest, - size_t len, - CipherContext *cipherCtx, - SSLContext *ctx) +static +int CCSymmEncryptDecrypt( + const uint8_t *src, + uint8_t *dest, + size_t len, + SymCipherContext cipherCtx) { CCCryptorStatus ccrtn; - - ASSERT(cipherCtx != NULL); - ASSERT(cipherCtx->cryptorRef != NULL); - if(cipherCtx->cryptorRef == NULL) { + CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; + ASSERT(cryptorRef != NULL); + if(cryptorRef == NULL) { sslErrorLog("CCSymmEncryptDecrypt: NULL cryptorRef\n"); - return internalComponentErr; + return errSSLRecordInternal; } size_t data_moved; - ccrtn = CCCryptorUpdate(cipherCtx->cryptorRef, src, len, - dest, len, &data_moved); + ccrtn = CCCryptorUpdate(cryptorRef, src, len, + dest, len, &data_moved); assert(data_moved == len); - #if SSL_DEBUG +#if SSL_DEBUG if(ccrtn) { sslErrorLog("CCSymmEncryptDecrypt: returned %d\n", (int)ccrtn); - return internalComponentErr; + return errSSLRecordInternal; + } +#endif + return 0; +} + +#if ENABLE_AES_GCM + +/* same for en/decrypt */ +static +int CCSymmAEADSetIV( + const uint8_t *iv, + size_t len, + SymCipherContext cipherCtx) +{ + CCCryptorStatus ccrtn; + CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; + + ASSERT(cryptorRef != NULL); + if(cryptorRef == NULL) { + sslErrorLog("CCSymmAEADAddIV: NULL cryptorRef\n"); + return errSecInternalComponent; + } + ccrtn = CCCryptorGCMAddIV(cryptorRef, iv, len); +#if SSL_DEBUG + if(ccrtn) { + sslErrorLog("CCSymmAEADAddIV: returned %d\n", (int)ccrtn); + return errSSLRecordInternal; + } +#endif + return 0; +} + +/* same for en/decrypt */ +static +int CCSymmAddADD( + const uint8_t *src, + size_t len, + SymCipherContext cipherCtx) +{ + CCCryptorStatus ccrtn; + CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; + + ASSERT(cryptorRef != NULL); + if(cryptorRef == NULL) { + sslErrorLog("CCSymmAddADD: NULL cryptorRef\n"); + return errSSLRecordInternal; + } + ccrtn = CCCryptorGCMAddADD(cryptorRef, src, len); +#if SSL_DEBUG + if(ccrtn) { + sslErrorLog("CCSymmAddADD: returned %d\n", (int)ccrtn); + return errSSLRecordInternal; + } +#endif + return 0; +} + +static +int CCSymmAEADEncrypt( + const uint8_t *src, + uint8_t *dest, + size_t len, + SymCipherContext cipherCtx) +{ + CCCryptorStatus ccrtn; + CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; + + ASSERT(cryptorRef != NULL); + if(cryptorRef == NULL) { + sslErrorLog("CCSymmAEADEncrypt: NULL cryptorRef\n"); + return errSSLRecordInternal; + } + ccrtn = CCCryptorGCMEncrypt(cryptorRef, src, len, dest); +#if SSL_DEBUG + if(ccrtn) { + sslErrorLog("CCSymmAEADEncrypt: returned %d\n", (int)ccrtn); + return errSSLRecordInternal; } - #endif - return noErr; +#endif + return 0; } -OSStatus CCSymmFinish( - CipherContext *cipherCtx, - SSLContext *ctx) + +static +int CCSymmAEADDecrypt( + const uint8_t *src, + uint8_t *dest, + size_t len, + SymCipherContext cipherCtx) { - if(cipherCtx->cryptorRef) { - CCCryptorRelease(cipherCtx->cryptorRef); - cipherCtx->cryptorRef = NULL; + CCCryptorStatus ccrtn; + CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; + + ASSERT(cipherCtx != NULL); + ASSERT(cipherCtx->cryptorRef != NULL); + if(cipherCtx->cryptorRef == NULL) { + sslErrorLog("CCSymmAEADDecrypt: NULL cryptorRef\n"); + return errSSLRecordInternal; + } + ccrtn = CCCryptorGCMDecrypt(cryptorRef, src, len, dest); +#if SSL_DEBUG + if(ccrtn) { + sslErrorLog("CCSymmAEADDecrypt: returned %d\n", (int)ccrtn); + return errSSLRecordInternal; } - return noErr; +#endif + return 0; } + +static +int CCSymmAEADDone( + uint8_t *mac, + size_t *macLen, + SymCipherContext cipherCtx) +{ + CCCryptorStatus ccrtn; + CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; + + ASSERT(cipherCtx != NULL); + ASSERT(cipherCtx->cryptorRef != NULL); + if(cipherCtx->cryptorRef == NULL) { + sslErrorLog("CCSymmAEADDone: NULL cryptorRef\n"); + return errSSLRecordInternal; + } + ccrtn = CCCryptorGCMFinal(cipherCtx->cryptorRef, mac, macLen); + CCCryptorStatus ccrtn2 = CCCryptorGCMReset(cipherCtx->cryptorRef); + if (ccrtn == kCCSuccess) + ccrtn = ccrtn2; +#if SSL_DEBUG + if(ccrtn) { + sslErrorLog("CCSymmAEADDone: returned %d\n", (int)ccrtn); + return errSSLRecordInternal; + } +#endif + return 0; +} +#endif + +static +int CCSymmFinish( + SymCipherContext cipherCtx) +{ + CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx; + + if(cryptorRef) { + CCCryptorRelease(cryptorRef); + } + return 0; +} + +#endif /* KERNEL */ + +#if ENABLE_DES +const SSLSymmetricCipher SSLCipherDES_CBC = { + .params = &SSLCipherDES_CBCParams, + .c.cipher = { + .initialize = CCSymmInit, + .encrypt = CCSymmEncryptDecrypt, + .decrypt = CCSymmEncryptDecrypt + }, + .finish = CCSymmFinish +}; +#endif /* ENABLE_DES */ + +#if ENABLE_3DES +const SSLSymmetricCipher SSLCipher3DES_CBC = { + .params = &SSLCipher3DES_CBCParams, + .c.cipher = { + .initialize = CCSymmInit, + .encrypt = CCSymmEncryptDecrypt, + .decrypt = CCSymmEncryptDecrypt + }, + .finish = CCSymmFinish +}; +#endif /* ENABLE_3DES */ + +#if ENABLE_RC4 +const SSLSymmetricCipher SSLCipherRC4_128 = { + .params = &SSLCipherRC4_128Params, + .c.cipher = { + .initialize = CCSymmInit, + .encrypt = CCSymmEncryptDecrypt, + .decrypt = CCSymmEncryptDecrypt + }, + .finish = CCSymmFinish +}; +#endif /* ENABLE_RC4 */ + +#if ENABLE_RC2 +const SSLSymmetricCipher SSLCipherRC2_128 = { + .params = &SSLCipherRC2_128Params, + .c.cipher = { + .initialize = CCSymmInit, + .encrypt = CCSymmEncryptDecrypt, + .decrypt = CCSymmEncryptDecrypt + }, + .finish = CCSymmFinish +}; +#endif /* ENABLE_RC2*/ + +#if ENABLE_AES +const SSLSymmetricCipher SSLCipherAES_128_CBC = { + .params = &SSLCipherAES_128_CBCParams, + .c.cipher = { + .initialize = CCSymmInit, + .encrypt = CCSymmEncryptDecrypt, + .decrypt = CCSymmEncryptDecrypt + }, + .finish = CCSymmFinish +}; +#endif /* ENABLE_AES */ + +#if ENABLE_AES256 +const SSLSymmetricCipher SSLCipherAES_256_CBC = { + .params = &SSLCipherAES_256_CBCParams, + .c.cipher = { + .initialize = CCSymmInit, + .encrypt = CCSymmEncryptDecrypt, + .decrypt = CCSymmEncryptDecrypt + }, + .finish = CCSymmFinish +}; +#endif /* ENABLE_AES256 */ + +#if ENABLE_AES_GCM +const SSLSymmetricCipher SSLCipherAES_128_GCM = { + .params = &SSLCipherAES_128_GCMParams, + .c.aead = { + .initialize = CCSymmInit, + .setIV = CCSymmAEADSetIV, + .update = CCSymmAddADD, + .encrypt = CCSymmAEADEncrypt, + .decrypt = CCSymmAEADDecrypt, + .done = CCSymmAEADDone + }, + .finish = CCSymmFinish +}; + +const SSLSymmetricCipher SSLCipherAES_256_GCM = { + .params = &SSLCipherAES_256_GCMParams, + .c.aead = { + .initialize = CCSymmInit, + .setIV = CCSymmAEADSetIV, + .update = CCSymmAddADD, + .encrypt = CCSymmAEADEncrypt, + .decrypt = CCSymmAEADDecrypt, + .done = CCSymmAEADDone + }, + .finish = CCSymmFinish +}; +#endif /* ENABLE_AES_GCM */