X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/67c7378dcb8de24c86b7fedff90b4b496f2e474c..5a719ac813caa6f2ceaa192274fad2e1c2cec162:/SecureTransport/symCipher.cpp diff --git a/SecureTransport/symCipher.cpp b/SecureTransport/symCipher.cpp new file mode 100644 index 00000000..b3dd7f4e --- /dev/null +++ b/SecureTransport/symCipher.cpp @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS + * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT + * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the + * specific language governing rights and limitations under the License. + */ + + +/* + File: symCipher.c + + Contains: CDSA-based symmetric cipher module + + Written by: Doug Mitchell + + Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved. + +*/ + +#include "sslContext.h" +#include "cryptType.h" +#include "sslDebug.h" +#include "sslMemory.h" +#include "appleCdsa.h" +#include "symCipher.h" + +#include + +#include + +/* dispose of dynamically allocated resources in a CipherContext */ +static void disposeCipherCtx( + CipherContext *cipherCtx) +{ + assert(cipherCtx != NULL); + if(cipherCtx->symKey != NULL) { + assert(cipherCtx->cspHand != 0); + CSSM_FreeKey(cipherCtx->cspHand, NULL, cipherCtx->symKey, CSSM_FALSE); + sslFree(cipherCtx->symKey); + cipherCtx->symKey = NULL; + } + cipherCtx->cspHand = 0; + if(cipherCtx->ccHand != 0) { + CSSM_DeleteContext(cipherCtx->ccHand); + cipherCtx->ccHand = 0; + } +} + +OSStatus CDSASymmInit( + uint8 *key, + uint8* iv, + CipherContext *cipherCtx, + SSLContext *ctx) +{ + /* + * Cook up a symmetric key and a CCSM_CC_HANDLE. Assumes: + * cipherCtx->symCipher.keyAlg + * ctx->cspHand + * key (raw key bytes) + * On successful exit: + * Resulting CSSM_KEY_PTR --> cipherCtx->symKey + * Resulting CSSM_CC_HANDLE --> cipherCtx->ccHand + * (Currently) a copy of ctx->cspHand --> cipherCtx->cspHand + * + * FIXME - for now we assume that ctx->cspHand is capable of + * using the specified algorithm, keysize, and mode. This + * may need revisiting. + */ + + OSStatus serr = errSSLInternal; + CSSM_RETURN crtn; + const SSLSymmetricCipher *symCipher; + CSSM_DATA ivData; + CSSM_DATA_PTR ivDataPtr = NULL; + CSSM_KEY_PTR symKey = NULL; + CSSM_CC_HANDLE ccHand = 0; + char *op; + + assert(cipherCtx != NULL); + assert(cipherCtx->symCipher != NULL); + assert(ctx != NULL); + if(ctx->cspHand == 0) { + sslErrorLog("CDSASymmInit: NULL cspHand!\n"); + return errSSLInternal; + } + + /* clean up cipherCtx */ + disposeCipherCtx(cipherCtx); + + /* cook up a raw key */ + symKey = (CSSM_KEY_PTR)sslMalloc(sizeof(CSSM_KEY)); + if(symKey == NULL) { + return memFullErr; + } + serr = sslSetUpSymmKey(symKey, cipherCtx->symCipher->keyAlg, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, CSSM_TRUE, + key, cipherCtx->symCipher->keySize); + if(serr) { + sslFree(symKey); + return serr; + } + + cipherCtx->symKey = symKey; + + /* now the crypt handle */ + symCipher = cipherCtx->symCipher; + if(symCipher->ivSize != 0) { + ivData.Data = iv; + ivData.Length = symCipher->ivSize; + ivDataPtr = &ivData; + } + crtn = CSSM_CSP_CreateSymmetricContext(ctx->cspHand, + symCipher->encrAlg, + symCipher->encrMode, + NULL, + symKey, + ivDataPtr, + symCipher->encrPad, + 0, // Params + &ccHand); + if(crtn) { + stPrintCdsaError("CSSM_CSP_CreateSymmetricContext", crtn); + serr = errSSLCrypto; + goto errOut; + } + cipherCtx->ccHand = ccHand; + + /* after this, each en/decrypt is merely an update */ + if(cipherCtx->encrypting) { + crtn = CSSM_EncryptDataInit(ccHand); + op = "CSSM_EncryptDataInit"; + } + else { + crtn = CSSM_DecryptDataInit(ccHand); + op = "CSSM_DecryptDataInit"; + } + if(crtn) { + stPrintCdsaError("CSSM_CSP_EncryptDataInit", crtn); + serr = errSSLCrypto; + goto errOut; + } + + /* success */ + cipherCtx->cspHand = ctx->cspHand; + serr = noErr; + +errOut: + if(serr) { + /* dispose of the stuff we created */ + disposeCipherCtx(cipherCtx); + } + return serr; +} + +#define REDECRYPT_DATA 0 + +#define LOG_SYMM_DATA 0 +#if LOG_SYMM_DATA +static void logSymmData( + char *field, + SSLBuffer *data, + int maxLen) +{ + int i; + + printf("%s: ", field); + for(i=0; ilength; i++) { + if(i == maxLen) { + break; + } + printf("%02X", data->data[i]); + if((i % 4) == 3) { + printf(" "); + } + } + printf("\n"); +} +#else /* LOG_SYMM_DATA */ +#define logSymmData(f, d, l) +#endif /* LOG_SYMM_DATA */ + +#define IS_ALIGNED(count, blockSize) ((count % blockSize) == 0) + +OSStatus CDSASymmEncrypt( + SSLBuffer src, + SSLBuffer dest, + CipherContext *cipherCtx, + SSLContext *ctx) +{ + CSSM_RETURN crtn; + CSSM_DATA ptextData; + CSSM_DATA ctextData; + uint32 bytesEncrypted; + OSStatus serr = errSSLInternal; + uint32 origLen = dest.length; + + /* + * Valid on entry: + * cipherCtx->ccHand + * cipherCtx->cspHand + */ + assert(ctx != NULL); + assert(cipherCtx != NULL); + logSymmData("Symm encrypt ptext", &src, 48); + + /* this requirement allows us to avoid a malloc and copy */ + assert(dest.length >= src.length); + + #if SSL_DEBUG + { + unsigned blockSize = cipherCtx->symCipher->blockSize; + if(blockSize) { + if(!IS_ALIGNED(src.length, blockSize)) { + sslErrorLog("CDSASymmEncrypt: unaligned ptext (len %ld bs %d)\n", + src.length, blockSize); + return errSSLInternal; + } + if(!IS_ALIGNED(dest.length, blockSize)) { + sslErrorLog("CDSASymmEncrypt: unaligned ctext (len %ld bs %d)\n", + dest.length, blockSize); + return errSSLInternal; + } + } + } + #endif + + if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) { + sslErrorLog("CDSASymmEncrypt: null args\n"); + return errSSLInternal; + } + SSLBUF_TO_CSSM(&src, &ptextData); + SSLBUF_TO_CSSM(&dest, &ctextData); + crtn = CSSM_EncryptDataUpdate(cipherCtx->ccHand, + &ptextData, + 1, + &ctextData, + 1, + &bytesEncrypted); + if(crtn) { + stPrintCdsaError("CSSM_EncryptDataUpdate", crtn); + serr = errSSLCrypto; + goto errOut; + } + + if(bytesEncrypted > origLen) { + /* should never happen, callers always give us block-aligned + * plaintext and CSP padding is disabled. */ + sslErrorLog("Symmetric encrypt overflow: bytesEncrypted %ld destLen %ld\n", + bytesEncrypted, dest.length); + serr = errSSLCrypto; + goto errOut; + } + dest.length = bytesEncrypted; + logSymmData("Symm encrypt ctext", &dest, 48); + serr = noErr; + +errOut: + return serr; +} + +OSStatus CDSASymmDecrypt( + SSLBuffer src, + SSLBuffer dest, + CipherContext *cipherCtx, + SSLContext *ctx) +{ + CSSM_RETURN crtn; + CSSM_DATA ptextData = {0, NULL}; + CSSM_DATA ctextData; + uint32 bytesDecrypted; + OSStatus serr = errSSLInternal; + uint32 origLen = dest.length; + + /* + * Valid on entry: + * cipherCtx->cspHand + * cipherCtx->ccHand + */ + assert(ctx != NULL); + assert(cipherCtx != NULL); + if((cipherCtx->ccHand == 0) || (cipherCtx->cspHand == 0)) { + sslErrorLog("CDSASymmDecrypt: null args\n"); + return errSSLInternal; + } + /* this requirement allows us to avoid a malloc and copy */ + assert(dest.length >= src.length); + + #if SSL_DEBUG + { + unsigned blockSize = cipherCtx->symCipher->blockSize; + if(blockSize) { + if(!IS_ALIGNED(src.length, blockSize)) { + sslErrorLog("CDSASymmDecrypt: unaligned ctext (len %ld bs %d)\n", + src.length, blockSize); + return errSSLInternal; + } + if(!IS_ALIGNED(dest.length, blockSize)) { + sslErrorLog("CDSASymmDecrypt: unaligned ptext (len %ld bs %d)\n", + dest.length, blockSize); + return errSSLInternal; + } + } + } + #endif + + SSLBUF_TO_CSSM(&src, &ctextData); + SSLBUF_TO_CSSM(&dest, &ptextData); + crtn = CSSM_DecryptDataUpdate(cipherCtx->ccHand, + &ctextData, + 1, + &ptextData, + 1, + &bytesDecrypted); + if(crtn) { + stPrintCdsaError("CSSM_DecryptDataUpdate", crtn); + serr = errSSLCrypto; + goto errOut; + } + + if(bytesDecrypted > origLen) { + /* FIXME - can this happen? Should we remalloc? */ + sslErrorLog("Symmetric decrypt overflow: bytesDecrypted %ld destLen %ld\n", + bytesDecrypted, dest.length); + serr = errSSLCrypto; + goto errOut; + } + dest.length = bytesDecrypted; + serr = noErr; + logSymmData("Symm decrypt ptext(1)", &dest, 48); +errOut: + return serr; +} + +OSStatus CDSASymmFinish( + CipherContext *cipherCtx, + SSLContext *ctx) +{ + /* dispose of cipherCtx->{symKey,cspHand,ccHand} */ + disposeCipherCtx(cipherCtx); + return noErr; +} +