]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_transform/lib/EncryptTransform.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / Security / libsecurity_transform / lib / EncryptTransform.cpp
diff --git a/Security/libsecurity_transform/lib/EncryptTransform.cpp b/Security/libsecurity_transform/lib/EncryptTransform.cpp
deleted file mode 100644 (file)
index c661751..0000000
+++ /dev/null
@@ -1,1098 +0,0 @@
-/*
- * Copyright (c) 2010-2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The 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.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-
-#include "EncryptTransform.h"
-#include "SecEncryptTransform.h"
-#include "EncryptTransformUtilities.h"
-#include "Utilities.h"
-#include "SecDigestTransform.h"
-#include "Digest.h"
-#include <Security/SecRandom.h>
-#include "SecMaskGenerationFunctionTransform.h"
-
-static CFStringRef kEncryptTransformType = CFSTR("Encrypt Transform");
-static CFStringRef kDecryptTransformType = CFSTR("Decrypt Transform");
-//static const char *kEncryptTransformType_cstr = "Encrypt Transform";
-//static const char *kDecryptTransformType_cstr = "Decrypt Transform";
-static uint8 iv[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
-static const CSSM_DATA gKeySalt = {16, iv}; // default Salt for key
-
-dispatch_once_t EncryptDecryptBase::serializerSetUp;
-dispatch_queue_t EncryptDecryptBase::serializerTransformStartingExecution;
-
-/* --------------------------------------------------------------------------
- Implementation of the EncryptDecryptBase class
- -------------------------------------------------------------------------- */
-
-/* --------------------------------------------------------------------------
- method:               EncryptDecryptBase (Constructor)
- description:  Initialize a new instance of a EncryptDecryptBase class
- -------------------------------------------------------------------------- */
-EncryptDecryptBase::EncryptDecryptBase(CFStringRef type) :
-Transform(type),
-m_cssm_padding(CSSM_PADDING_NONE),
-m_mode(CSSM_ALGMODE_CBCPadIV8),
-m_cssm_key(NULL),
-m_handle((CSSM_CC_HANDLE)0),
-m_forEncryption(FALSE),
-m_processedData(NULL),
-m_accumulator(NULL)
-{
-       m_forEncryption = CFEqual(type, kEncryptTransformType);
-    inputAH = transforms_assume(this->getAH(kSecTransformInputAttributeName, false, false));
-}
-
-/* --------------------------------------------------------------------------
- method:               ~EncryptDecryptBase (pre-Destructor)
- description:  Clean m_handle, let Transform::Finalize() do the rest
- -------------------------------------------------------------------------- */
-void EncryptDecryptBase::Finalize()
-{
-       if (m_handle != (CSSM_CC_HANDLE)0)
-       {
-               CSSM_CC_HANDLE tmp_handle = m_handle;
-               // Leaving this to the destructor causes occasional crashes.
-               // This may be a CDSA thread afinity bug, or it might be more
-               // local.
-               dispatch_async(mDispatchQueue, ^{
-                       CSSM_DeleteContext(tmp_handle);
-               });
-               m_handle = ((CSSM_CC_HANDLE)0);
-       }
-
-       Transform::Finalize();
-}
-
-
-/* --------------------------------------------------------------------------
- method:               ~EncryptDecryptBase (Destructor)
- description:  Clean up the memory of an EncryptDecryptBase object
- -------------------------------------------------------------------------- */
-EncryptDecryptBase::~EncryptDecryptBase()
-{
-       if (NULL != m_processedData)
-       {
-               CFRelease(m_processedData);
-               m_processedData = NULL;
-       }
-       if (NULL != m_accumulator)
-       {
-               CFRelease(m_accumulator);
-               m_accumulator = NULL;
-       }
-}
-
-/* --------------------------------------------------------------------------
- method:               InitializeObject(SecKeyRef key, CFErrorRef *error)
- description:  Initialize an instance of the base encrypt/decrypt transform
- -------------------------------------------------------------------------- */
-bool EncryptDecryptBase::InitializeObject(SecKeyRef key, CFErrorRef *error)
-{
-       SetAttributeNoCallback(kSecEncryptKey, key);
-       if (error)
-       {
-               *error = NULL;
-       }
-
-       return true;
-}
-
-/* --------------------------------------------------------------------------
- method:               SerializedTransformStartingExecution()
- description:  Get this transform ready to run, should only be called on
-                               the serializerTransformStartingExecution queue
- -------------------------------------------------------------------------- */
-CFErrorRef EncryptDecryptBase::SerializedTransformStartingExecution()
-{
-       CFErrorRef result = NULL;       // Assume all is well
-       SecKeyRef key = (SecKeyRef) GetAttribute(kSecEncryptKey);
-       if (NULL == key)
-       {
-               return CreateSecTransformErrorRef(kSecTransformErrorAttributeNotFound, "The attribute %@ was not found.", kSecEncryptKey);
-       }
-
-       OSStatus err = errSecSuccess;
-       err = SecKeyGetCSSMKey(key, (const CSSM_KEY **)&m_cssm_key);
-       if (errSecSuccess != err)
-       {
-               CFStringRef result = SecCopyErrorMessageString(err, NULL);
-               CFErrorRef retValue = CreateSecTransformErrorRef(err, "CDSA error (%@).", result);
-               CFRelease(result);
-               return retValue;
-       }
-
-       CSSM_CSP_HANDLE csp;
-       err = SecKeyGetCSPHandle(key, &csp);
-       if (errSecSuccess != err)
-       {
-               CFStringRef result = SecCopyErrorMessageString(err, NULL);
-               CFErrorRef retValue = CreateSecTransformErrorRef(err, "CDSA error (%@).", result);
-               CFRelease(result);
-               return retValue;
-       }
-
-       CSSM_ALGORITHMS keyAlg = m_cssm_key->KeyHeader.AlgorithmId;
-
-       m_cssm_padding = CSSM_PADDING_NONE;
-       CFStringRef paddingStr = (CFStringRef) GetAttribute(kSecPaddingKey);
-       CFStringRef modeStr = (CFStringRef) GetAttribute (kSecEncryptionMode);
-       CFDataRef ivData = (CFDataRef) GetAttribute(kSecIVKey);
-
-       Boolean hasPadding = (paddingStr != NULL);
-       Boolean hasMode = (modeStr != NULL);
-       Boolean hasIVData = (ivData != NULL);
-       Boolean isSymmetrical = (m_cssm_key->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY);
-
-
-    if (!hasPadding)
-       {
-               if (CSSM_ALGID_RSA == keyAlg || CSSM_ALGID_ECDSA == keyAlg)
-               {
-                       m_cssm_padding = CSSM_PADDING_PKCS1;
-               }
-               else
-               {
-                       m_cssm_padding = CSSM_PADDING_PKCS7;
-               }
-               m_oaep_padding = false;
-       }
-       else
-       {
-               if (CFStringCompare(kSecPaddingOAEPKey, paddingStr, kCFCompareAnchored)) {
-                       m_oaep_padding = false;
-                       m_cssm_padding = ConvertPaddingStringToEnum(paddingStr);
-               } else {
-                       m_cssm_padding = CSSM_PADDING_NONE;
-                       m_oaep_padding = true;
-                       m_accumulator = CFDataCreateMutable(NULL, 0);
-                       if (!m_accumulator) {
-                               return GetNoMemoryErrorAndRetain();
-                       }
-               }
-       }
-
-       if (!hasMode)
-       {
-               m_mode = (CSSM_PADDING_NONE == m_cssm_padding) ? CSSM_ALGMODE_CBC_IV8 : CSSM_ALGMODE_CBCPadIV8;
-       }
-       else
-       {
-               m_mode = ConvertEncryptModeStringToEnum(modeStr, (CSSM_PADDING_NONE != m_cssm_padding));
-       }
-
-
-       CSSM_RETURN crtn = CSSM_OK;
-       CSSM_ACCESS_CREDENTIALS creds;
-       CSSM_ACCESS_CREDENTIALS* credPtr = NULL;
-       memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
-
-       err = SecKeyGetCredentials(key,
-                                  (m_forEncryption) ? CSSM_ACL_AUTHORIZATION_ENCRYPT : CSSM_ACL_AUTHORIZATION_DECRYPT,
-                                  kSecCredentialTypeDefault,
-                                  (const CSSM_ACCESS_CREDENTIALS **)&credPtr);
-       if (errSecSuccess != err)
-       {
-               memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
-               credPtr = &creds;
-       }
-
-       if (isSymmetrical)
-       {
-               CSSM_DATA initVector;
-               if (hasIVData)
-               {
-                       initVector.Length = CFDataGetLength(ivData);
-                       initVector.Data = const_cast<uint8_t*>(CFDataGetBytePtr(ivData));
-               }
-               else
-               {
-                       initVector.Length = gKeySalt.Length;
-                       initVector.Data = (uint8 *)malloc(initVector.Length);
-                       initVector.Data = gKeySalt.Data;
-               }
-
-               crtn = CSSM_CSP_CreateSymmetricContext(csp, keyAlg, m_mode, credPtr, m_cssm_key,
-                                                      &initVector, m_cssm_padding, NULL, &m_handle);
-
-               // Need better error here
-               if (crtn != CSSM_OK)
-               {
-                       CFStringRef result = SecCopyErrorMessageString(crtn, NULL);
-                       CFErrorRef retValue = CreateSecTransformErrorRef(kSecTransformErrorNotInitializedCorrectly, "CDSA error (%@).", result);
-                       CFRelease(result);
-                       return retValue;
-               }
-       }
-       else
-       {
-               crtn = CSSM_CSP_CreateAsymmetricContext(csp, keyAlg, credPtr, m_cssm_key, m_cssm_padding, &m_handle);
-
-               // Need better error here
-               if (crtn != CSSM_OK)
-               {
-                       CFStringRef result = SecCopyErrorMessageString(crtn, NULL);
-                       CFErrorRef retValue = CreateSecTransformErrorRef(kSecTransformErrorNotInitializedCorrectly, "CDSA error (%@).", result);
-                       CFRelease(result);
-                       return retValue;
-               }
-       }
-
-       // Encryption
-       crtn = (m_forEncryption) ? CSSM_EncryptDataInit(m_handle) : CSSM_DecryptDataInit(m_handle);
-       // Need better error here
-       if (crtn != CSSM_OK)
-       {
-                       CFStringRef result = SecCopyErrorMessageString(crtn, NULL);
-                       CFErrorRef retValue = CreateSecTransformErrorRef(kSecTransformErrorNotInitializedCorrectly, "CDSA encrypt/decrypt init error (%@).", result);
-                       CFRelease(result);
-                       return retValue;
-       }
-
-
-       return result;
-}
-
-/* --------------------------------------------------------------------------
- method:               TransformStartingExecution()
- description:  Get this transform ready to run.
- NOTE:                 the encrypt/decrypt setup is not safe to call for a single
-                               key from multiple threads at once, TransformStartingExecution is
-                               responsable making sure this doesn't happen,
-                               SerializedTransformStartingExecution() does the real set up work.
- -------------------------------------------------------------------------- */
-CFErrorRef EncryptDecryptBase::TransformStartingExecution()
-{
-
-       dispatch_once(&serializerSetUp, ^{
-               serializerTransformStartingExecution = dispatch_queue_create("com.apple.security.EncryptDecrypt.key-setup", NULL);
-       });
-
-       __block CFErrorRef result = NULL;       // Assume all is well
-
-       dispatch_sync(serializerTransformStartingExecution, ^{
-               result = SerializedTransformStartingExecution();
-       });
-       return result;
-}
-
-/* --------------------------------------------------------------------------
- method:               TransformCanExecute
- description:  Do we have a key?
- -------------------------------------------------------------------------- */
-Boolean EncryptDecryptBase::TransformCanExecute()
-{
-       // make sure we have a key -- there may be some circumstance when one isn't available
-       // and besides, it helps test this logic
-       SecKeyRef key = (SecKeyRef) GetAttribute(kSecEncryptKey);
-       return key != NULL;
-}
-
-void EncryptDecryptBase::SendCSSMError(CSSM_RETURN retCode)
-{
-       // make a CFErrorRef for the error message
-       CFStringRef errorString = SecCopyErrorMessageString(retCode, NULL);
-       CFErrorRef errorRef = CreateGenericErrorRef(kCFErrorDomainOSStatus, retCode, "%@", errorString);
-       CFRelease(errorString);
-
-       SendAttribute(kSecTransformOutputAttributeName, errorRef);
-       CFRelease(errorRef);
-}
-
-#warning "This declaration should be in some header"
-void xor_bytes(UInt8 *dst, const UInt8 *src1, const UInt8 *src2, CFIndex length);
-void xor_bytes(UInt8 *dst, const UInt8 *src1, const UInt8 *src2, CFIndex length)
-{
-       // NOTE: this can be made faster, but see if we already have a faster version somewhere first.
-
-       // _mm_xor_ps would be nice here
-       // failing that, getting to an aligned boundry and switching to uint64_t
-       // would be good.
-
-       while (length--) {
-               *dst++ = *src1++ ^ *src2++;
-       }
-}
-
-extern "C" {
-       extern CFDataRef oaep_unpadding_via_c(CFDataRef encodedMessage);
-}
-
-CFDataRef EncryptDecryptBase::remove_oaep_padding(CFDataRef encodedMessage)
-{
-#if 1
-       return oaep_unpadding_via_c(encodedMessage);
-#else
-    CFStringRef hashAlgo = NULL;
-    CFDataRef message = NULL, maskedSeed = NULL, maskedDB = NULL, seedMask = NULL, seed = NULL, dbMask = NULL;
-    CFDataRef pHash = NULL, pHashPrime = NULL;
-    CFDataRef EncodingParameters = NULL;
-    CFErrorRef error = NULL;
-    UInt8 *raw_seed = NULL, *raw_DB = NULL, *addr01 = NULL;
-    SecTransformRef mgf_maskedDB = NULL, mgf_dbMask = NULL, hash = NULL;
-    int hLen = -1;
-       // RSA's OAEP documentation assumes the crypto layer will remove the leading (partial) byte,
-       // but CDSA leaves that responsability to us (we did ask it for "no padding" after all).
-       // (use extraPaddingLength = 0 when using a layer that does strip that byte)
-    const int extraPaddingLength = 1;
-
-       // The numbered steps below correspond to RSA Laboratories' RSAES-OAEP Encryption Scheme
-       // document's numbered steps.
-
-    // NOTE: we omit step 1: "If the length of P is greater than the input limitation for the hash
-    // function (2^61 − 1 octets for SHA-1) then output ‘‘decoding error’’ and stop."; we don't have
-    // ready access to the input limits of the hash functions, and in the real world we won't be
-    // seeing messages that long anyway.
-
-    // (2) If emLen < 2hLen + 1, output ‘‘decoding error’’ and stop.
-    hashAlgo = (CFStringRef)this->GetAttribute(kSecOAEPMGF1DigestAlgorithmAttributeName);
-       if (hashAlgo == NULL) {
-               hashAlgo = kSecDigestSHA1;
-       }
-    hLen = Digest::LengthForType(hashAlgo);
-    if (CFDataGetLength(encodedMessage) < 2*hLen + 1) {
-        goto out;
-    }
-
-    // (3) Let maskedSeed be the first hLen octets of EM and let maskedDB be the remaining emLen−hLen
-    // octets.
-    maskedSeed = CFDataCreateWithBytesNoCopy(NULL, CFDataGetBytePtr(encodedMessage) +extraPaddingLength, hLen, kCFAllocatorNull);
-    maskedDB = CFDataCreateWithBytesNoCopy(NULL, CFDataGetBytePtr(encodedMessage) + hLen +extraPaddingLength, CFDataGetLength(encodedMessage) - hLen -extraPaddingLength, kCFAllocatorNull);
-
-    // (4) Let seedMask = MGF(maskedDB, hLen).
-    mgf_maskedDB = SecCreateMaskGenerationFunctionTransform(hashAlgo, hLen, &error);
-    if (!mgf_maskedDB) {
-        goto out;
-    }
-    if (!SecTransformSetAttribute(mgf_maskedDB, kSecTransformInputAttributeName, maskedDB, &error)) {
-        goto out;
-    }
-    seedMask = (CFDataRef)SecTransformExecute(mgf_maskedDB, &error);
-    if (!seedMask) {
-        goto out;
-    }
-       (void)transforms_assume(hLen == CFDataGetLength(seedMask));
-
-    // (5) Let seed = maskedSeed ⊕ seedMask.
-    raw_seed = (UInt8*)malloc(hLen);
-    xor_bytes(raw_seed, CFDataGetBytePtr(maskedSeed), CFDataGetBytePtr(seedMask), hLen);
-    seed = CFDataCreateWithBytesNoCopy(NULL, raw_seed, hLen, kCFAllocatorNull);
-    if (!seed) {
-               free(raw_seed);
-               error = GetNoMemoryErrorAndRetain();
-               goto out;
-       }
-    // (6) Let dbMask = MGF (seed, emLen − hLen).
-    mgf_dbMask = SecCreateMaskGenerationFunctionTransform(hashAlgo, CFDataGetLength(encodedMessage) - hLen, &error);
-    if (!mgf_dbMask) {
-        goto out;
-    }
-    if (!SecTransformSetAttribute(mgf_dbMask, kSecTransformInputAttributeName, seed, &error)) {
-        goto out;
-    }
-    dbMask = (CFDataRef)SecTransformExecute(mgf_dbMask, &error);
-    if (!dbMask) {
-        goto out;
-    }
-
-    // (7) Let DB = maskedDB ⊕ dbMask.
-    raw_DB = (UInt8*)malloc(CFDataGetLength(dbMask));
-    xor_bytes(raw_DB, CFDataGetBytePtr(maskedDB), CFDataGetBytePtr(dbMask), CFDataGetLength(dbMask));
-
-    // (8) Let pHash = Hash(P), an octet string of length hLen.
-    hash = SecDigestTransformCreate(hashAlgo, 0, &error);
-       if (!hash) {
-               goto out;
-       }
-    EncodingParameters = (CFDataRef)this->GetAttribute(kSecOAEPEncodingParametersAttributeName);
-       if (EncodingParameters) {
-               CFRetain(EncodingParameters);
-       } else {
-               EncodingParameters = CFDataCreate(NULL, (UInt8*)"", 0);
-               if (!EncodingParameters) {
-                       goto out;
-               }
-       }
-       if (!SecTransformSetAttribute(hash, kSecTransformInputAttributeName, EncodingParameters, &error)) {
-               goto out;
-       }
-
-       pHash = (CFDataRef)transforms_assume(SecTransformExecute(hash, &error));
-       if (!pHash) {
-               goto out;
-       }
-       (void)transforms_assume(hLen == CFDataGetLength(pHash));
-
-
-    // (9) Separate DB into an octet string pHash’ consisting of the first hLen octets of DB, a
-    // (possibly empty) octet string PS consisting of consecutive zero octets following pHash’,
-    // and a message M as If there is no 01 octet to separate PS from M , output ‘‘decoding error’’ and stop.
-    pHashPrime = CFDataCreateWithBytesNoCopy(NULL, raw_DB, hLen, kCFAllocatorNull);
-    if (CFEqual(pHash, pHashPrime)) {
-        addr01 = (UInt8*)memchr(raw_DB + hLen, 0x01, CFDataGetLength(dbMask) - hLen);
-        if (!addr01) {
-            goto out;
-        }
-        message = CFDataCreate(NULL, addr01 + 1, (CFDataGetLength(dbMask) - ((addr01 - raw_DB) + 1)) -extraPaddingLength);
-    } else {
-        // (10) If pHash’ does not equal pHash, output ‘‘decoding error’’ and stop.
-        goto out;
-    }
-
-out:
-    if (!message) {
-        if (!error) {
-            error = CreateSecTransformErrorRef(kSecTransformErrorInvalidInput, "decoding error");
-        }
-        SetAttributeNoCallback(kSecTransformOutputAttributeName, error);
-    }
-
-       // Release eveything except:
-       //      hashAlgo (obtained via get)
-       //      message (return value)
-       CFSafeRelease(maskedSeed);
-       CFSafeRelease(maskedDB);
-       CFSafeRelease(seedMask);
-       CFSafeRelease(seed);
-       CFSafeRelease(dbMask);
-       CFSafeRelease(pHash);
-       CFSafeRelease(pHashPrime);
-       CFSafeRelease(mgf_dbMask);
-       CFSafeRelease(mgf_maskedDB);
-       CFSafeRelease(hash);
-       CFSafeRelease(EncodingParameters);
-       // raw_seed is free'd via CFData, addr01 was never allocated, so raw_DB is our lot
-       free(raw_DB);
-
-    // (11) Output M.
-    return message;
-#endif
-}
-
-extern "C" {
-       extern CFDataRef oaep_padding_via_c(int desired_message_length, CFDataRef dataValue);
-}
-
-CFDataRef EncryptDecryptBase::apply_oaep_padding(CFDataRef dataValue)
-{
-#if 1
-       // MGF1 w/ SHA1 assumed here
-
-       CFErrorRef error = NULL;
-       int hLen = Digest::LengthForType(kSecDigestSHA1);
-       CFNumberRef desired_message_length_cf = (CFNumberRef)this->GetAttribute(kSecOAEPMessageLengthAttributeName);
-       int desired_message_length = 0;
-       CSSM_QUERY_SIZE_DATA RSA_size;
-       CFDataRef EM = NULL;
-
-       if (desired_message_length_cf) {
-               CFNumberGetValue(desired_message_length_cf, kCFNumberIntType, &desired_message_length);
-       } else {
-               // take RSA (or whatever crypto) block size onto account too
-               RSA_size.SizeInputBlock = (uint32)(CFDataGetLength(dataValue) + 2*hLen +1);
-               RSA_size.SizeOutputBlock = 0;
-               OSStatus status = CSSM_QuerySize(m_handle, CSSM_TRUE, 1, &RSA_size);
-               if (status != errSecSuccess) {
-                       CFStringRef errorString = SecCopyErrorMessageString(status, NULL);
-                       error = CreateSecTransformErrorRef(kSecTransformErrorInvalidOperation, "CDSA error (%@).", errorString);
-                       CFRelease(errorString);
-                       SetAttributeNoCallback(kSecTransformOutputAttributeName, error);
-                       (void)transforms_assume_zero(EM);
-                       return EM;
-               }
-               (void)transforms_assume(RSA_size.SizeInputBlock <= RSA_size.SizeOutputBlock);
-               desired_message_length = RSA_size.SizeOutputBlock;
-       }
-       CFDataRef returnData = oaep_padding_via_c(desired_message_length, dataValue);
-       return returnData;
-
-#else
-       CFDataRef seed = NULL, dbMask = NULL, maskedDB = NULL, seedMask = NULL, padHash = NULL, padZeros = NULL;
-    CFDataRef EncodingParameters = NULL;
-       CFMutableDataRef EM = NULL, dataBlob = NULL;
-       CFNumberRef desired_message_length_cf = NULL;
-       CFErrorRef error = NULL;
-       CFStringRef hashAlgo = NULL;
-       UInt8 *raw_padZeros = NULL, *raw_seed = NULL, *raw_maskedSeed = NULL, *raw_maskedDB = NULL;
-       SecTransformRef mgf_dbMask = NULL, mgf_seedMask = NULL, hash = NULL;
-       CFIndex paddingNeeded = -1, padLen = -1;
-       int hLen = -1;
-       CSSM_QUERY_SIZE_DATA RSA_size;
-
-       // NOTE: we omit (1) If the length of P is greater than the input limitation for the hash function
-       // (2^61 − 1 octets for SHA-1) then output ‘‘parameter string too long’’ and stop.
-       // We don't have ready access to the input limit of the hash functions, and in the real world
-       // we won't be seeing a message that long anyway.
-
-       // (2) If mLen > emLen − 2hLen − 1, output ‘‘message too long’’ and stop.
-       hashAlgo = (CFStringRef)this->GetAttribute(kSecOAEPMGF1DigestAlgorithmAttributeName);
-       if (hashAlgo == NULL) {
-               hashAlgo = kSecDigestSHA1;
-       }
-       hLen = Digest::LengthForType(hashAlgo);
-       desired_message_length_cf = (CFNumberRef)this->GetAttribute(kSecOAEPMessageLengthAttributeName);
-       int desired_message_length = 0;
-       if (desired_message_length_cf) {
-               CFNumberGetValue(desired_message_length_cf, kCFNumberIntType, &desired_message_length);
-       } else {
-               // take RSA (or whatever crypto) block size onto account too
-               RSA_size.SizeInputBlock = CFDataGetLength(dataValue) + 2*hLen +1;
-               RSA_size.SizeOutputBlock = 0;
-               OSStatus status = CSSM_QuerySize(m_handle, CSSM_TRUE, 1, &RSA_size);
-               if (status != errSecSuccess) {
-                       CFStringRef errorString = SecCopyErrorMessageString(status, NULL);
-                       error = CreateSecTransformErrorRef(kSecTransformErrorInvalidOperation, "CDSA error (%@).", errorString);
-                       CFRelease(errorString);
-                       goto out;
-               }
-               (void)transforms_assume(RSA_size.SizeInputBlock <= RSA_size.SizeOutputBlock);
-               desired_message_length = RSA_size.SizeOutputBlock -1;
-       }
-       padLen = (desired_message_length - (2*hLen) -1) - CFDataGetLength(dataValue);
-       if (padLen < 0) {
-               error = CreateSecTransformErrorRef(kSecTransformErrorInvalidLength, "Your message is too long for your message length, it needs to be %d bytes shorter, or you need to adjust the kSecOAEPMessageLengthAttributeName attribute", -padLen);
-        goto out;
-       }
-
-       // (3) Generate an octet string PS consisting of emLen − mLen − 2hLen − 1 zero octets. The length of PS may be 0.
-       raw_padZeros = (UInt8*)calloc(padLen, 1);
-       if (!raw_padZeros) {
-               error = GetNoMemoryErrorAndRetain();
-               goto out;
-       }
-       padZeros = CFDataCreateWithBytesNoCopy(NULL, raw_padZeros, padLen, kCFAllocatorMalloc);
-       if (!padZeros) {
-               free(raw_padZeros);
-               error = GetNoMemoryErrorAndRetain();
-               goto out;
-       }
-
-       // (4) Let pHash = Hash(P), an octet string of length hLen.
-       hash = SecDigestTransformCreate(hashAlgo, 0, &error);
-       if (!hash) {
-               goto out;
-       }
-    EncodingParameters = (CFDataRef)this->GetAttribute(kSecOAEPEncodingParametersAttributeName);
-       if (EncodingParameters) {
-               CFRetain(EncodingParameters);
-       } else {
-               EncodingParameters = CFDataCreate(NULL, (UInt8*)"", 0);
-               if (!EncodingParameters) {
-                       error = GetNoMemoryErrorAndRetain();
-                       goto out;
-               }
-       }
-       if (!SecTransformSetAttribute(hash, kSecTransformInputAttributeName, EncodingParameters, &error)) {
-               goto out;
-       }
-
-       padHash = (CFDataRef)transforms_assume(SecTransformExecute(hash, &error));
-       if (!padHash) {
-               goto out;
-       }
-       (void)transforms_assume(hLen == CFDataGetLength(padHash));
-
-       // (5) Concatenate pHash,PS, the message M, and other padding to form a data block DB as DB = pHash∥PS∥01∥M.
-       dataBlob = CFDataCreateMutable(NULL, CFDataGetLength(padHash) + padLen + 1 + CFDataGetLength(dataValue));
-       if (!dataBlob) {
-               error = GetNoMemoryErrorAndRetain();
-               goto out;
-       }
-       CFDataAppendBytes(dataBlob, CFDataGetBytePtr(padHash), hLen);
-       CFDataAppendBytes(dataBlob, raw_padZeros, padLen);
-       CFDataAppendBytes(dataBlob, (UInt8*)"\01", 1);
-       CFDataAppendBytes(dataBlob, CFDataGetBytePtr(dataValue), CFDataGetLength(dataValue));
-
-       // (6) Generate a random octet string seed of length hLen.
-       seed = (CFDataRef)this->GetAttribute(CFSTR("FixedSeedForOAEPTesting"));
-       raw_seed = NULL;
-       if (seed) {
-               raw_seed = (UInt8*)CFDataGetBytePtr(seed);
-               (void)transforms_assume(hLen == CFDataGetLength(seed));
-               CFRetain(seed);
-       } else {
-               raw_seed = (UInt8*)malloc(hLen);
-               if (!raw_seed) {
-                       error = GetNoMemoryErrorAndRetain();
-                       goto out;
-               }
-               SecRandomCopyBytes(kSecRandomDefault, hLen, raw_seed);
-               seed = CFDataCreateWithBytesNoCopy(NULL, raw_seed, hLen, kCFAllocatorMalloc);
-               if (!seed) {
-                       free(raw_seed);
-                       error = GetNoMemoryErrorAndRetain();
-               }
-       }
-
-       // (7) Let dbMask = MGF (seed, emLen − hLen).
-       mgf_dbMask = transforms_assume(SecCreateMaskGenerationFunctionTransform(hashAlgo, desired_message_length - hLen, &error));
-       if (!mgf_dbMask) {
-               goto out;
-       }
-       if (!SecTransformSetAttribute(mgf_dbMask, kSecTransformInputAttributeName, seed, &error)) {
-               goto out;
-       }
-       dbMask = (CFDataRef)SecTransformExecute(mgf_dbMask, &error);
-
-       // (8) Let maskedDB = DB ⊕ dbMask.
-       // NOTE: we do some allocations above...you know, we should be able to malloc ONE buffer of the
-       // proper size.
-       raw_maskedDB = (UInt8 *)malloc(CFDataGetLength(dbMask));
-       if (!raw_maskedDB) {
-               error = GetNoMemoryErrorAndRetain();
-               goto out;
-       }
-       xor_bytes(raw_maskedDB, CFDataGetBytePtr(dbMask), CFDataGetBytePtr(dataBlob), CFDataGetLength(dbMask));
-       maskedDB = CFDataCreateWithBytesNoCopy(NULL, raw_maskedDB, CFDataGetLength(dataBlob), kCFAllocatorMalloc);
-       if (!maskedDB) {
-               free(raw_maskedDB);
-               error = GetNoMemoryErrorAndRetain();
-               goto out;
-       }
-
-       // (9) Let seedMask = MGF(maskedDB, hLen).
-       mgf_seedMask = transforms_assume(SecCreateMaskGenerationFunctionTransform(hashAlgo, hLen, &error));
-       if (!mgf_seedMask) {
-               goto out;
-       }
-       if (!SecTransformSetAttribute(mgf_seedMask, kSecTransformInputAttributeName, maskedDB, &error)) {
-               goto out;
-       }
-       seedMask = transforms_assume((CFDataRef)SecTransformExecute(mgf_seedMask, &error));
-       if (!seedMask) {
-               goto out;
-       }
-
-       // (10) Let maskedSeed = seed ⊕ seedMask
-       raw_maskedSeed = (UInt8 *)malloc(hLen);
-       if (!raw_maskedSeed) {
-               error = GetNoMemoryErrorAndRetain();
-               goto out;
-       }
-       xor_bytes(raw_maskedSeed, raw_seed, CFDataGetBytePtr(seedMask), hLen);
-
-       // (11) Let EM = maskedSeed∥maskedDB (if we didn't have to pushback the NULL we could do this without physically concatanating)
-       // (figure out amount of leading zero padding we need)
-       RSA_size.SizeInputBlock = hLen + CFDataGetLength(maskedDB);
-       CSSM_QuerySize(m_handle, CSSM_TRUE, 1, &RSA_size);
-       paddingNeeded = RSA_size.SizeOutputBlock - RSA_size.SizeInputBlock;
-       (void)transforms_assume(paddingNeeded >= 0);
-
-       EM = CFDataCreateMutable(NULL, CFDataGetLength(maskedDB) + hLen + paddingNeeded);
-       if (!EM) {
-               error = GetNoMemoryErrorAndRetain();
-               goto out;
-       }
-       while(paddingNeeded--) {
-               CFDataAppendBytes(EM, (UInt8*)"", 1);
-       }
-
-       CFDataAppendBytes(EM, raw_maskedSeed, hLen);
-       CFDataAppendBytes(EM, raw_maskedDB, CFDataGetLength(maskedDB));
-out:
-       if (error) {
-               SetAttributeNoCallback(kSecTransformOutputAttributeName, error);
-               (void)transforms_assume_zero(EM);
-       }
-
-       CFSafeRelease(seed); // via get??
-       CFSafeRelease(dbMask);
-       CFSafeRelease(maskedDB);
-       CFSafeRelease(seedMask);
-       CFSafeRelease(padHash);
-       CFSafeRelease(padZeros);
-       CFSafeRelease(EncodingParameters);
-       CFSafeRelease(dataBlob);
-       // desired_message_length_cf -- via get
-       // hashAlgo -- via get
-       CFSafeRelease(mgf_dbMask);
-       CFSafeRelease(mgf_seedMask);
-       CFSafeRelease(hash);
-       // raw_* are all freed by their associated CFDatas, except raw_maskedSeed
-       free(raw_maskedSeed);
-
-       // (12) Output EM.
-       return EM;
-#endif
-}
-
-/* --------------------------------------------------------------------------
- method:               AttributeChanged
- description:  deal with input
- -------------------------------------------------------------------------- */
-void EncryptDecryptBase::AttributeChanged(SecTransformAttributeRef ah, CFTypeRef value)
-{
-       // sanity check our arguments
-       if (ah != inputAH)
-       {
-               return; // we only deal with input
-       }
-
-       if (value != NULL)
-       {
-               CFTypeID valueType = CFGetTypeID(value);
-               if (valueType != CFDataGetTypeID())
-               {
-                       CFStringRef realType = CFCopyTypeIDDescription(valueType);
-                       CFErrorRef error = CreateSecTransformErrorRef(kSecTransformErrorNotInitializedCorrectly, "Value is not a CFDataRef -- this one is a %@", realType);
-                       CFRelease(realType);
-                       SetAttributeNoCallback(kSecTransformOutputAttributeName, error);
-                       return;
-               }
-
-               if (m_forEncryption && m_accumulator) {
-                       CFDataRef d = (CFDataRef)value;
-                       CFDataAppendBytes(m_accumulator, CFDataGetBytePtr(d), CFDataGetLength(d));
-                       return;
-               }
-       }
-
-       if (m_forEncryption && m_accumulator) {
-               (void)transforms_assume_zero(value);
-               value = m_accumulator;
-               m_accumulator = NULL;
-               dispatch_async(this->mDispatchQueue, ^{
-                       CFSafeRelease(value);
-               });
-               this->Pushback(inputAH, NULL);
-
-        if (m_oaep_padding) {
-                       value = apply_oaep_padding((CFDataRef)value);
-                       dispatch_async(this->mDispatchQueue, ^{
-                               CFSafeRelease(value);
-                       });
-        }
-       }
-
-       // add the input to our cryptor
-       CFDataRef valueRef = (CFDataRef) value;
-       CSSM_RETURN     crtn = CSSM_OK;
-       Boolean inFinal = FALSE;
-
-       if (valueRef != NULL)
-       {
-               // Convert to A CSSM_DATA
-               CSSM_DATA dataStruct;
-               dataStruct.Length = CFDataGetLength(valueRef);
-        dataStruct.Data = const_cast<uint8_t*>(CFDataGetBytePtr(valueRef));
-
-               CSSM_DATA intermediateDataStruct;
-               memset(&intermediateDataStruct, 0, sizeof(intermediateDataStruct));
-
-               CSSM_SIZE bytesProcessed = 0;
-
-               if (m_forEncryption)
-               {
-                       crtn = CSSM_EncryptDataUpdate(m_handle,
-                                                                                 &dataStruct,
-                                                                                 1,
-                                                                                 &intermediateDataStruct,
-                                                                                 1,
-                                                                                 &bytesProcessed);
-               }
-               else
-               {
-                       crtn = CSSM_DecryptDataUpdate(m_handle,
-                                                                                 &dataStruct,
-                                                                                 1,
-                                                                                 &intermediateDataStruct,
-                                                                                 1,
-                                                                                 &bytesProcessed);
-               }
-
-               if (CSSM_OK != crtn)
-               {
-                       SendCSSMError(crtn);
-                       return;
-               }
-
-
-               if (intermediateDataStruct.Length > 0)
-               {
-                       if (NULL == m_processedData)
-                       {
-                               m_processedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
-                       }
-
-                       CFDataAppendBytes(m_processedData, intermediateDataStruct.Data, bytesProcessed);
-                       free(intermediateDataStruct.Data);
-               }
-       }
-       else
-       {
-               // Finalize
-
-               inFinal = TRUE;
-               CSSM_DATA remData;
-               memset(&remData, 0, sizeof(remData));
-
-               crtn = (m_forEncryption) ? CSSM_EncryptDataFinal(m_handle, &remData) : CSSM_DecryptDataFinal(m_handle, &remData);
-
-               if (CSSM_OK == crtn)
-               {
-            if (m_forEncryption == false && m_accumulator) {
-                (void)transforms_assume_zero(m_processedData);
-                if (remData.Length > 0) {
-                    CFDataAppendBytes(m_accumulator, remData.Data, remData.Length);
-                }
-            } else {
-                if (NULL == m_processedData)
-                {
-                    m_processedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
-                }
-
-                if (remData.Length > 0)
-                {
-                    CFDataAppendBytes(m_processedData, remData.Data, remData.Length);
-                }
-            }
-               }
-
-               free(remData.Data);
-
-               if (CSSM_OK != crtn)
-               {
-                       SendCSSMError(crtn);
-                       return;
-               }
-       }
-
-       if (NULL != m_processedData)
-       {
-        SendAttribute(kSecTransformOutputAttributeName, m_processedData);
-               CFRelease(m_processedData);
-               m_processedData = NULL;
-       }
-
-       if (inFinal)
-       {
-        if (m_oaep_padding && m_forEncryption == false) {
-            CFTypeRef unpadded = remove_oaep_padding(m_accumulator);
-            SendAttribute(kSecTransformOutputAttributeName, unpadded);
-            CFRelease(unpadded);
-        }
-               SendAttribute(kSecTransformOutputAttributeName, NULL);
-       }
-
-
-}
-
-/* --------------------------------------------------------------------------
- method:               CopyState
- description:  Copy the current state of this transform
- -------------------------------------------------------------------------- */
-CFDictionaryRef EncryptDecryptBase::CopyState()
-{
-       // make a dictionary for our state
-       CFMutableDictionaryRef state = (CFMutableDictionaryRef) CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-       CFStringRef paddingStr = (CFStringRef) GetAttribute(kSecPaddingKey);
-       CFStringRef modeStr = (CFStringRef) GetAttribute (kSecEncryptionMode);
-       CFDataRef ivData = (CFDataRef) GetAttribute(kSecIVKey);
-       if (NULL != paddingStr)
-       {
-               CFDictionaryAddValue(state, kSecPaddingKey, paddingStr);
-       }
-
-       if (NULL != modeStr)
-       {
-               CFDictionaryAddValue(state, kSecEncryptionMode, modeStr);
-       }
-
-       if (NULL != ivData)
-       {
-               CFDictionaryAddValue(state, kSecIVKey, ivData);
-       }
-
-       return state;
-}
-
-/* --------------------------------------------------------------------------
- method:               RestoreState
- description:  Restore the state of this transform from a dictionary
- -------------------------------------------------------------------------- */
-void EncryptDecryptBase::RestoreState(CFDictionaryRef state)
-{
-       if (NULL == state)
-       {
-               return;
-       }
-
-       CFStringRef paddingStr = (CFStringRef)CFDictionaryGetValue(state, kSecPaddingKey);
-       CFStringRef modeStr = (CFStringRef)CFDictionaryGetValue(state, kSecEncryptionMode);
-       CFDataRef ivData = (CFDataRef)CFDictionaryGetValue(state, kSecIVKey);
-
-       if (NULL != paddingStr)
-       {
-               SetAttribute(kSecPaddingKey, paddingStr);
-       }
-
-       if (NULL != modeStr)
-       {
-               SetAttribute(kSecEncryptionMode, modeStr);
-       }
-
-       if (NULL != ivData)
-       {
-               SetAttribute(kSecIVKey, ivData);
-       }
-
-}
-
-/* --------------------------------------------------------------------------
- Implementation of the EncryptTransform
- -------------------------------------------------------------------------- */
-
-/* --------------------------------------------------------------------------
- method:               EncryptTransform (Constructor)
- description:  Make a new EncryptTransform
- -------------------------------------------------------------------------- */
-EncryptTransform::EncryptTransform() : EncryptDecryptBase(kEncryptTransformType)
-{
-}
-
-/* --------------------------------------------------------------------------
- method:               ~EncryptTransform (Destructor)
- description:  Clean up the memory of anEncryptTransform
- -------------------------------------------------------------------------- */
-EncryptTransform::~EncryptTransform()
-{
-}
-
-/* --------------------------------------------------------------------------
- method:               [static] Make
- description:  Make a new instance of this class
- -------------------------------------------------------------------------- */
-SecTransformRef EncryptTransform::Make()
-{
-       EncryptTransform* tr = new EncryptTransform();
-       SecTransformRef str = (SecTransformRef) CoreFoundationHolder::MakeHolder(kEncryptTransformType, tr);
-       return str;
-}
-
-/* --------------------------------------------------------------------------
- Interface and implementation of the EncryptTransformFactory
- -------------------------------------------------------------------------- */
-
-class EncryptTransformFactory : public TransformFactory
-{
-public:
-       EncryptTransformFactory();
-       CFTypeRef Make();
-};
-
-
-/* --------------------------------------------------------------------------
- method:               EncryptTransformFactory (Constructor)
- description:
- -------------------------------------------------------------------------- */
-EncryptTransformFactory::EncryptTransformFactory() :
-TransformFactory(kEncryptTransformType)
-{}
-
-
-/* --------------------------------------------------------------------------
- method:               MakeTransformFactory
- description:  Make an instance of this factory class
- -------------------------------------------------------------------------- */
-TransformFactory* EncryptTransform::MakeTransformFactory()
-{
-       return new EncryptTransformFactory;
-}
-
-/* --------------------------------------------------------------------------
- method:               Make
- description:  Create an instance of this class
- -------------------------------------------------------------------------- */
-CFTypeRef EncryptTransformFactory::Make()
-{
-       return EncryptTransform::Make();
-}
-
-
-/* --------------------------------------------------------------------------
- method:               DecryptTransform (Constructor)
- description:  Make a new DecryptTransform
- -------------------------------------------------------------------------- */
-DecryptTransform::DecryptTransform() : EncryptDecryptBase(kDecryptTransformType)
-{
-}
-
-/* --------------------------------------------------------------------------
- method:               ~DecryptTransform (Destructor)
- description:  Clean up the memory of anDecryptTransform
- -------------------------------------------------------------------------- */
-DecryptTransform::~DecryptTransform()
-{
-}
-
-
-/* --------------------------------------------------------------------------
- method:               [static] Make
- description:  Make a new instance of this class
- -------------------------------------------------------------------------- */
-SecTransformRef DecryptTransform::Make()
-{
-       DecryptTransform* tr = new DecryptTransform();
-       SecTransformRef str = (SecTransformRef) CoreFoundationHolder::MakeHolder(kDecryptTransformType, tr);
-       return str;
-}
-
-/* --------------------------------------------------------------------------
- Interface and implementation of the DecryptTransformFactory
- -------------------------------------------------------------------------- */
-
-class DecryptTransformFactory : public TransformFactory
-{
-public:
-       DecryptTransformFactory();
-       CFTypeRef Make();
-};
-
-
-/* --------------------------------------------------------------------------
- method:               DecryptTransformFactory (Constructor)
- description:
- -------------------------------------------------------------------------- */
-DecryptTransformFactory::DecryptTransformFactory() :
-TransformFactory(kDecryptTransformType)
-{}
-
-
-/* --------------------------------------------------------------------------
- method:               MakeTransformFactory
- description:  Make an instance of this factory class
- -------------------------------------------------------------------------- */
-TransformFactory* DecryptTransform::MakeTransformFactory()
-{
-       return new DecryptTransformFactory;
-}
-
-/* --------------------------------------------------------------------------
- method:               Make
- description:  Create an instance of this class
- -------------------------------------------------------------------------- */
-CFTypeRef DecryptTransformFactory::Make()
-{
-       return DecryptTransform::Make();
-}
-