X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/67c7378dcb8de24c86b7fedff90b4b496f2e474c..5a719ac813caa6f2ceaa192274fad2e1c2cec162:/SecureTransport/sslDigests.cpp diff --git a/SecureTransport/sslDigests.cpp b/SecureTransport/sslDigests.cpp new file mode 100644 index 00000000..5748ad6d --- /dev/null +++ b/SecureTransport/sslDigests.cpp @@ -0,0 +1,328 @@ +/* + * 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: sslDigests.cpp + + Contains: interface between SSL and SHA, MD5 digest implementations + + Written by: Doug Mitchell + + Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved. + +*/ + +#include "sslContext.h" +#include "cryptType.h" +#include "sslMemory.h" +#include "sslDigests.h" +#include "sslDebug.h" +#include "appleCdsa.h" +#include +#include + +#define DIGEST_PRINT 0 +#if DIGEST_PRINT +#define dgprintf(s) printf s +#else +#define dgprintf(s) +#endif + +/* + * Common digest context. The SSLBuffer.data pointer in a "digest state" argument + * casts to one of these. + */ +typedef struct { + CSSM_CC_HANDLE hashHand; +} cdsaHashContext; + +const UInt8 SSLMACPad1[MAX_MAC_PADDING] = +{ + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36 +}; + +const UInt8 SSLMACPad2[MAX_MAC_PADDING] = +{ + 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C, + 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C, + 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C, + 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C, + 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C, + 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C +}; + +/* + * Public general hash functions + */ + +/* + * A convenience wrapper for HashReference.clone, which has the added benefit of + * allocating the state buffer for the caller. + */ +OSStatus +CloneHashState( + const HashReference &ref, + const SSLBuffer &state, + SSLBuffer &newState, + SSLContext *ctx) +{ + OSStatus err; + if ((err = SSLAllocBuffer(newState, ref.contextSize, ctx)) != 0) + return err; + return ref.clone(state, newState); +} + +/* + * Wrapper for HashReference.init. + */ +OSStatus +ReadyHash(const HashReference &ref, SSLBuffer &state, SSLContext *ctx) +{ + OSStatus err; + if ((err = SSLAllocBuffer(state, ref.contextSize, ctx)) != 0) + return err; + return ref.init(state, ctx); +} + +/* + * Wrapper for HashReference.clone. Tolerates NULL digestCtx and frees it if it's + * there. + */ +OSStatus CloseHash(const HashReference &ref, SSLBuffer &state, SSLContext *ctx) +{ + OSStatus serr; + + if(state.data == NULL) { + return noErr; + } + serr = ref.close(state, ctx); + if(serr) { + return serr; + } + return SSLFreeBuffer(state, ctx); +} + +static OSStatus HashNullInit(SSLBuffer &digestCtx, SSLContext *sslCtx); +static OSStatus HashNullUpdate(SSLBuffer &digestCtx, const SSLBuffer &data); +static OSStatus HashNullFinal(SSLBuffer &digestCtx, SSLBuffer &digest); +static OSStatus HashNullClose(SSLBuffer &digestCtx, SSLContext *sslCtx); +static OSStatus HashNullClone(const SSLBuffer &src, SSLBuffer &dst); + +static OSStatus HashMD5Init(SSLBuffer &digestCtx, SSLContext *sslCtx); +static OSStatus HashSHA1Init(SSLBuffer &digestCtx, SSLContext *sslCtx); +static OSStatus cdsaHashInit(SSLBuffer &digestCtx, SSLContext *sslCtx, + CSSM_ALGORITHMS digestAlg); +static OSStatus cdsaHashUpdate(SSLBuffer &digestCtx, const SSLBuffer &data); +static OSStatus cdsaHashFinal(SSLBuffer &digestCtx, SSLBuffer &digest); +static OSStatus cdsaHashClose(SSLBuffer &digestCtx, SSLContext *sslCtx); +static OSStatus cdsaHashClone(const SSLBuffer &src, SSLBuffer &dest); + +/* + * These are the handles by which the bulk of digesting work + * is done. + */ +const HashReference SSLHashNull = + { + 0, + 0, + 0, + HashNullInit, + HashNullUpdate, + HashNullFinal, + HashNullClose, + HashNullClone + }; + +const HashReference SSLHashMD5 = + { + sizeof(cdsaHashContext), + 16, + 48, + HashMD5Init, + cdsaHashUpdate, + cdsaHashFinal, + cdsaHashClose, + cdsaHashClone + }; + +const HashReference SSLHashSHA1 = + { + sizeof(cdsaHashContext), + 20, + 40, + HashSHA1Init, + cdsaHashUpdate, + cdsaHashFinal, + cdsaHashClose, + cdsaHashClone + }; + +/*** NULL ***/ +static OSStatus HashNullInit(SSLBuffer &digestCtx, SSLContext *sslCtx) { + return noErr; +} + +static OSStatus HashNullUpdate(SSLBuffer &digestCtx, const SSLBuffer &data) { + return noErr; +} + +static OSStatus HashNullFinal(SSLBuffer &digestCtx, SSLBuffer &digest) { + return noErr; +} +static OSStatus HashNullClose(SSLBuffer &digestCtx, SSLContext *sslCtx) { + return noErr; +} +static OSStatus HashNullClone(const SSLBuffer &src, SSLBuffer &dest) { + return noErr; +} + +static OSStatus HashMD5Init(SSLBuffer &digestCtx, SSLContext *sslCtx) +{ + assert(digestCtx.length >= sizeof(cdsaHashContext)); + return cdsaHashInit(digestCtx, sslCtx, CSSM_ALGID_MD5); +} + +static OSStatus HashSHA1Init(SSLBuffer &digestCtx, SSLContext *sslCtx) +{ + assert(digestCtx.length >= sizeof(cdsaHashContext)); + return cdsaHashInit(digestCtx, sslCtx, CSSM_ALGID_SHA1); +} + +/* common digest functions via CDSA */ +static OSStatus cdsaHashInit(SSLBuffer &digestCtx, + SSLContext *sslCtx, + CSSM_ALGORITHMS digestAlg) +{ + OSStatus serr; + cdsaHashContext *cdsaCtx; + CSSM_CC_HANDLE hashHand = 0; + CSSM_RETURN crtn; + + assert(digestCtx.length >= sizeof(cdsaHashContext)); + serr = attachToCsp(sslCtx); // should be a nop + if(serr) { + return serr; + } + cdsaCtx = (cdsaHashContext *)digestCtx.data; + cdsaCtx->hashHand = 0; + dgprintf(("###cdsaHashInit cdsaCtx %p\n", cdsaCtx)); + + /* cook up a digest context, initialize it */ + crtn = CSSM_CSP_CreateDigestContext(sslCtx->cspHand, + digestAlg, + &hashHand); + if(crtn) { + sslErrorLog("CSSM_CSP_CreateDigestContext failure\n"); + return errSSLCrypto; + } + crtn = CSSM_DigestDataInit(hashHand); + if(crtn) { + CSSM_DeleteContext(hashHand); + sslErrorLog("CSSM_DigestDataInit failure\n"); + return errSSLCrypto; + } + cdsaCtx->hashHand = hashHand; + return noErr; +} + +static OSStatus cdsaHashUpdate(SSLBuffer &digestCtx, const SSLBuffer &data) +{ + cdsaHashContext *cdsaCtx; + CSSM_RETURN crtn; + CSSM_DATA cdata; + + assert(digestCtx.length >= sizeof(cdsaHashContext)); + cdsaCtx = (cdsaHashContext *)digestCtx.data; + //dgprintf(("###cdsaHashUpdate cdsaCtx %p\n", cdsaCtx)); + + SSLBUF_TO_CSSM(&data, &cdata); + crtn = CSSM_DigestDataUpdate(cdsaCtx->hashHand, &cdata, 1); + if(crtn) { + sslErrorLog("CSSM_DigestDataUpdate failure\n"); + return errSSLCrypto; + } + else { + return noErr; + } +} + +static OSStatus cdsaHashFinal(SSLBuffer &digestCtx, SSLBuffer &digest) +{ + cdsaHashContext *cdsaCtx; + CSSM_RETURN crtn; + CSSM_DATA cdata; + OSStatus srtn = noErr; + + assert(digestCtx.length >= sizeof(cdsaHashContext)); + cdsaCtx = (cdsaHashContext *)digestCtx.data; + dgprintf(("###cdsaHashFinal cdsaCtx %p\n", cdsaCtx)); + SSLBUF_TO_CSSM(&digest, &cdata); + crtn = CSSM_DigestDataFinal(cdsaCtx->hashHand, &cdata); + if(crtn) { + sslErrorLog("CSSM_DigestDataFinal failure\n"); + srtn = errSSLCrypto; + } + else { + digest.length = cdata.Length; + } + CSSM_DeleteContext(cdsaCtx->hashHand); + cdsaCtx->hashHand = 0; + return srtn; +} + +static OSStatus cdsaHashClose(SSLBuffer &digestCtx, SSLContext *sslCtx) +{ + cdsaHashContext *cdsaCtx; + + assert(digestCtx.length >= sizeof(cdsaHashContext)); + cdsaCtx = (cdsaHashContext *)digestCtx.data; + dgprintf(("###cdsaHashClose cdsaCtx %p\n", cdsaCtx)); + if(cdsaCtx->hashHand != 0) { + CSSM_DeleteContext(cdsaCtx->hashHand); + cdsaCtx->hashHand = 0; + } + return noErr; +} + +static OSStatus cdsaHashClone(const SSLBuffer &src, SSLBuffer &dst) +{ + cdsaHashContext *srcCtx; + cdsaHashContext *dstCtx; + CSSM_RETURN crtn; + + assert(src.length >= sizeof(cdsaHashContext)); + assert(dst.length >= sizeof(cdsaHashContext)); + srcCtx = (cdsaHashContext *)src.data; + dstCtx = (cdsaHashContext *)dst.data; + dgprintf(("###cdsaHashClone srcCtx %p dstCtx %p\n", srcCtx, dstCtx)); + + crtn = CSSM_DigestDataClone(srcCtx->hashHand, &dstCtx->hashHand); + if(crtn) { + sslErrorLog("CSSM_DigestDataClone failure\n"); + return errSSLCrypto; + } + else { + return noErr; + } +} +